summaryrefslogtreecommitdiffstats
path: root/services/java
diff options
context:
space:
mode:
Diffstat (limited to 'services/java')
-rw-r--r--services/java/com/android/server/AppsLaunchFailureReceiver.java73
-rw-r--r--services/java/com/android/server/AssetRedirectionManagerService.java397
-rw-r--r--services/java/com/android/server/DeviceStorageMonitorService.java20
-rw-r--r--services/java/com/android/server/InputMethodManagerService.java18
-rwxr-xr-xservices/java/com/android/server/NotificationManagerService.java19
-rw-r--r--services/java/com/android/server/SystemServer.java18
-rw-r--r--services/java/com/android/server/ThrottleService.java17
-rw-r--r--services/java/com/android/server/UiModeManagerService.java20
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java49
-rw-r--r--services/java/com/android/server/connectivity/Tethering.java18
-rw-r--r--services/java/com/android/server/pm/PackageManagerService.java206
-rw-r--r--services/java/com/android/server/pm/Settings.java2
-rwxr-xr-xservices/java/com/android/server/wm/WindowManagerService.java25
13 files changed, 846 insertions, 36 deletions
diff --git a/services/java/com/android/server/AppsLaunchFailureReceiver.java b/services/java/com/android/server/AppsLaunchFailureReceiver.java
new file mode 100644
index 0000000..6ef07aa
--- /dev/null
+++ b/services/java/com/android/server/AppsLaunchFailureReceiver.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2010, T-Mobile USA, Inc.
+ *
+ * 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 com.android.server;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.content.res.CustomTheme;
+import android.util.Log;
+import android.app.ActivityManager;
+import android.os.SystemClock;
+
+public class AppsLaunchFailureReceiver extends BroadcastReceiver {
+
+ private static final int FAILURES_THRESHOLD = 5;
+ private static final int EXPIRATION_TIME_IN_MILLISECONDS = 30000; // 30 seconds
+
+ private int mFailuresCount = 0;
+ private long mStartTime = 0;
+
+ // This function implements the following logic.
+ // If after a theme was applied the number of application launch failures
+ // at any moment was equal to FAILURES_THRESHOLD
+ // in less than EXPIRATION_TIME_IN_MILLISECONDS
+ // the default theme is applied unconditionally.
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (action.equals(Intent.ACTION_APP_LAUNCH_FAILURE)) {
+ long currentTime = SystemClock.uptimeMillis();
+ if (currentTime - mStartTime > EXPIRATION_TIME_IN_MILLISECONDS) {
+ // reset both the count and the timer
+ mStartTime = currentTime;
+ mFailuresCount = 0;
+ }
+ if (mFailuresCount <= FAILURES_THRESHOLD) {
+ mFailuresCount++;
+ if (mFailuresCount == FAILURES_THRESHOLD) {
+ CustomTheme defaultTheme = CustomTheme.getSystemTheme();
+ ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
+ Configuration currentConfig = am.getConfiguration();
+ currentConfig.customTheme = new CustomTheme(
+ defaultTheme.getThemeId(),
+ defaultTheme.getThemePackageName());
+ am.updateConfiguration(currentConfig);
+ }
+ }
+ } else if (action.equals(Intent.ACTION_APP_LAUNCH_FAILURE_RESET)) {
+ mFailuresCount = 0;
+ mStartTime = SystemClock.uptimeMillis();
+ } else if (action.equals(Intent.ACTION_PACKAGE_ADDED) ||
+ action.equals(Intent.ACTION_PACKAGE_REMOVED)) {
+ mFailuresCount = 0;
+ mStartTime = SystemClock.uptimeMillis();
+ }
+ }
+
+}
diff --git a/services/java/com/android/server/AssetRedirectionManagerService.java b/services/java/com/android/server/AssetRedirectionManagerService.java
new file mode 100644
index 0000000..1e124b9
--- /dev/null
+++ b/services/java/com/android/server/AssetRedirectionManagerService.java
@@ -0,0 +1,397 @@
+package com.android.server;
+
+import com.android.internal.app.IAssetRedirectionManager;
+import com.android.internal.util.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ThemeInfo;
+import android.content.res.AssetManager;
+import android.content.res.PackageRedirectionMap;
+import android.content.res.Resources;
+import android.os.RemoteException;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+public class AssetRedirectionManagerService extends IAssetRedirectionManager.Stub {
+ private static final String TAG = "AssetRedirectionManager";
+
+ private final Context mContext;
+
+ /*
+ * TODO: This data structure should have some way to expire very old cache
+ * entries. Would be nice to optimize for the removal path as well.
+ */
+ private final HashMap<RedirectionKey, PackageRedirectionMap> mRedirections =
+ new HashMap<RedirectionKey, PackageRedirectionMap>();
+
+ public AssetRedirectionManagerService(Context context) {
+ mContext = context;
+ }
+
+ @Override
+ public void clearRedirectionMapsByTheme(String themePackageName, String themeId)
+ throws RemoteException {
+ synchronized (mRedirections) {
+ Set<RedirectionKey> keys = mRedirections.keySet();
+ Iterator<RedirectionKey> iter = keys.iterator();
+ while (iter.hasNext()) {
+ RedirectionKey key = iter.next();
+ if (themePackageName.equals(key.themePackageName) &&
+ (themeId == null || themeId.equals(key.themeId))) {
+ iter.remove();
+ }
+ }
+ }
+ }
+
+ @Override
+ public void clearPackageRedirectionMap(String targetPackageName) throws RemoteException {
+ synchronized (mRedirections) {
+ Set<RedirectionKey> keys = mRedirections.keySet();
+ Iterator<RedirectionKey> iter = keys.iterator();
+ while (iter.hasNext()) {
+ RedirectionKey key = iter.next();
+ if (targetPackageName.equals(key.targetPackageName)) {
+ iter.remove();
+ }
+ }
+ }
+ }
+
+ @Override
+ public PackageRedirectionMap getPackageRedirectionMap(String themePackageName,
+ String themeId, String targetPackageName) throws RemoteException {
+ synchronized (mRedirections) {
+ RedirectionKey key = new RedirectionKey();
+ key.themePackageName = themePackageName;
+ key.themeId = themeId;
+ key.targetPackageName = targetPackageName;
+
+ PackageRedirectionMap map = mRedirections.get(key);
+ if (map != null) {
+ return map;
+ } else {
+ map = generatePackageRedirectionMap(key);
+ if (map != null) {
+ mRedirections.put(key, map);
+ }
+ return map;
+ }
+ }
+ }
+
+ private PackageRedirectionMap generatePackageRedirectionMap(RedirectionKey key) {
+ AssetManager assets = new AssetManager();
+
+ boolean frameworkAssets = key.targetPackageName.equals("android");
+
+ if (!frameworkAssets) {
+ PackageInfo pi = getPackageInfo(mContext, key.targetPackageName);
+ if (pi == null || pi.applicationInfo == null ||
+ assets.addAssetPath(pi.applicationInfo.publicSourceDir) == 0) {
+ Log.w(TAG, "Unable to attach target package assets for " + key.targetPackageName);
+ return null;
+ }
+ }
+
+ PackageInfo pi = getPackageInfo(mContext, key.themePackageName);
+ if (pi == null || pi.applicationInfo == null || pi.themeInfos == null ||
+ assets.addAssetPath(pi.applicationInfo.publicSourceDir) == 0) {
+ Log.w(TAG, "Unable to attach theme package assets from " + key.themePackageName);
+ return null;
+ }
+
+ PackageRedirectionMap resMap = new PackageRedirectionMap();
+
+ /*
+ * Apply a special redirection hack for the highest level <style>
+ * replacing @android:style/Theme.
+ */
+ if (frameworkAssets) {
+ int themeResourceId = findThemeResourceId(pi.themeInfos, key.themeId);
+ assets.generateStyleRedirections(resMap.getNativePointer(), android.R.style.Theme,
+ themeResourceId);
+ }
+
+ Resources res = new Resources(assets, null, null);
+ generateExplicitRedirections(resMap, res, key.themePackageName, key.targetPackageName);
+
+ return resMap;
+ }
+
+ private void generateExplicitRedirections(PackageRedirectionMap resMap, Resources res,
+ String themePackageName, String targetPackageName) {
+ /*
+ * XXX: We should be parsing the <theme> tag's <meta-data>! Instead,
+ * we're just assuming that res/xml/<package>.xml exists and describes
+ * the redirects we want!
+ */
+ String redirectXmlName = targetPackageName.replace('.', '_');
+ int redirectXmlResId = res.getIdentifier(redirectXmlName, "xml", themePackageName);
+ if (redirectXmlResId == 0) {
+ return;
+ }
+
+ ResourceRedirectionsProcessor processor = new ResourceRedirectionsProcessor(res,
+ redirectXmlResId, themePackageName, targetPackageName, resMap);
+ processor.process();
+ }
+
+ private static PackageInfo getPackageInfo(Context context, String packageName) {
+ try {
+ return context.getPackageManager().getPackageInfo(packageName, 0);
+ } catch (NameNotFoundException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Searches for the high-level theme resource id for the specific
+ * &lt;theme&gt; tag being applied.
+ * <p>
+ * An individual theme package can contain multiple &lt;theme&gt; tags, each
+ * representing a separate theme choice from the user's perspective, even
+ * though the most common case is for there to be only 1.
+ *
+ * @return The style resource id or 0 if no match was found.
+ */
+ private static int findThemeResourceId(ThemeInfo[] themeInfos, String needle) {
+ if (themeInfos != null && !TextUtils.isEmpty(needle)) {
+ int n = themeInfos.length;
+ for (int i = 0; i < n; i++) {
+ ThemeInfo info = themeInfos[i];
+ if (needle.equals(info.themeId)) {
+ return info.styleResourceId;
+ }
+ }
+ }
+ return 0;
+ }
+
+ private static Resources getUnredirectedResourcesForPackage(Context context, String packageName) {
+ AssetManager assets = new AssetManager();
+
+ if (!packageName.equals("android")) {
+ PackageInfo pi = getPackageInfo(context, packageName);
+ if (pi == null || pi.applicationInfo == null ||
+ assets.addAssetPath(pi.applicationInfo.publicSourceDir) == 0) {
+ Log.w(TAG, "Unable to get resources for package " + packageName);
+ return null;
+ }
+ }
+
+ return new Resources(assets, null, null);
+ }
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ synchronized (mRedirections) {
+ final ArrayList<RedirectionKey> filteredKeySet = new ArrayList<RedirectionKey>();
+ for (Map.Entry<RedirectionKey, PackageRedirectionMap> entry: mRedirections.entrySet()) {
+ PackageRedirectionMap map = entry.getValue();
+ if (map != null && map.getPackageId() != -1) {
+ filteredKeySet.add(entry.getKey());
+ }
+ }
+ Collections.sort(filteredKeySet, new Comparator<RedirectionKey>() {
+ @Override
+ public int compare(RedirectionKey a, RedirectionKey b) {
+ int comp = a.themePackageName.compareTo(b.themePackageName);
+ if (comp != 0) {
+ return comp;
+ }
+ comp = a.themeId.compareTo(b.themeId);
+ if (comp != 0) {
+ return comp;
+ }
+ return a.targetPackageName.compareTo(b.targetPackageName);
+ }
+ });
+
+ pw.println("Theme asset redirections:");
+ String lastPackageName = null;
+ String lastId = null;
+ Resources themeRes = null;
+ for (RedirectionKey key: filteredKeySet) {
+ if (lastPackageName == null || !lastPackageName.equals(key.themePackageName)) {
+ pw.println("* Theme package " + key.themePackageName + ":");
+ lastPackageName = key.themePackageName;
+ themeRes = getUnredirectedResourcesForPackage(mContext, key.themePackageName);
+ }
+ if (lastId == null || !lastId.equals(key.themeId)) {
+ pw.println(" theme id #" + key.themeId + ":");
+ lastId = key.themeId;
+ }
+ pw.println(" " + key.targetPackageName + ":");
+ Resources targetRes = getUnredirectedResourcesForPackage(mContext, key.targetPackageName);
+ PackageRedirectionMap resMap = mRedirections.get(key);
+ int[] fromIdents = resMap.getRedirectionKeys();
+ int N = fromIdents.length;
+ for (int i = 0; i < N; i++) {
+ int fromIdent = fromIdents[i];
+ int toIdent = resMap.lookupRedirection(fromIdent);
+ String fromName = targetRes != null ? targetRes.getResourceName(fromIdent) : null;
+ String toName = themeRes != null ? themeRes.getResourceName(toIdent) : null;
+ pw.println(String.format(" %s (0x%08x) => %s (0x%08x)", fromName, fromIdent,
+ toName, toIdent));
+ }
+ }
+ }
+ }
+
+ private static class RedirectionKey {
+ public String themePackageName;
+ public String themeId;
+ public String targetPackageName;
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) return true;
+ if (!(o instanceof RedirectionKey)) return false;
+ final RedirectionKey oo = (RedirectionKey)o;
+ if (!nullSafeEquals(themePackageName, oo.themePackageName)) {
+ return false;
+ }
+ if (!nullSafeEquals(themeId, oo.themeId)) {
+ return false;
+ }
+ if (!nullSafeEquals(targetPackageName, oo.targetPackageName)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return themePackageName.hashCode() +
+ themeId.hashCode() +
+ targetPackageName.hashCode();
+ }
+
+ private static boolean nullSafeEquals(Object a, Object b) {
+ if (a == null) {
+ return b == a;
+ } else if (b == null) {
+ return false;
+ } else {
+ return a.equals(b);
+ }
+ }
+ }
+
+ /**
+ * Parses and processes explicit redirection XML files.
+ */
+ private static class ResourceRedirectionsProcessor {
+ private final Resources mResources;
+ private final XmlPullParser mParser;
+ private final int mResourceId;
+ private final String mThemePackageName;
+ private final String mTargetPackageName;
+ private final PackageRedirectionMap mResMap;
+
+ public ResourceRedirectionsProcessor(Resources res, int resourceId,
+ String themePackageName, String targetPackageName,
+ PackageRedirectionMap outMap) {
+ mResources = res;
+ mParser = res.getXml(resourceId);
+ mResourceId = resourceId;
+ mThemePackageName = themePackageName;
+ mTargetPackageName = targetPackageName;
+ mResMap = outMap;
+ }
+
+ public void process() {
+ XmlPullParser parser = mParser;
+ int type;
+ try {
+ while ((type = parser.next()) != XmlPullParser.START_TAG
+ && type != XmlPullParser.END_DOCUMENT) {
+ // just loop...
+ }
+
+ String tagName = parser.getName();
+ if (parser.getName().equals("resource-redirections")) {
+ processResourceRedirectionsTag();
+ } else {
+ Log.w(TAG, "Unknown root element: " + tagName + " at " + getResourceLabel() + " " +
+ parser.getPositionDescription());
+ }
+ } catch (XmlPullParserException e) {
+ Log.w(TAG, "Malformed theme redirection meta at " + getResourceLabel());
+ } catch (IOException e) {
+ Log.w(TAG, "Unknown error reading redirection meta at " + getResourceLabel());
+ }
+ }
+
+ private void processResourceRedirectionsTag() throws XmlPullParserException, IOException {
+ XmlPullParser parser = mParser;
+ int type;
+ final int innerDepth = parser.getDepth();
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT &&
+ (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
+ if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+ continue;
+ }
+
+ String tagName = parser.getName();
+ if (tagName.equals("item")) {
+ processItemTag();
+ } else {
+ Log.w(TAG, "Unknown element under <resource-redirections>: " + tagName
+ + " at " + getResourceLabel() + " "
+ + parser.getPositionDescription());
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+ }
+ }
+ }
+
+ private void processItemTag() throws XmlPullParserException, IOException {
+ XmlPullParser parser = mParser;
+ String fromName = parser.getAttributeValue(null, "name");
+ if (TextUtils.isEmpty(fromName)) {
+ Log.w(TAG, "Missing android:name attribute on <item> tag at " + getResourceLabel() + " " +
+ parser.getPositionDescription());
+ return;
+ }
+ String toName = parser.nextText();
+ if (TextUtils.isEmpty(toName)) {
+ Log.w(TAG, "Missing <item> text at " + getResourceLabel() + " " +
+ parser.getPositionDescription());
+ return;
+ }
+ int fromIdent = mResources.getIdentifier(fromName, null, mTargetPackageName);
+ if (fromIdent == 0) {
+ Log.w(TAG, "No such resource found for " + mTargetPackageName + ":" + fromName);
+ return;
+ }
+ int toIdent = mResources.getIdentifier(toName, null, mThemePackageName);
+ if (toIdent == 0) {
+ Log.w(TAG, "No such resource found for " + mThemePackageName + ":" + toName);
+ return;
+ }
+ mResMap.addRedirection(fromIdent, toIdent);
+ }
+
+ private String getResourceLabel() {
+ return "resource #0x" + Integer.toHexString(mResourceId);
+ }
+ }
+}
diff --git a/services/java/com/android/server/DeviceStorageMonitorService.java b/services/java/com/android/server/DeviceStorageMonitorService.java
index 94a087a..cce5653 100644
--- a/services/java/com/android/server/DeviceStorageMonitorService.java
+++ b/services/java/com/android/server/DeviceStorageMonitorService.java
@@ -19,9 +19,11 @@ package com.android.server;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import com.android.internal.app.ThemeUtils;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -84,6 +86,7 @@ public class DeviceStorageMonitorService extends Binder {
private boolean mLowMemFlag=false;
private boolean mMemFullFlag=false;
private Context mContext;
+ private Context mUiContext;
private ContentResolver mContentResolver;
private long mTotalMemory; // on /data
private StatFs mDataFileStats;
@@ -345,6 +348,14 @@ public class DeviceStorageMonitorService extends Binder {
mLastReportedFreeMemTime = 0;
mContext = context;
mContentResolver = mContext.getContentResolver();
+
+ ThemeUtils.registerThemeChangeReceiver(mContext, new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context content, Intent intent) {
+ mUiContext = null;
+ }
+ });
+
//create StatFs object
mDataFileStats = new StatFs(DATA_PATH);
mSystemFileStats = new StatFs(SYSTEM_PATH);
@@ -402,7 +413,7 @@ public class DeviceStorageMonitorService extends Binder {
notification.icon = com.android.internal.R.drawable.stat_notify_disk_full;
notification.tickerText = title;
notification.flags |= Notification.FLAG_NO_CLEAR;
- notification.setLatestEventInfo(mContext, title, details, intent);
+ notification.setLatestEventInfo(getUiContext(), title, details, intent);
mNotificationMgr.notifyAsUser(null, LOW_MEMORY_NOTIFICATION_ID, notification,
UserHandle.ALL);
mContext.sendStickyBroadcastAsUser(mStorageLowIntent, UserHandle.ALL);
@@ -515,4 +526,11 @@ public class DeviceStorageMonitorService extends Binder {
pw.print(" mMemCacheTrimToThreshold=");
pw.println(Formatter.formatFileSize(mContext, mMemCacheTrimToThreshold));
}
+
+ private Context getUiContext() {
+ if (mUiContext == null) {
+ mUiContext = ThemeUtils.createUiContext(mContext);
+ }
+ return mUiContext != null ? mUiContext : mContext;
+ }
}
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index b11432d..445a4bb 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -15,6 +15,7 @@
package com.android.server;
+import com.android.internal.app.ThemeUtils;
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.HandlerCaller;
import com.android.internal.os.SomeArgs;
@@ -165,6 +166,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
private static final Locale ENGLISH_LOCALE = new Locale("en");
final Context mContext;
+ private Context mUiContext;
final Resources mRes;
final Handler mHandler;
final InputMethodSettings mSettings;
@@ -848,6 +850,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
(KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
mNotificationManager = (NotificationManager)
mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+ ThemeUtils.registerThemeChangeReceiver(mContext, new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ mUiContext = null;
+ }
+ });
+
mStatusBar = statusBar;
statusBar.setIconVisibility("ime", false);
updateImeWindowStatusLocked();
@@ -2525,6 +2534,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
}
+ private Context getUiContext() {
+ if (mUiContext == null) {
+ mUiContext = ThemeUtils.createUiContext(mContext);
+ }
+ return mUiContext != null ? mUiContext : mContext;
+ }
+
// ----------------------------------------------------------------------
private void showInputMethodMenu() {
@@ -2561,7 +2577,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
private void showInputMethodMenuInternal(boolean showSubtypes) {
if (DEBUG) Slog.v(TAG, "Show switching menu");
- final Context context = mContext;
+ final Context context = getUiContext();
final boolean isScreenLocked = isScreenLocked();
final String lastInputMethodId = mSettings.getSelectedInputMethod();
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index af49135..5f0187c 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -79,6 +79,9 @@ import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import java.io.File;
+
+import com.android.internal.app.ThemeUtils;
+
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@@ -122,6 +125,7 @@ public class NotificationManagerService extends INotificationManager.Stub
private static final boolean ENABLE_BLOCKED_TOASTS = true;
final Context mContext;
+ Context mUiContext;
final IActivityManager mAm;
final IBinder mForegroundToken = new Binder();
@@ -533,6 +537,13 @@ public class NotificationManagerService extends INotificationManager.Stub
}
};
+ private BroadcastReceiver mThemeChangeReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ mUiContext = null;
+ }
+ };
+
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -766,6 +777,7 @@ public class NotificationManagerService extends INotificationManager.Stub
ledObserver.observe();
QuietHoursSettingsObserver qhObserver = new QuietHoursSettingsObserver(mHandler);
qhObserver.observe();
+ ThemeUtils.registerThemeChangeReceiver(mContext, mThemeChangeReceiver);
}
void systemReady() {
@@ -1634,6 +1646,13 @@ public class NotificationManagerService extends INotificationManager.Stub
return -1;
}
+ private Context getUiContext() {
+ if (mUiContext == null) {
+ mUiContext = ThemeUtils.createUiContext(mContext);
+ }
+ return mUiContext != null ? mUiContext : mContext;
+ }
+
private void updateNotificationPulse() {
synchronized (mNotificationList) {
updateLightsLocked();
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 3dd22b0..cec8a4c 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006 The Android Open Source Project
+ * This code has been modified. Portions copyright (C) 2010, T-Mobile USA, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,6 +25,7 @@ import android.content.ContentResolver;
import android.content.ContentService;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.IPackageManager;
import android.content.res.Configuration;
import android.media.AudioService;
@@ -757,6 +759,13 @@ class ServerThread extends Thread {
reportWtf("starting DreamManagerService", e);
}
}
+
+ try {
+ Slog.i(TAG, "AssetRedirectionManager Service");
+ ServiceManager.addService("assetredirection", new AssetRedirectionManagerService(context));
+ } catch (Throwable e) {
+ Slog.e(TAG, "Failure starting AssetRedirectionManager Service", e);
+ }
}
// Before things start rolling, be sure we have decided whether
@@ -840,6 +849,15 @@ class ServerThread extends Thread {
reportWtf("making Display Manager Service ready", e);
}
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_APP_LAUNCH_FAILURE);
+ filter.addAction(Intent.ACTION_APP_LAUNCH_FAILURE_RESET);
+ filter.addAction(Intent.ACTION_PACKAGE_ADDED);
+ filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ filter.addCategory(Intent.CATEGORY_THEME_PACKAGE_INSTALLED_STATE_CHANGE);
+ filter.addDataScheme("package");
+ context.registerReceiver(new AppsLaunchFailureReceiver(), filter);
+
// These are needed to propagate to the runnable below.
final Context contextF = context;
final MountService mountServiceF = mountService;
diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java
index 75eb3c4..9bc3a91 100644
--- a/services/java/com/android/server/ThrottleService.java
+++ b/services/java/com/android/server/ThrottleService.java
@@ -53,6 +53,7 @@ import android.util.Slog;
import android.util.TrustedTime;
import com.android.internal.R;
+import com.android.internal.app.ThemeUtils;
import com.android.internal.telephony.TelephonyProperties;
import java.io.BufferedWriter;
@@ -80,6 +81,7 @@ public class ThrottleService extends IThrottleManager.Stub {
private HandlerThread mThread;
private Context mContext;
+ private Context mUiContext;
private static final int INITIAL_POLL_DELAY_SEC = 90;
private static final int TESTING_POLLING_PERIOD_SEC = 60 * 1;
@@ -339,6 +341,13 @@ public class ThrottleService extends IThrottleManager.Stub {
}
}, new IntentFilter(ACTION_RESET));
+ ThemeUtils.registerThemeChangeReceiver(mContext, new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ mUiContext = null;
+ }
+ });
+
// use a new thread as we don't want to stall the system for file writes
mThread = new HandlerThread(TAG);
mThread.start();
@@ -685,12 +694,18 @@ public class ThrottleService extends IThrottleManager.Stub {
}
mThrottlingNotification.flags = flags;
mThrottlingNotification.tickerText = title;
- mThrottlingNotification.setLatestEventInfo(mContext, title, message, pi);
+ mThrottlingNotification.setLatestEventInfo(getUiContext(), title, message, pi);
mNotificationManager.notifyAsUser(null, mThrottlingNotification.icon,
mThrottlingNotification, UserHandle.ALL);
}
+ private Context getUiContext() {
+ if (mUiContext == null) {
+ mUiContext = ThemeUtils.createUiContext(mContext);
+ }
+ return mUiContext != null ? mUiContext : mContext;
+ }
private void clearThrottleAndNotification() {
if (mThrottleIndex.get() != THROTTLE_INDEX_UNTHROTTLED) {
diff --git a/services/java/com/android/server/UiModeManagerService.java b/services/java/com/android/server/UiModeManagerService.java
index 0e456f1..797990e 100644
--- a/services/java/com/android/server/UiModeManagerService.java
+++ b/services/java/com/android/server/UiModeManagerService.java
@@ -48,6 +48,7 @@ import java.io.PrintWriter;
import com.android.internal.R;
import com.android.internal.app.DisableCarModeActivity;
import com.android.server.TwilightService.TwilightState;
+import com.android.internal.app.ThemeUtils;
final class UiModeManagerService extends IUiModeManager.Stub {
private static final String TAG = UiModeManager.class.getSimpleName();
@@ -60,6 +61,7 @@ final class UiModeManagerService extends IUiModeManager.Stub {
private final Context mContext;
private final TwilightService mTwilightService;
private final Handler mHandler = new Handler();
+ private Context mUiContext;
final Object mLock = new Object();
@@ -142,6 +144,13 @@ final class UiModeManagerService extends IUiModeManager.Stub {
}
};
+ private final BroadcastReceiver mThemeChangeReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ mUiContext = null;
+ }
+ };
+
private final TwilightService.TwilightListener mTwilightListener =
new TwilightService.TwilightListener() {
@Override
@@ -161,6 +170,8 @@ final class UiModeManagerService extends IUiModeManager.Stub {
mContext.registerReceiver(mBatteryReceiver,
new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
+ ThemeUtils.registerThemeChangeReceiver(mContext, mThemeChangeReceiver);
+
mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
mWakeLock = mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG);
@@ -549,7 +560,7 @@ final class UiModeManagerService extends IUiModeManager.Stub {
n.flags = Notification.FLAG_ONGOING_EVENT;
n.when = 0;
n.setLatestEventInfo(
- mContext,
+ getUiContext(),
mContext.getString(R.string.car_mode_disable_notification_title),
mContext.getString(R.string.car_mode_disable_notification_message),
PendingIntent.getActivityAsUser(mContext, 0, carModeOffIntent, 0,
@@ -579,6 +590,13 @@ final class UiModeManagerService extends IUiModeManager.Stub {
}
}
+ private Context getUiContext() {
+ if (mUiContext == null) {
+ mUiContext = ThemeUtils.createUiContext(mContext);
+ }
+ return mUiContext != null ? mUiContext : mContext;
+ }
+
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index d2cd646..a747f0b 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006-2008 The Android Open Source Project
+ * This code has been modified. Portions copyright (C) 2010, T-Mobile USA, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +20,7 @@ package com.android.server.am;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import com.android.internal.R;
+import com.android.internal.app.ThemeUtils;
import com.android.internal.os.BatteryStatsImpl;
import com.android.internal.os.ProcessStats;
import com.android.internal.widget.LockPatternUtils;
@@ -87,6 +89,7 @@ import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
+import android.content.res.CustomTheme;
import android.graphics.Bitmap;
import android.net.Proxy;
import android.net.ProxyProperties;
@@ -160,6 +163,7 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
+import dalvik.system.Zygote;
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
@@ -667,6 +671,7 @@ public final class ActivityManagerService extends ActivityManagerNative
boolean mLaunchWarningShown = false;
Context mContext;
+ Context mUiContext;
int mFactoryTest;
@@ -936,7 +941,7 @@ public final class ActivityManagerService extends ActivityManagerNative
return;
}
if (mShowDialogs && !mSleeping && !mShuttingDown) {
- Dialog d = new AppErrorDialog(mContext,
+ Dialog d = new AppErrorDialog(getUiContext(),
ActivityManagerService.this, res, proc);
d.show();
proc.crashDialog = d;
@@ -971,7 +976,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (mShowDialogs) {
Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
- mContext, proc, (ActivityRecord)data.get("activity"),
+ getUiContext(), proc, (ActivityRecord)data.get("activity"),
msg.arg1 != 0);
d.show();
proc.anrDialog = d;
@@ -997,7 +1002,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
AppErrorResult res = (AppErrorResult) data.get("result");
if (mShowDialogs && !mSleeping && !mShuttingDown) {
- Dialog d = new StrictModeViolationDialog(mContext,
+ Dialog d = new StrictModeViolationDialog(getUiContext(),
ActivityManagerService.this, res, proc);
d.show();
proc.crashDialog = d;
@@ -1011,7 +1016,7 @@ public final class ActivityManagerService extends ActivityManagerNative
} break;
case SHOW_FACTORY_ERROR_MSG: {
Dialog d = new FactoryErrorDialog(
- mContext, msg.getData().getCharSequence("msg"));
+ getUiContext(), msg.getData().getCharSequence("msg"));
d.show();
ensureBootCompleted();
} break;
@@ -1031,7 +1036,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (!app.waitedForDebugger) {
Dialog d = new AppWaitingForDebuggerDialog(
ActivityManagerService.this,
- mContext, app);
+ getUiContext(), app);
app.waitDialog = d;
app.waitedForDebugger = true;
d.show();
@@ -1113,7 +1118,7 @@ public final class ActivityManagerService extends ActivityManagerNative
Log.e(TAG, title + ": " + text);
if (mShowDialogs) {
// XXX This is a temporary dialog, no need to localize.
- AlertDialog d = new BaseErrorDialog(mContext);
+ AlertDialog d = new BaseErrorDialog(getUiContext());
d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
d.setCancelable(false);
d.setTitle(title);
@@ -1184,7 +1189,7 @@ public final class ActivityManagerService extends ActivityManagerNative
notification.defaults = 0; // please be quiet
notification.sound = null;
notification.vibrate = null;
- notification.setLatestEventInfo(context, text,
+ notification.setLatestEventInfo(getUiContext(), text,
mContext.getText(R.string.heavy_weight_notification_detail),
PendingIntent.getActivityAsUser(mContext, 0, root.intent,
PendingIntent.FLAG_CANCEL_CURRENT, null,
@@ -1799,6 +1804,15 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
+ private Context getUiContext() {
+ synchronized (this) {
+ if (mUiContext == null && mBooted) {
+ mUiContext = ThemeUtils.createUiContext(mContext);
+ }
+ return mUiContext != null ? mUiContext : mContext;
+ }
+ }
+
/**
* Initialize the application bind args. These are passed to each
* process when the bindApplication() IPC is sent to the process. They're
@@ -3407,7 +3421,7 @@ public final class ActivityManagerService extends ActivityManagerNative
@Override
public void run() {
synchronized (ActivityManagerService.this) {
- final Dialog d = new LaunchWarningWindow(mContext, cur, next);
+ final Dialog d = new LaunchWarningWindow(getUiContext(), cur, next);
d.show();
mHandler.postDelayed(new Runnable() {
@Override
@@ -4390,6 +4404,13 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}, pkgFilter);
+ ThemeUtils.registerThemeChangeReceiver(mContext, new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ mUiContext = null;
+ }
+ });
+
synchronized (this) {
// Ensure that any processes we had put on hold are now started
// up.
@@ -12310,6 +12331,11 @@ public final class ActivityManagerService extends ActivityManagerNative
values.userSetLocale);
}
+ if (values.customTheme != null) {
+ saveThemeResourceLocked(values.customTheme,
+ !values.customTheme.equals(mConfiguration.customTheme));
+ }
+
mConfigurationSeq++;
if (mConfigurationSeq <= 0) {
mConfigurationSeq = 1;
@@ -12529,6 +12555,13 @@ public final class ActivityManagerService extends ActivityManagerNative
return srec.launchedFromUid;
}
+ private void saveThemeResourceLocked(CustomTheme t, boolean isDiff){
+ if(isDiff){
+ SystemProperties.set(Configuration.THEME_ID_PERSISTENCE_PROPERTY, t.getThemeId());
+ SystemProperties.set(Configuration.THEME_PACKAGE_NAME_PERSISTENCE_PROPERTY, t.getThemePackageName());
+ }
+ }
+
// =========================================================
// LIFETIME MANAGEMENT
// =========================================================
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index e4a7ead..8f154b1 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -47,6 +47,7 @@ import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
+import com.android.internal.app.ThemeUtils;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.util.IState;
@@ -74,6 +75,7 @@ import java.util.Set;
public class Tethering extends INetworkManagementEventObserver.Stub {
private Context mContext;
+ private Context mUiContext;
private final static String TAG = "Tethering";
private final static boolean DBG = true;
private final static boolean VDBG = false;
@@ -158,6 +160,13 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
mContext.registerReceiver(mStateReceiver, filter);
+ ThemeUtils.registerThemeChangeReceiver(mContext, new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context content, Intent intent) {
+ mUiContext = null;
+ }
+ });
+
filter = new IntentFilter();
filter.addAction(Intent.ACTION_MEDIA_SHARED);
filter.addAction(Intent.ACTION_MEDIA_UNSHARED);
@@ -478,12 +487,19 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
mTetheredNotification.defaults &= ~Notification.DEFAULT_SOUND;
mTetheredNotification.flags = Notification.FLAG_ONGOING_EVENT;
mTetheredNotification.tickerText = title;
- mTetheredNotification.setLatestEventInfo(mContext, title, message, pi);
+ mTetheredNotification.setLatestEventInfo(getUiContext(), title, message, pi);
notificationManager.notifyAsUser(null, mTetheredNotification.icon,
mTetheredNotification, UserHandle.ALL);
}
+ private Context getUiContext() {
+ if (mUiContext == null) {
+ mUiContext = ThemeUtils.createUiContext(mContext);
+ }
+ return mUiContext != null ? mUiContext : mContext;
+ }
+
private void clearTetheredNotification() {
NotificationManager notificationManager =
(NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 83672c5..0cbfa6f 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006 The Android Open Source Project
+ * This code has been modified. Portions copyright (C) 2010, T-Mobile USA, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,6 +32,7 @@ import static libcore.io.OsConstants.S_IXGRP;
import static libcore.io.OsConstants.S_IROTH;
import static libcore.io.OsConstants.S_IXOTH;
+import com.android.internal.app.IAssetRedirectionManager;
import com.android.internal.app.IMediaContainerService;
import com.android.internal.app.ResolverActivity;
import com.android.internal.content.NativeLibraryHelper;
@@ -143,6 +145,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
+import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -150,6 +153,9 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipOutputStream;
import libcore.io.ErrnoException;
import libcore.io.IoUtils;
@@ -201,6 +207,8 @@ public class PackageManagerService extends IPackageManager.Stub {
// package apks to install directory.
private static final String INSTALL_PACKAGE_SUFFIX = "-";
+ private static final int THEME_MAMANER_GUID = 1300;
+
static final int SCAN_MONITOR = 1<<0;
static final int SCAN_NO_DEX = 1<<1;
static final int SCAN_FORCE_DEX = 1<<2;
@@ -407,6 +415,8 @@ public class PackageManagerService extends IPackageManager.Stub {
ComponentName mResolveComponentName;
PackageParser.Package mPlatformPackage;
+ IAssetRedirectionManager mAssetRedirectionManager;
+
// Set of pending broadcasts for aggregating enable/disable of components.
final HashMap<String, ArrayList<String>> mPendingBroadcasts
= new HashMap<String, ArrayList<String>>();
@@ -706,7 +716,7 @@ public class PackageManagerService extends IPackageManager.Stub {
PackageInstalledInfo res = data.res;
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
- res.removedInfo.sendBroadcast(false, true, false);
+ res.removedInfo.sendBroadcast(false, true, false, false);
Bundle extras = new Bundle(1);
extras.putInt(Intent.EXTRA_UID, res.uid);
// Determine the set of users who are adding this
@@ -743,21 +753,25 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
- res.pkg.applicationInfo.packageName,
+ res.pkg.applicationInfo.packageName, null,
extras, null, null, firstUsers);
final boolean update = res.removedInfo.removedPackage != null;
if (update) {
extras.putBoolean(Intent.EXTRA_REPLACING, true);
}
+ String category = null;
+ if(res.pkg.mIsThemeApk) {
+ category = Intent.CATEGORY_THEME_PACKAGE_INSTALLED_STATE_CHANGE;
+ }
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
- res.pkg.applicationInfo.packageName,
+ res.pkg.applicationInfo.packageName, category,
extras, null, null, updateUsers);
if (update) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
- res.pkg.applicationInfo.packageName,
+ res.pkg.applicationInfo.packageName, category,
extras, null, null, updateUsers);
sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
- null, null,
+ null, null, null,
res.pkg.applicationInfo.packageName, null, updateUsers);
}
if (res.removedInfo.args != null) {
@@ -975,6 +989,7 @@ public class PackageManagerService extends IPackageManager.Stub {
Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID, ApplicationInfo.FLAG_SYSTEM);
mSettings.addSharedUserLPw("android.uid.log", LOG_UID, ApplicationInfo.FLAG_SYSTEM);
+ mSettings.addSharedUserLPw("com.tmobile.thememanager", THEME_MAMANER_GUID, ApplicationInfo.FLAG_SYSTEM);
mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID, ApplicationInfo.FLAG_SYSTEM);
mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID, ApplicationInfo.FLAG_SYSTEM);
@@ -2938,6 +2953,20 @@ public class PackageManagerService extends IPackageManager.Stub {
return list;
}
+ public List<PackageInfo> getInstalledThemePackages() {
+ // Returns a list of theme APKs.
+ ArrayList<PackageInfo> finalList = new ArrayList<PackageInfo>();
+ List<PackageInfo> installedPackagesList = mContext.getPackageManager().getInstalledPackages(0);
+ Iterator<PackageInfo> i = installedPackagesList.iterator();
+ while (i.hasNext()) {
+ final PackageInfo pi = i.next();
+ if (pi != null && pi.isThemeApk) {
+ finalList.add(pi);
+ }
+ }
+ return finalList;
+ }
+
@Override
public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags,
String lastRead, int userId) {
@@ -4495,6 +4524,32 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
+ // NOTE: this method can return null if the SystemServer is still
+ // initializing
+ public IAssetRedirectionManager getAssetRedirectionManager() {
+ if (mAssetRedirectionManager != null) {
+ return mAssetRedirectionManager;
+ }
+ IBinder b = ServiceManager.getService("assetredirection");
+ mAssetRedirectionManager = IAssetRedirectionManager.Stub.asInterface(b);
+ return mAssetRedirectionManager;
+ }
+
+ private void cleanAssetRedirections(PackageParser.Package pkg) {
+ IAssetRedirectionManager rm = getAssetRedirectionManager();
+ if (rm == null) {
+ return;
+ }
+ try {
+ if (pkg.mIsThemeApk) {
+ rm.clearRedirectionMapsByTheme(pkg.packageName, null);
+ } else {
+ rm.clearPackageRedirectionMap(pkg.packageName);
+ }
+ } catch (RemoteException e) {
+ }
+ }
+
void removePackageLI(PackageSetting ps, boolean chatty) {
if (DEBUG_INSTALL) {
if (chatty)
@@ -4523,6 +4578,8 @@ public class PackageManagerService extends IPackageManager.Stub {
// writer
synchronized (mPackages) {
+ cleanAssetRedirections(pkg);
+
mPackages.remove(pkg.applicationInfo.packageName);
if (pkg.mPath != null) {
mAppDirs.remove(pkg.mPath);
@@ -5367,7 +5424,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
};
- static final void sendPackageBroadcast(String action, String pkg,
+ static final void sendPackageBroadcast(String action, String pkg, String intentCategory,
Bundle extras, String targetPkg, IIntentReceiver finishedReceiver,
int[] userIds) {
IActivityManager am = ActivityManagerNative.getDefault();
@@ -5400,6 +5457,9 @@ public class PackageManagerService extends IPackageManager.Stub {
+ intent.toShortString(false, true, false, false)
+ " " + intent.getExtras(), here);
}
+ if (intentCategory != null) {
+ intent.addCategory(intentCategory);
+ }
am.broadcastIntent(null, intent, null, finishedReceiver,
0, null, null, null, finishedReceiver != null, false, id);
}
@@ -5483,6 +5543,7 @@ public class PackageManagerService extends IPackageManager.Stub {
String addedPackage = null;
int addedAppId = -1;
int[] addedUsers = null;
+ String category = null;
// TODO post a message to the handler to obtain serial ordering
synchronized (mInstallLock) {
@@ -5513,6 +5574,9 @@ public class PackageManagerService extends IPackageManager.Stub {
synchronized (mPackages) {
p = mAppDirs.get(fullPathStr);
if (p != null) {
+ if (p.mIsThemeApk) {
+ category = Intent.CATEGORY_THEME_PACKAGE_INSTALLED_STATE_CHANGE;
+ }
ps = mSettings.mPackages.get(p.applicationInfo.packageName);
if (ps != null) {
removedUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
@@ -5554,6 +5618,9 @@ public class PackageManagerService extends IPackageManager.Stub {
addedAppId = UserHandle.getAppId(p.applicationInfo.uid);
}
}
+ if (p != null && p.mIsThemeApk) {
+ category = Intent.CATEGORY_THEME_PACKAGE_INSTALLED_STATE_CHANGE;
+ }
}
// reader
@@ -5566,13 +5633,13 @@ public class PackageManagerService extends IPackageManager.Stub {
Bundle extras = new Bundle(1);
extras.putInt(Intent.EXTRA_UID, removedAppId);
extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
- sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
+ sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, category,
extras, null, null, removedUsers);
}
if (addedPackage != null) {
Bundle extras = new Bundle(1);
extras.putInt(Intent.EXTRA_UID, addedAppId);
- sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage,
+ sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage, category,
extras, null, null, addedUsers);
}
}
@@ -5669,7 +5736,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
if (sendAdded) {
- sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
+ sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, null,
packageName, extras, null, null, new int[] {userId});
}
} finally {
@@ -7791,6 +7858,24 @@ public class PackageManagerService extends IPackageManager.Stub {
Log.d(TAG, "New package installed in " + newPackage.mPath);
+ cleanAssetRedirections(newPackage);
+
+ if (newPackage.mIsThemeApk) {
+ /* DBS-TODO
+ boolean isThemePackageDrmProtected = false;
+ int N = newPackage.mThemeInfos.size();
+ for (int i = 0; i < N; i++) {
+ if (newPackage.mThemeInfos.get(i).isDrmProtected) {
+ isThemePackageDrmProtected = true;
+ break;
+ }
+ }
+ if (isThemePackageDrmProtected) {
+ splitThemePackage(newPackage.mPath);
+ }
+ */
+ }
+
synchronized (mPackages) {
updatePermissionsLPw(newPackage.packageName, newPackage,
UPDATE_PERMISSIONS_REPLACE_PKG | (newPackage.permissions.size() > 0
@@ -7806,6 +7891,65 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
+ private void deleteLockedZipFileIfExists(String originalPackagePath) {
+ String lockedZipFilePath = PackageParser.getLockedZipFilePath(originalPackagePath);
+ File zipFile = new File(lockedZipFilePath);
+ if (zipFile.exists() && zipFile.isFile()) {
+ if (!zipFile.delete()) {
+ Log.w(TAG, "Couldn't delete locked zip file: " + originalPackagePath);
+ }
+ }
+ }
+ private void splitThemePackage(File originalFile) {
+ final String originalPackagePath = originalFile.getPath();
+ final String lockedZipFilePath = PackageParser.getLockedZipFilePath(originalPackagePath);
+
+ try {
+ final List<String> drmProtectedEntries = new ArrayList<String>();
+ final ZipFile privateZip = new ZipFile(originalFile.getPath());
+
+ final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
+ while (privateZipEntries.hasMoreElements()) {
+ final ZipEntry zipEntry = privateZipEntries.nextElement();
+ final String zipEntryName = zipEntry.getName();
+ if (zipEntryName.startsWith("assets/") && zipEntryName.contains("/locked/")) {
+ drmProtectedEntries.add(zipEntryName);
+ }
+ }
+ privateZip.close();
+
+ String [] args = new String[0];
+ args = drmProtectedEntries.toArray(args);
+ int code = mContext.getAssets().splitDrmProtectedThemePackage(
+ originalPackagePath,
+ lockedZipFilePath,
+ args);
+ if (code != 0) {
+ Log.e("PackageManagerService",
+ "splitDrmProtectedThemePackage returned = " + code);
+ }
+ code = FileUtils.setPermissions(
+ lockedZipFilePath,
+ 0640,
+ -1,
+ THEME_MAMANER_GUID);
+ if (code != 0) {
+ Log.e("PackageManagerService",
+ "Set permissions for " + lockedZipFilePath + " returned = " + code);
+ }
+ code = FileUtils.setPermissions(
+ originalPackagePath,
+ 0644,
+ -1, -1);
+ if (code != 0) {
+ Log.e("PackageManagerService",
+ "Set permissions for " + originalPackagePath + " returned = " + code);
+ }
+ } catch (IOException e) {
+ Log.e(TAG, "Failure to generate new zip files for theme");
+ }
+ }
+
private void installPackageLI(InstallArgs args,
boolean newInstall, PackageInstalledInfo res) {
int pFlags = args.flags;
@@ -8066,6 +8210,18 @@ public class PackageManagerService extends IPackageManager.Stub {
boolean removedForAllUsers = false;
boolean systemUpdate = false;
+
+ synchronized (mPackages) {
+ PackageParser.Package p = mPackages.get(packageName);
+ if (p != null) {
+ info.isThemeApk = p.mIsThemeApk;
+ if (info.isThemeApk &&
+ !info.isRemovedPackageSystemUpdate) {
+ deleteLockedZipFileIfExists(p.mPath);
+ }
+ }
+ }
+
synchronized (mInstallLock) {
res = deletePackageLI(packageName,
(flags & PackageManager.DELETE_ALL_USERS) != 0
@@ -8078,7 +8234,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
if (res) {
- info.sendBroadcast(true, systemUpdate, removedForAllUsers);
+ info.sendBroadcast(true, systemUpdate, removedForAllUsers, true);
// If the removed package was a system update, the old system package
// was re-enabled; we need to broadcast this information
@@ -8088,11 +8244,16 @@ public class PackageManagerService extends IPackageManager.Stub {
? info.removedAppId : info.uid);
extras.putBoolean(Intent.EXTRA_REPLACING, true);
- sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
+ String category = null;
+ if (info.isThemeApk) {
+ category = Intent.CATEGORY_THEME_PACKAGE_INSTALLED_STATE_CHANGE;
+ }
+
+ sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, category,
extras, null, null, null);
- sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
+ sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, category,
extras, null, null, null);
- sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null,
+ sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null, null,
null, packageName, null, null);
}
}
@@ -8117,8 +8278,10 @@ public class PackageManagerService extends IPackageManager.Stub {
boolean isRemovedPackageSystemUpdate = false;
// Clean up resources deleted packages.
InstallArgs args = null;
+ boolean isThemeApk = false;
- void sendBroadcast(boolean fullRemove, boolean replacing, boolean removedForAllUsers) {
+ void sendBroadcast(boolean fullRemove, boolean replacing, boolean removedForAllUsers,
+ boolean deleteLockedZipFileIfExists) {
Bundle extras = new Bundle(1);
extras.putInt(Intent.EXTRA_UID, removedAppId >= 0 ? removedAppId : uid);
extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
@@ -8127,15 +8290,19 @@ public class PackageManagerService extends IPackageManager.Stub {
}
extras.putBoolean(Intent.EXTRA_REMOVED_FOR_ALL_USERS, removedForAllUsers);
if (removedPackage != null) {
- sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
+ String category = null;
+ if (isThemeApk) {
+ category = Intent.CATEGORY_THEME_PACKAGE_INSTALLED_STATE_CHANGE;
+ }
+ sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, category,
extras, null, null, removedUsers);
if (fullRemove && !replacing) {
- sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED, removedPackage,
+ sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED, removedPackage, category,
extras, null, null, removedUsers);
}
}
if (removedAppId >= 0) {
- sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras, null, null,
+ sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, null, extras, null, null,
removedUsers);
}
}
@@ -8714,6 +8881,7 @@ public class PackageManagerService extends IPackageManager.Stub {
"replacePreferredActivity expects filter to have no data authorities, " +
"paths, schemes or types.");
}
+
synchronized (mPackages) {
if (mContext.checkCallingOrSelfPermission(
android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
@@ -8989,7 +9157,7 @@ public class PackageManagerService extends IPackageManager.Stub {
extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
extras.putInt(Intent.EXTRA_UID, packageUid);
- sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, null, null,
+ sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, null, extras, null, null,
new int[] {UserHandle.getUserId(packageUid)});
}
@@ -9654,7 +9822,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
: Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
- sendPackageBroadcast(action, null, extras, null, finishedReceiver, null);
+ sendPackageBroadcast(action, null, null, extras, null, finishedReceiver, null);
}
}
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 94494ae..15395d2 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -2478,7 +2478,7 @@ final class Settings {
if (pkgSetting.getNotLaunched(userId)) {
if (pkgSetting.installerPackageName != null) {
PackageManagerService.sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_LAUNCH,
- pkgSetting.name, null,
+ pkgSetting.name, null, null,
pkgSetting.installerPackageName, null, new int[] {userId});
}
pkgSetting.setNotLaunched(false, userId);
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 38233d0..0e5adbb 100755
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -41,6 +41,8 @@ import static android.view.WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import com.android.internal.app.IBatteryStats;
+import com.android.internal.app.ThemeUtils;
+
import com.android.internal.policy.PolicyManager;
import com.android.internal.policy.impl.PhoneWindowManager;
import com.android.internal.view.IInputContext;
@@ -295,6 +297,13 @@ public class WindowManagerService extends IWindowManager.Stub
private static final float THUMBNAIL_ANIMATION_DECELERATE_FACTOR = 1.5f;
+
+ private BroadcastReceiver mThemeChangeReceiver = new BroadcastReceiver() {
+ public void onReceive(Context context, Intent intent) {
+ mUiContext = null;
+ }
+ };
+
final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -310,6 +319,7 @@ public class WindowManagerService extends IWindowManager.Stub
int mCurrentUserId;
final Context mContext;
+ private Context mUiContext;
final boolean mHaveInputMethods;
@@ -847,6 +857,15 @@ public class WindowManagerService extends IWindowManager.Stub
} finally {
Surface.closeTransaction();
}
+
+ ThemeUtils.registerThemeChangeReceiver(mContext, mThemeChangeReceiver);
+ }
+
+ private Context getUiContext() {
+ if (mUiContext == null) {
+ mUiContext = ThemeUtils.createUiContext(mContext);
+ }
+ return mUiContext != null ? mUiContext : mContext;
}
public InputMonitor getInputMonitor() {
@@ -5414,13 +5433,13 @@ public class WindowManagerService extends IWindowManager.Stub
// Called by window manager policy. Not exposed externally.
@Override
public void shutdown(boolean confirm) {
- ShutdownThread.shutdown(mContext, confirm);
+ ShutdownThread.shutdown(getUiContext(), confirm);
}
// Called by window manager policy. Not exposed externally.
@Override
public void rebootSafeMode(boolean confirm) {
- ShutdownThread.rebootSafeMode(mContext, confirm);
+ ShutdownThread.rebootSafeMode(getUiContext(), confirm);
}
public void setInputFilter(IInputFilter filter) {
@@ -5433,7 +5452,7 @@ public class WindowManagerService extends IWindowManager.Stub
// Called by window manager policy. Not exposed externally.
@Override
public void reboot() {
- ShutdownThread.reboot(mContext, null, true);
+ ShutdownThread.reboot(getUiContext(), null, true);
}
public void setCurrentUser(final int newUserId) {