您的位置:首页 > 其它

ThemeChooser---debug  (5.1)

2016-04-27 16:59 169 查看
private ThemeManager mService;
mService = (ThemeManager) getActivity().getSystemService(Context.THEME_SERVICE);


得到ThemeManager类, 该类里包含了服务接口IThemeService;


ThemeManager类: /frameworks/base/core/java/android/content/res/ThemeManager.java

public ThemeManager(Context context, IThemeService service) {
mContext = context;
mService = service; //private IThemeService mService;
mHandler = new Handler(Looper.getMainLooper());
}


前面我们得到了mService(ThemeManager), 这里mService调用requestThemeChange方法。

ThemeChangeRequest request = getThemeChangeRequestForSelectedComponents();
mService.requestThemeChange(request, true);


我们先来看下ThemeChangeRequest类: /frameworks/base/core/java/android/content/res/ThemeChangeRequest.java

public final class ThemeChangeRequest implements Parcelable {
private final Map<String, String> mThemeComponents = new HashMap<String, String>();//保存组件信息
private final Map<String, String> mPerAppOverlays = new HashMap<String, String>();
.
.
.
}


我们可以看到该类实现了Parcelable接口, ThemeChangeRequest作为传输对象


现在我们来看下ThemeManager: /frameworks/base/core/java/android/content/res/ThemeManager.java

public class ThemeManager {
.
.
.
private IThemeService mService;
public void requestThemeChange(ThemeChangeRequest request, boolean removePerAppThemes) {
try {
mService.requestThemeChange(request, removePerAppThemes);
} catch (RemoteException e) {
logThemeServiceException(e);
}
}
.
.
.
}


我们可以看到该方法里实际是调用了IThemeService接口的requestThemeChange方法, 现在我们来看下该接口

IThemeService接口: 该接口是用aidl实现的,让我们来看下该aidl文件: IThemeService.aidl : /frameworks/base/core/java/android/content/res/IThemeService.aidl

interface IThemeService {
void requestThemeChangeUpdates(in IThemeChangeListener listener);
void removeUpdates(in IThemeChangeListener listener);

void requestThemeChange(in ThemeChangeRequest request, boolean removePerAppThemes);
void applyDefaultTheme();
boolean isThemeApplying();
int getProgress();

boolean cacheComposedIcon(in Bitmap icon, String path);

boolean processThemeResources(String themePkgName);
boolean isThemeBeingProcessed(String themePkgName);
void registerThemeProcessingListener(in IThemeProcessingListener listener);
void unregisterThemeProcessingListener(in IThemeProcessingListener listener);

void rebuildResourceCache();
}


我们再来看下实现了该接口的ThemeService类: /frameworks/base/services/core/java/com/android/server/ThemeService.java

public class ThemeService extends IThemeService.Stub {
.
.
.
@Override
public void requestThemeChange(ThemeChangeRequest request, boolean removePerAppThemes)
throws RemoteException {
mContext.enforceCallingOrSelfPermission(
Manifest.permission.ACCESS_THEME_MANAGER, null); //获得权限
Message msg;
/**
* Since the ThemeService handles compiling theme resource we need to make sure that any
* of the components we are trying to apply are either already processed or put to the
* front of the queue and handled before the theme change takes place.
*
* TODO: create a callback that can be sent to any ThemeChangeListeners to notify them that
* the theme will be applied once the processing is done.
*/
synchronized (mThemesToProcessQueue) {
Map<String, String> componentMap = request.getThemeComponentsMap();
for (Object key : componentMap.keySet()) {
if (ThemesColumns.MODIFIES_OVERLAYS.equals(key) ||
ThemesColumns.MODIFIES_NAVIGATION_BAR.equals(key) ||
ThemesColumns.MODIFIES_STATUS_BAR.equals(key) ||
ThemesColumns.MODIFIES_ICONS.equals(key)) {
String pkgName = (String) componentMap.get(key);
if (mThemesToProcessQueue.indexOf(pkgName) > 0) {
mThemesToProcessQueue.remove(pkgName);
mThemesToProcessQueue.add(0, pkgName);
// We want to make sure these resources are taken care of first so
// send the dequeue message and place it in the front of the queue
msg = mResourceProcessingHandler.obtainMessage(
ResourceProcessingHandler.MESSAGE_DEQUEUE_AND_PROCESS_THEME); //private ResourceProcessingHandler mResourceProcessingHandler;
mResourceProcessingHandler.sendMessageAtFrontOfQueue(msg);
}
}
}
}
msg = Message.obtain();
msg.what = ThemeWorkerHandler.MESSAGE_CHANGE_THEME;
msg.obj = request;
msg.arg1 = removePerAppThemes ? 1 : 0;
mHandler.sendMessage(msg);
}
.....
}


我们来看下ResourceProcessingHandler类:

private class ResourceProcessingHandler extends Handler {
private static final int MESSAGE_QUEUE_THEME_FOR_PROCESSING = 3;
private static final int MESSAGE_DEQUEUE_AND_PROCESS_THEME = 4;

public ResourceProcessingHandler(Looper looper) {
super(looper);
}

@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_QUEUE_THEME_FOR_PROCESSING:
String pkgName = (String) msg.obj;
synchronized (mThemesToProcessQueue) {
if (!mThemesToProcessQueue.contains(pkgName)) {
if (DEBUG) Log.d(TAG, "Adding " + pkgName + " for processing");
mThemesToProcessQueue.add(pkgName);
if (mThemesToProcessQueue.size() == 1) {
this.sendEmptyMessage(MESSAGE_DEQUEUE_AND_PROCESS_THEME);
}
}
}
break;
case MESSAGE_DEQUEUE_AND_PROCESS_THEME:
synchronized (mThemesToProcessQueue) {
pkgName = mThemesToProcessQueue.get(0);
}
if (pkgName != null) {
if (DEBUG) Log.d(TAG, "Processing " + pkgName);
String name;
try {
PackageInfo pi = mPM.getPackageInfo(pkgName, 0);
name = getThemeName(pi);
} catch (PackageManager.NameNotFoundException e) {
name = null;
}

int result = mPM.processThemeResources(pkgName);
if (result < 0) {
postFailedThemeInstallNotification(name != null ? name : pkgName);
}
sendThemeResourcesCachedBroadcast(pkgName, result);

synchronized (mThemesToProcessQueue) {
mThemesToProcessQueue.remove(0);
if (mThemesToProcessQueue.size() > 0 &&
!hasMessages(MESSAGE_DEQUEUE_AND_PROCESS_THEME)) {
this.sendEmptyMessage(MESSAGE_DEQUEUE_AND_PROCESS_THEME);
}
}
postFinishedProcessing(pkgName);
}
break;
default:
Log.w(TAG, "Unknown message " + msg.what);
break;
}
}
}


另一个处理类:ThemeWorkerHandler

private class ThemeWorkerHandler extends Handler {
private static final int MESSAGE_CHANGE_THEME = 1;
private static final int MESSAGE_APPLY_DEFAULT_THEME = 2;
private static final int MESSAGE_REBUILD_RESOURCE_CACHE = 3;

public ThemeWorkerHandler(Looper looper) {
super(looper);
}

@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_CHANGE_THEME:
final ThemeChangeRequest request = (ThemeChangeRequest) msg.obj;
doApplyTheme(request, msg.arg1 == 1);
break;
case MESSAGE_APPLY_DEFAULT_THEME:
doApplyDefaultTheme();
break;
case MESSAGE_REBUILD_RESOURCE_CACHE:
doRebuildResourceCache();
break;
default:
Log.w(TAG, "Unknown message " + msg.what);
break;
}
}
}


我们再来看下doApplyTheme方法:

private void doApplyTheme(ThemeChangeRequest request, boolean removePerAppTheme) {
if (request == null || request.getNumChangesRequested() == 0) {
postFinish(true, request, 0);
return;
}
.
.
.
if (request.getIconsThemePackageName() != null) {
updateIcons(request.getIconsThemePackageName());
incrementProgress(progressIncrement);
}

if (request.getWallpaperThemePackageName() != null) {
if (updateWallpaper(request.getWallpaperThemePackageName(),
request.getWallpaperId())) {
mWallpaperChangedByUs = true;
}
incrementProgress(progressIncrement);
}

.
.
.
postFinish(true, request, updateTime);
mIsThemeApplying = false;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: