diff options
-rw-r--r-- | core/java/android/app/ActivityThread.java | 9 | ||||
-rw-r--r-- | core/java/android/content/Intent.java | 6 | ||||
-rw-r--r-- | core/res/AndroidManifest.xml | 6 | ||||
-rw-r--r-- | core/res/res/values/cm_strings.xml | 2 | ||||
-rw-r--r-- | core/res/res/values/cm_symbols.xml | 3 | ||||
-rw-r--r-- | services/core/java/com/android/server/am/ActivityManagerService.java | 26 | ||||
-rw-r--r-- | services/java/com/android/server/AppsFailureReceiver.java (renamed from services/java/com/android/server/AppsLaunchFailureReceiver.java) | 38 | ||||
-rw-r--r-- | services/java/com/android/server/SystemServer.java | 6 |
8 files changed, 76 insertions, 20 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 6c88563..cd27d76 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -2428,13 +2428,6 @@ public final class ActivityThread { } catch (Exception e) { if (!mInstrumentation.onException(activity, e)) { - if (e instanceof InflateException) { - Log.e(TAG, "Failed to inflate", e); - sendAppLaunchFailureBroadcast(r); - } else if (e instanceof Resources.NotFoundException) { - Log.e(TAG, "Failed to find resource", e); - sendAppLaunchFailureBroadcast(r); - } throw new RuntimeException( "Unable to start activity " + component + ": " + e.toString(), e); @@ -2449,7 +2442,7 @@ public final class ActivityThread { if (r.packageInfo != null && !TextUtils.isEmpty(r.packageInfo.getPackageName())) { pkg = r.packageInfo.getPackageName(); } - Intent intent = new Intent(Intent.ACTION_APP_LAUNCH_FAILURE, + Intent intent = new Intent(Intent.ACTION_APP_FAILURE, (pkg != null)? Uri.fromParts("package", pkg, null) : null); getSystemContext().sendBroadcast(intent); } diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 052c6d3..a1a0867 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -2846,13 +2846,15 @@ public class Intent implements Parcelable, Cloneable { * Could indicate that curently applied theme is malicious. * @hide */ - public static final String ACTION_APP_LAUNCH_FAILURE = "com.tmobile.intent.action.APP_LAUNCH_FAILURE"; + public static final String ACTION_APP_FAILURE = + "com.tmobile.intent.action.APP_FAILURE"; /** * Broadcast Action: Request to reset the unrecoverable errors count to 0. * @hide */ - public static final String ACTION_APP_LAUNCH_FAILURE_RESET = "com.tmobile.intent.action.APP_LAUNCH_FAILURE_RESET"; + public static final String ACTION_APP_FAILURE_RESET = + "com.tmobile.intent.action.APP_FAILURE_RESET"; /** * Activity Action: Shows the brightness setting dialog. diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 863b9ea..540a74b 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2954,10 +2954,10 @@ </intent-filter> </receiver> - <receiver android:name="com.android.server.AppsLaunchFailureReceiver" > + <receiver android:name="com.android.server.AppsFailureReceiver" > <intent-filter> - <action android:name="com.tmobile.intent.action.APP_LAUNCH_FAILURE" /> - <action android:name="com.tmobile.intent.action.APP_LAUNCH_FAILURE_RESET" /> + <action android:name="com.tmobile.intent.action.APP_FAILURE" /> + <action android:name="com.tmobile.intent.action.APP_FAILURE_RESET" /> <action android:name="android.intent.action.PACKAGE_ADDED" /> <action android:name="android.intent.action.PACKAGE_REMOVED" /> <action android:name="org.cyanogenmod.intent.action.THEME_CHANGED" /> diff --git a/core/res/res/values/cm_strings.xml b/core/res/res/values/cm_strings.xml index 98e0539..b5da286 100644 --- a/core/res/res/values/cm_strings.xml +++ b/core/res/res/values/cm_strings.xml @@ -133,4 +133,6 @@ <!-- stylus gestures support --> <string name="stylus_app_not_installed">%s is not installed</string> + <string name="theme_reset_notification_title">Theme reset</string> + <string name="theme_reset_notification_body">System theme restored due to multiple app crashes.</string> </resources> diff --git a/core/res/res/values/cm_symbols.xml b/core/res/res/values/cm_symbols.xml index d2ad24d..a5d780e 100644 --- a/core/res/res/values/cm_symbols.xml +++ b/core/res/res/values/cm_symbols.xml @@ -71,4 +71,7 @@ <java-symbol type="bool" name="config_stylusGestures" /> <java-symbol type="string" name="stylus_app_not_installed" /> + <!-- Theme reset notification --> + <java-symbol type="string" name="theme_reset_notification_title" /> + <java-symbol type="string" name="theme_reset_notification_body" /> </resources> diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 6c450c6..9da1a95 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -76,6 +76,7 @@ import android.util.SparseIntArray; import android.view.Display; import android.util.BoostFramework; +import android.view.InflateException; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.app.AssistUtils; @@ -12024,6 +12025,28 @@ public final class ActivityManagerService extends ActivityManagerNative } } + private void sendAppFailureBroadcast(String pkgName) { + Intent intent = new Intent(Intent.ACTION_APP_FAILURE, + (pkgName != null)? Uri.fromParts("package", pkgName, null) : null); + mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT_OR_SELF); + } + + /** + * A possible theme crash is one that throws one of the following exceptions + * {@link android.content.res.Resources.NotFoundException} + * {@link android.view.InflateException} + * + * @param exceptionClassName + * @return True if exceptionClassName is one of the above exceptions + */ + private boolean isPossibleThemeCrash(String exceptionClassName) { + if (Resources.NotFoundException.class.getName().equals(exceptionClassName) || + InflateException.class.getName().equals(exceptionClassName)) { + return true; + } + return false; + } + private boolean handleAppCrashLocked(ProcessRecord app, String reason, String shortMsg, String longMsg, String stackTrace) { long now = SystemClock.uptimeMillis(); @@ -12034,6 +12057,9 @@ public final class ActivityManagerService extends ActivityManagerNative } else { crashTime = null; } + + if (isPossibleThemeCrash(shortMsg)) sendAppFailureBroadcast(app.info.packageName); + if (crashTime != null && now < crashTime+ProcessList.MIN_CRASH_INTERVAL) { // This process loses! Slog.w(TAG, "Process " + app.info.processName diff --git a/services/java/com/android/server/AppsLaunchFailureReceiver.java b/services/java/com/android/server/AppsFailureReceiver.java index 81b23ec..bebef9b 100644 --- a/services/java/com/android/server/AppsLaunchFailureReceiver.java +++ b/services/java/com/android/server/AppsFailureReceiver.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2010, T-Mobile USA, Inc. + * 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. @@ -13,9 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.android.server; +import android.app.Notification; +import android.app.NotificationManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -28,11 +30,15 @@ import android.provider.ThemesContract; import java.util.ArrayList; import java.util.List; -public class AppsLaunchFailureReceiver extends BroadcastReceiver { +import com.android.internal.R; + +public class AppsFailureReceiver extends BroadcastReceiver { private static final int FAILURES_THRESHOLD = 3; private static final int EXPIRATION_TIME_IN_MILLISECONDS = 30000; // 30 seconds + private static final int THEME_RESET_NOTIFICATION_ID = 0x4641494C; + private int mFailuresCount = 0; private long mStartTime = 0; @@ -44,8 +50,9 @@ public class AppsLaunchFailureReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); - if (action.equals(Intent.ACTION_APP_LAUNCH_FAILURE)) { + if (action.equals(Intent.ACTION_APP_FAILURE)) { long currentTime = SystemClock.uptimeMillis(); + String pkgName = intent.getStringExtra("package"); if (currentTime - mStartTime > EXPIRATION_TIME_IN_MILLISECONDS) { // reset both the count and the timer mStartTime = currentTime; @@ -70,9 +77,10 @@ public class AppsLaunchFailureReceiver extends BroadcastReceiver { components.add(ThemesContract.ThemesColumns.MODIFIES_STATUS_BAR); components.add(ThemesContract.ThemesColumns.MODIFIES_NAVIGATION_BAR); tm.requestThemeChange(ThemeConfig.SYSTEM_DEFAULT, components); + postThemeResetNotification(context); } } - } else if (action.equals(Intent.ACTION_APP_LAUNCH_FAILURE_RESET) + } else if (action.equals(Intent.ACTION_APP_FAILURE_RESET) || action.equals(ThemeUtils.ACTION_THEME_CHANGED)) { mFailuresCount = 0; mStartTime = SystemClock.uptimeMillis(); @@ -83,4 +91,26 @@ public class AppsLaunchFailureReceiver extends BroadcastReceiver { } } + /** + * Posts a notification to let the user know their theme was reset + * @param context + */ + private void postThemeResetNotification(Context context) { + NotificationManager nm = + (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + String title = context.getString(R.string.theme_reset_notification_title); + String body = context.getString(R.string.theme_reset_notification_body); + Notification notice = new Notification.Builder(context) + .setAutoCancel(true) + .setOngoing(false) + .setContentTitle(title) + .setContentText(body) + .setStyle(new Notification.BigTextStyle().bigText(body)) + .setSmallIcon(android.R.drawable.stat_notify_error) + .setWhen(System.currentTimeMillis()) + .setCategory(Notification.CATEGORY_SYSTEM) + .setPriority(Notification.PRIORITY_MAX) + .build(); + nm.notify(THEME_RESET_NOTIFICATION_ID, notice); + } } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index b4427ec..48deb68 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -1152,14 +1152,14 @@ public final class SystemServer { } IntentFilter filter = new IntentFilter(); - filter.addAction(Intent.ACTION_APP_LAUNCH_FAILURE); - filter.addAction(Intent.ACTION_APP_LAUNCH_FAILURE_RESET); + filter.addAction(Intent.ACTION_APP_FAILURE); + filter.addAction(Intent.ACTION_APP_FAILURE_RESET); filter.addAction(Intent.ACTION_PACKAGE_ADDED); filter.addAction(Intent.ACTION_PACKAGE_REMOVED); filter.addAction(ThemeUtils.ACTION_THEME_CHANGED); filter.addCategory(Intent.CATEGORY_THEME_PACKAGE_INSTALLED_STATE_CHANGE); filter.addDataScheme("package"); - context.registerReceiver(new AppsLaunchFailureReceiver(), filter); + context.registerReceiver(new AppsFailureReceiver(), filter); // These are needed to propagate to the runnable below. final NetworkManagementService networkManagementF = networkManagement; |