diff options
Diffstat (limited to 'sdk/src/java/cyanogenmod/themes')
6 files changed, 821 insertions, 0 deletions
diff --git a/sdk/src/java/cyanogenmod/themes/IThemeChangeListener.aidl b/sdk/src/java/cyanogenmod/themes/IThemeChangeListener.aidl new file mode 100644 index 0000000..0700eb6 --- /dev/null +++ b/sdk/src/java/cyanogenmod/themes/IThemeChangeListener.aidl @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2014-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. + */ + +package cyanogenmod.themes; + +/** {@hide} */ +oneway interface IThemeChangeListener { + void onProgress(int progress); + void onFinish(boolean isSuccess); +} diff --git a/sdk/src/java/cyanogenmod/themes/IThemeProcessingListener.aidl b/sdk/src/java/cyanogenmod/themes/IThemeProcessingListener.aidl new file mode 100644 index 0000000..648e1a9 --- /dev/null +++ b/sdk/src/java/cyanogenmod/themes/IThemeProcessingListener.aidl @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2014-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. + */ + +package cyanogenmod.themes; + +/** {@hide} */ +oneway interface IThemeProcessingListener { + void onFinishedProcessing(String pkgName); +} diff --git a/sdk/src/java/cyanogenmod/themes/IThemeService.aidl b/sdk/src/java/cyanogenmod/themes/IThemeService.aidl new file mode 100644 index 0000000..fa186e9 --- /dev/null +++ b/sdk/src/java/cyanogenmod/themes/IThemeService.aidl @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2014-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. + */ + +package cyanogenmod.themes; + +import cyanogenmod.themes.IThemeChangeListener; +import cyanogenmod.themes.IThemeProcessingListener; +import cyanogenmod.themes.ThemeChangeRequest; + +import java.util.Map; + +/** {@hide} */ +interface IThemeService { + oneway void requestThemeChangeUpdates(in IThemeChangeListener listener); + oneway void removeUpdates(in IThemeChangeListener listener); + + oneway void requestThemeChange(in ThemeChangeRequest request, boolean removePerAppThemes); + oneway void applyDefaultTheme(); + boolean isThemeApplying(); + int getProgress(); + + boolean processThemeResources(String themePkgName); + boolean isThemeBeingProcessed(String themePkgName); + oneway void registerThemeProcessingListener(in IThemeProcessingListener listener); + oneway void unregisterThemeProcessingListener(in IThemeProcessingListener listener); + + oneway void rebuildResourceCache(); + + long getLastThemeChangeTime(); + int getLastThemeChangeRequestType(); +} diff --git a/sdk/src/java/cyanogenmod/themes/ThemeChangeRequest.aidl b/sdk/src/java/cyanogenmod/themes/ThemeChangeRequest.aidl new file mode 100644 index 0000000..e1d9e4f --- /dev/null +++ b/sdk/src/java/cyanogenmod/themes/ThemeChangeRequest.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2015-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. + */ + +package cyanogenmod.themes; + +parcelable ThemeChangeRequest; diff --git a/sdk/src/java/cyanogenmod/themes/ThemeChangeRequest.java b/sdk/src/java/cyanogenmod/themes/ThemeChangeRequest.java new file mode 100644 index 0000000..f8eeeb5 --- /dev/null +++ b/sdk/src/java/cyanogenmod/themes/ThemeChangeRequest.java @@ -0,0 +1,322 @@ +/* + * Copyright (C) 2015-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. + */ +package cyanogenmod.themes; + +import android.content.pm.ThemeUtils; +import android.content.res.ThemeConfig; +import android.os.Parcel; +import android.os.Parcelable; + +import cyanogenmod.os.Concierge; +import cyanogenmod.os.Concierge.ParcelInfo; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import static cyanogenmod.providers.ThemesContract.ThemesColumns.*; + +public final class ThemeChangeRequest implements Parcelable { + public static final int DEFAULT_WALLPAPER_ID = -1; + + private final Map<String, String> mThemeComponents = new HashMap<>(); + private final Map<String, String> mPerAppOverlays = new HashMap<>(); + private RequestType mRequestType; + private long mWallpaperId = -1; + + public String getOverlayThemePackageName() { + return getThemePackageNameForComponent(MODIFIES_OVERLAYS); + } + + public String getStatusBarThemePackageName() { + return getThemePackageNameForComponent(MODIFIES_STATUS_BAR); + } + + public String getNavBarThemePackageName() { + return getThemePackageNameForComponent(MODIFIES_NAVIGATION_BAR); + } + + public String getFontThemePackageName() { + return getThemePackageNameForComponent(MODIFIES_FONTS); + } + + public String getIconsThemePackageName() { + return getThemePackageNameForComponent(MODIFIES_ICONS); + } + + public String getBootanimationThemePackageName() { + return getThemePackageNameForComponent(MODIFIES_BOOT_ANIM); + } + + public String getWallpaperThemePackageName() { + return getThemePackageNameForComponent(MODIFIES_LAUNCHER); + } + + public String getLockWallpaperThemePackageName() { + return getThemePackageNameForComponent(MODIFIES_LOCKSCREEN); + } + + public String getAlarmThemePackageName() { + return getThemePackageNameForComponent(MODIFIES_ALARMS); + } + + public String getNotificationThemePackageName() { + return getThemePackageNameForComponent(MODIFIES_NOTIFICATIONS); + } + + public String getRingtoneThemePackageName() { + return getThemePackageNameForComponent(MODIFIES_RINGTONES); + } + + public String getLiveLockScreenThemePackageName() { + return getThemePackageNameForComponent(MODIFIES_LIVE_LOCK_SCREEN); + } + + public final Map<String, String> getThemeComponentsMap() { + return Collections.unmodifiableMap(mThemeComponents); + } + + public long getWallpaperId() { + return mWallpaperId; + } + + /** + * Get the mapping for per app themes + * @return A mapping of apps and the theme to apply for each one. or null if none set. + */ + public final Map<String, String> getPerAppOverlays() { + return Collections.unmodifiableMap(mPerAppOverlays); + } + + public int getNumChangesRequested() { + return mThemeComponents.size() + mPerAppOverlays.size(); + } + + public RequestType getReqeustType() { + return mRequestType; + } + + private String getThemePackageNameForComponent(String componentName) { + return mThemeComponents.get(componentName); + } + + private ThemeChangeRequest(Map<String, String> components, Map<String, String> perAppThemes, + RequestType requestType, long wallpaperId) { + if (components != null) { + mThemeComponents.putAll(components); + } + if (perAppThemes != null) { + mPerAppOverlays.putAll(perAppThemes); + } + mRequestType = requestType; + mWallpaperId = wallpaperId; + } + + private ThemeChangeRequest(Parcel source) { + // Read parcelable version via the Concierge + ParcelInfo parcelInfo = Concierge.receiveParcel(source); + int parcelableVersion = parcelInfo.getParcelVersion(); + + int numComponents = source.readInt(); + for (int i = 0; i < numComponents; i++) { + mThemeComponents.put(source.readString(), source.readString()); + } + + numComponents = source.readInt(); + for (int i = 0 ; i < numComponents; i++) { + mPerAppOverlays.put(source.readString(), source.readString()); + } + mRequestType = RequestType.values()[source.readInt()]; + mWallpaperId = source.readLong(); + + // Complete parcel info for the concierge + parcelInfo.complete(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + // Tell the concierge to prepare the parcel + ParcelInfo parcelInfo = Concierge.prepareParcel(dest); + + dest.writeInt(mThemeComponents.size()); + for (String component : mThemeComponents.keySet()) { + dest.writeString(component); + dest.writeString(mThemeComponents.get(component)); + } + dest.writeInt((mPerAppOverlays.size())); + for (String appPkgName : mPerAppOverlays.keySet()) { + dest.writeString(appPkgName); + dest.writeString(mPerAppOverlays.get(appPkgName)); + } + dest.writeInt(mRequestType.ordinal()); + dest.writeLong(mWallpaperId); + + // Complete the parcel info for the concierge + parcelInfo.complete(); + } + + public static final Parcelable.Creator<ThemeChangeRequest> CREATOR = + new Parcelable.Creator<ThemeChangeRequest>() { + @Override + public ThemeChangeRequest createFromParcel(Parcel source) { + return new ThemeChangeRequest(source); + } + + @Override + public ThemeChangeRequest[] newArray(int size) { + return new ThemeChangeRequest[size]; + } + }; + + public enum RequestType { + USER_REQUEST, + USER_REQUEST_MIXNMATCH, + THEME_UPDATED, + THEME_REMOVED, + THEME_RESET + } + + public static class Builder { + Map<String, String> mThemeComponents = new HashMap<>(); + Map<String, String> mPerAppOverlays = new HashMap<>(); + RequestType mRequestType = RequestType.USER_REQUEST; + long mWallpaperId; + + public Builder() {} + + public Builder(ThemeConfig themeConfig) { + if (themeConfig != null) { + buildChangeRequestFromThemeConfig(themeConfig); + } + } + + public Builder setOverlay(String pkgName) { + return setComponent(MODIFIES_OVERLAYS, pkgName); + } + + public Builder setStatusBar(String pkgName) { + return setComponent(MODIFIES_STATUS_BAR, pkgName); + } + + public Builder setNavBar(String pkgName) { + return setComponent(MODIFIES_NAVIGATION_BAR, pkgName); + } + + public Builder setFont(String pkgName) { + return setComponent(MODIFIES_FONTS, pkgName); + } + + public Builder setIcons(String pkgName) { + return setComponent(MODIFIES_ICONS, pkgName); + } + + public Builder setBootanimation(String pkgName) { + return setComponent(MODIFIES_BOOT_ANIM, pkgName); + } + + public Builder setWallpaper(String pkgName) { + return setComponent(MODIFIES_LAUNCHER, pkgName); + } + + // Used in the case that more than one wallpaper exists for a given pkg name + public Builder setWallpaperId(long id) { + mWallpaperId = id; + return this; + } + + public Builder setLockWallpaper(String pkgName) { + return setComponent(MODIFIES_LOCKSCREEN, pkgName); + } + + public Builder setAlarm(String pkgName) { + return setComponent(MODIFIES_ALARMS, pkgName); + } + + public Builder setNotification(String pkgName) { + return setComponent(MODIFIES_NOTIFICATIONS, pkgName); + } + + public Builder setRingtone(String pkgName) { + return setComponent(MODIFIES_RINGTONES, pkgName); + } + + public Builder setLiveLockScreen(String pkgName) { + return setComponent(MODIFIES_LIVE_LOCK_SCREEN, pkgName); + } + + public Builder setComponent(String component, String pkgName) { + if (pkgName != null) { + mThemeComponents.put(component, pkgName); + } else { + mThemeComponents.remove(component); + } + return this; + } + + public Builder setAppOverlay(String appPkgName, String themePkgName) { + if (appPkgName != null) { + if (themePkgName != null) { + mPerAppOverlays.put(appPkgName, themePkgName); + } else { + mPerAppOverlays.remove(appPkgName); + } + } + + return this; + } + + public Builder setRequestType(RequestType requestType) { + mRequestType = requestType != null ? requestType : RequestType.USER_REQUEST; + return this; + } + + public ThemeChangeRequest build() { + return new ThemeChangeRequest(mThemeComponents, mPerAppOverlays, + mRequestType, mWallpaperId); + } + + private void buildChangeRequestFromThemeConfig(ThemeConfig themeConfig) { + if (themeConfig.getFontPkgName() != null) { + this.setFont(themeConfig.getFontPkgName()); + } + if (themeConfig.getIconPackPkgName() != null) { + this.setIcons(themeConfig.getIconPackPkgName()); + } + if (themeConfig.getOverlayPkgName() != null) { + this.setOverlay(themeConfig.getOverlayPkgName()); + } + if (themeConfig.getOverlayForStatusBar() != null) { + this.setStatusBar(themeConfig.getOverlayForStatusBar()); + } + if (themeConfig.getOverlayForNavBar() != null) { + this.setNavBar(themeConfig.getOverlayForNavBar()); + } + + // Check if there are any per-app overlays using this theme + final Map<String, ThemeConfig.AppTheme> themes = themeConfig.getAppThemes(); + for (String appPkgName : themes.keySet()) { + if (ThemeUtils.isPerAppThemeComponent(appPkgName)) { + this.setAppOverlay(appPkgName, themes.get(appPkgName).getOverlayPkgName()); + } + } + } + } +} diff --git a/sdk/src/java/cyanogenmod/themes/ThemeManager.java b/sdk/src/java/cyanogenmod/themes/ThemeManager.java new file mode 100644 index 0000000..5fbbde7 --- /dev/null +++ b/sdk/src/java/cyanogenmod/themes/ThemeManager.java @@ -0,0 +1,391 @@ +/* + * Copyright (C) 2014-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. + */ + +package cyanogenmod.themes; + +import android.content.Context; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.ArraySet; +import android.util.Log; + +import cyanogenmod.app.CMContextConstants; +import cyanogenmod.themes.ThemeChangeRequest.RequestType; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Manages changing and applying of themes. + * <p>Get an instance of this class by calling blah blah blah</p> + */ +public class ThemeManager { + private static final String TAG = ThemeManager.class.getName(); + private static IThemeService sService; + private static ThemeManager sInstance; + private static Handler mHandler; + + private Set<ThemeChangeListener> mChangeListeners = new ArraySet<>(); + + private Set<ThemeProcessingListener> mProcessingListeners = new ArraySet<>(); + + private ThemeManager(Context context) { + sService = getService(); + if (context.getPackageManager().hasSystemFeature( + CMContextConstants.Features.THEMES) && sService == null) { + throw new RuntimeException("Unable to get ThemeManagerService. The service either" + + " crashed, was not started, or the interface has been called to early in" + + " SystemServer init"); + } + mHandler = new Handler(Looper.getMainLooper()); + } + + public static ThemeManager getInstance(Context context) { + if (sInstance == null) { + sInstance = new ThemeManager(context); + } + + return sInstance; + } + + /** @hide */ + public static IThemeService getService() { + if (sService != null) { + return sService; + } + IBinder b = ServiceManager.getService(CMContextConstants.CM_THEME_SERVICE); + if (b != null) { + sService = IThemeService.Stub.asInterface(b); + return sService; + } + return null; + } + + private final IThemeChangeListener mThemeChangeListener = new IThemeChangeListener.Stub() { + @Override + public void onProgress(final int progress) throws RemoteException { + mHandler.post(new Runnable() { + @Override + public void run() { + synchronized (mChangeListeners) { + List<ThemeChangeListener> listenersToRemove = new ArrayList<>(); + for (ThemeChangeListener listener : mChangeListeners) { + try { + listener.onProgress(progress); + } catch (Throwable e) { + Log.w(TAG, "Unable to update theme change progress", e); + listenersToRemove.add(listener); + } + } + if (listenersToRemove.size() > 0) { + for (ThemeChangeListener listener : listenersToRemove) { + mChangeListeners.remove(listener); + } + } + } + } + }); + } + + @Override + public void onFinish(final boolean isSuccess) throws RemoteException { + mHandler.post(new Runnable() { + @Override + public void run() { + synchronized (mChangeListeners) { + List<ThemeChangeListener> listenersToRemove = new ArrayList<>(); + for (ThemeChangeListener listener : mChangeListeners) { + try { + listener.onFinish(isSuccess); + } catch (Throwable e) { + Log.w(TAG, "Unable to update theme change listener", e); + listenersToRemove.add(listener); + } + } + if (listenersToRemove.size() > 0) { + for (ThemeChangeListener listener : listenersToRemove) { + mChangeListeners.remove(listener); + } + } + } + } + }); + } + }; + + private final IThemeProcessingListener mThemeProcessingListener = + new IThemeProcessingListener.Stub() { + @Override + public void onFinishedProcessing(final String pkgName) throws RemoteException { + mHandler.post(new Runnable() { + @Override + public void run() { + synchronized (mProcessingListeners) { + List<ThemeProcessingListener> listenersToRemove = new ArrayList<>(); + for (ThemeProcessingListener listener : mProcessingListeners) { + try { + listener.onFinishedProcessing(pkgName); + } catch (Throwable e) { + Log.w(TAG, "Unable to update theme change progress", e); + listenersToRemove.add(listener); + } + } + if (listenersToRemove.size() > 0) { + for (ThemeProcessingListener listener : listenersToRemove) { + mProcessingListeners.remove(listener); + } + } + } + } + }); + } + }; + + + /** + * @deprecated Use {@link ThemeManager#registerThemeChangeListener(ThemeChangeListener)} instead + */ + public void addClient(ThemeChangeListener listener) { + registerThemeChangeListener(listener); + } + + /** + * @deprecated Use {@link ThemeManager#unregisterThemeChangeListener(ThemeChangeListener)} + * instead + */ + public void removeClient(ThemeChangeListener listener) { + unregisterThemeChangeListener(listener); + } + + /** + * @deprecated Use {@link ThemeManager#unregisterThemeChangeListener(ThemeChangeListener)} + * instead + */ + public void onClientPaused(ThemeChangeListener listener) { + unregisterThemeChangeListener(listener); + } + + /** + * @deprecated Use {@link ThemeManager#registerThemeChangeListener(ThemeChangeListener)} instead + */ + public void onClientResumed(ThemeChangeListener listener) { + registerThemeChangeListener(listener); + } + + /** + * @deprecated Use {@link ThemeManager#unregisterThemeChangeListener(ThemeChangeListener)} + * instead + */ + public void onClientDestroyed(ThemeChangeListener listener) { + unregisterThemeChangeListener(listener); + } + + /** + * Register a {@link ThemeChangeListener} to be notified when a theme is done being processed. + * @param listener {@link ThemeChangeListener} to register + */ + public void registerThemeChangeListener(ThemeChangeListener listener) { + synchronized (mChangeListeners) { + if (mChangeListeners.contains(listener)) { + throw new IllegalArgumentException("Listener already registered"); + } + if (mChangeListeners.size() == 0) { + try { + sService.requestThemeChangeUpdates(mThemeChangeListener); + } catch (RemoteException e) { + Log.w(TAG, "Unable to register listener", e); + } + } + mChangeListeners.add(listener); + } + } + + /** + * Unregister a {@link ThemeChangeListener} + * @param listener {@link ThemeChangeListener} to unregister + */ + public void unregisterThemeChangeListener(ThemeChangeListener listener) { + synchronized (mChangeListeners) { + mChangeListeners.remove(listener); + if (mChangeListeners.size() == 0) { + try { + sService.removeUpdates(mThemeChangeListener); + } catch (RemoteException e) { + Log.w(TAG, "Unable to unregister listener", e); + } + } + } + } + + /** + * Register a {@link ThemeProcessingListener} to be notified when a theme is done being + * processed. + * @param listener {@link ThemeProcessingListener} to register + */ + public void registerProcessingListener(ThemeProcessingListener listener) { + synchronized (mProcessingListeners) { + if (mProcessingListeners.contains(listener)) { + throw new IllegalArgumentException("Listener already registered"); + } + if (mProcessingListeners.size() == 0) { + try { + sService.registerThemeProcessingListener(mThemeProcessingListener); + } catch (RemoteException e) { + Log.w(TAG, "Unable to register listener", e); + } + } + mProcessingListeners.add(listener); + } + } + + /** + * Unregister a {@link ThemeProcessingListener}. + * @param listener {@link ThemeProcessingListener} to unregister + */ + public void unregisterProcessingListener(ThemeProcessingListener listener) { + synchronized (mProcessingListeners) { + mProcessingListeners.remove(listener); + if (mProcessingListeners.size() == 0) { + try { + sService.unregisterThemeProcessingListener(mThemeProcessingListener); + } catch (RemoteException e) { + Log.w(TAG, "Unable to unregister listener", e); + } + } + } + } + + public void requestThemeChange(String pkgName, List<String> components) { + requestThemeChange(pkgName, components, true); + } + + public void requestThemeChange(String pkgName, List<String> components, + boolean removePerAppThemes) { + Map<String, String> componentMap = new HashMap<>(components.size()); + for (String component : components) { + componentMap.put(component, pkgName); + } + requestThemeChange(componentMap, removePerAppThemes); + } + + public void requestThemeChange(Map<String, String> componentMap) { + requestThemeChange(componentMap, true); + } + + public void requestThemeChange(Map<String, String> componentMap, boolean removePerAppThemes) { + ThemeChangeRequest.Builder builder = new ThemeChangeRequest.Builder(); + for (String component : componentMap.keySet()) { + builder.setComponent(component, componentMap.get(component)); + } + + requestThemeChange(builder.build(), removePerAppThemes); + } + + public void requestThemeChange(ThemeChangeRequest request, boolean removePerAppThemes) { + try { + sService.requestThemeChange(request, removePerAppThemes); + } catch (RemoteException e) { + logThemeServiceException(e); + } + } + + public void applyDefaultTheme() { + try { + sService.applyDefaultTheme(); + } catch (RemoteException e) { + logThemeServiceException(e); + } + } + + public boolean isThemeApplying() { + try { + return sService.isThemeApplying(); + } catch (RemoteException e) { + logThemeServiceException(e); + } + + return false; + } + + public boolean isThemeBeingProcessed(String themePkgName) { + try { + return sService.isThemeBeingProcessed(themePkgName); + } catch (RemoteException e) { + logThemeServiceException(e); + } + return false; + } + + public int getProgress() { + try { + return sService.getProgress(); + } catch (RemoteException e) { + logThemeServiceException(e); + } + return -1; + } + + public boolean processThemeResources(String themePkgName) { + try { + return sService.processThemeResources(themePkgName); + } catch (RemoteException e) { + logThemeServiceException(e); + } + return false; + } + + public long getLastThemeChangeTime() { + try { + return sService.getLastThemeChangeTime(); + } catch (RemoteException e) { + logThemeServiceException(e); + } + return 0; + } + + public ThemeChangeRequest.RequestType getLastThemeChangeRequestType() { + try { + int type = sService.getLastThemeChangeRequestType(); + return (type >= 0 && type < RequestType.values().length) + ? RequestType.values()[type] + : null; + } catch (RemoteException e) { + logThemeServiceException(e); + } + + return null; + } + + private void logThemeServiceException(Exception e) { + Log.w(TAG, "Unable to access ThemeService", e); + } + + public interface ThemeChangeListener { + void onProgress(int progress); + void onFinish(boolean isSuccess); + } + + public interface ThemeProcessingListener { + void onFinishedProcessing(String pkgName); + } +} + |