Skip to content
Browse files

Better handling of modem panics

Unlike the stock ROM, we don't simply exec /sbin/reboot, but present UI
to the user where he can cancel the reboot (if he's currently doing
something) and is presented with a notice after the reboot.

Change-Id: Ib64ad901b9c407d21434e2cd7048b66f86bb443f
  • Loading branch information...
1 parent 28c54ce commit a0ad7d2c068fd5460a061f61be260a57b32a1be3 @maniac103 maniac103 committed with nadlabak
View
18 MmParts/AndroidManifest.xml
@@ -5,6 +5,10 @@
android:versionCode="1"
android:versionName="1.0" >
+ <uses-permission android:name="android.permission.BROADCAST_STICKY" />
+ <uses-permission android:name="android.permission.REBOOT" />
+ <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
+
<application
android:label="@string/app_name" >
<activity
@@ -14,6 +18,20 @@
<action android:name="com.cyanogenmod.action.LAUNCH_DEVICE_SETTINGS" />
</intent-filter>
</activity>
+
+ <activity android:name=".BpPanicNotifyActivity"
+ android:theme="@android:style/Theme.Translucent.NoTitleBar" />
+
+ <activity android:name=".BpPanicRebootNoticeActivity"
+ android:theme="@android:style/Theme.Translucent.NoTitleBar" />
+
+ <receiver android:name=".BpPanicReceiver">
+ <intent-filter>
+ <action android:name="android.intent.action.BOOT_COMPLETED" />
+ </intent-filter>
+ </receiver>
+
+ <service android:name=".BpPanicHandlerService" />
</application>
</manifest>
View
9 MmParts/res/values-de/strings.xml
@@ -42,5 +42,12 @@
<string name="ui_status_bar_oneperc_battery_title">Batterie in 1% Schritten</string>
<string name="ui_status_bar_oneperc_battery_summary">Zeigt den Ladezustand der Batterie in 1% Schritten. Kann Probleme mit Batterien und Ladegeräten von Fremdherstellern verursachen. (erfordert Neustart)</string>
-
+ <string name="modem_error">Modem-Problem</string>
+ <string name="touch_for_info">Berühren für Informationen</string>
+ <string name="reboot_timeout_msg">Wenn keine Option gewählt wird, wird das Gerät in %1$d Sekunden neu gestartet.</string>
+ <string name="modem_error_msg">Im Modem des Telefons wurde ein Problem festgestellt. Um es zu beheben, muss das Gerät neu gestartet werden.\nWas möchten Sie tun?</string>
+ <string name="reboot_btn">Neu starten</string>
+ <string name="snooze_btn">Später erinnern</string>
+ <string name="dismiss_btn">Nicht mehr erinnern</string>
+ <string name="device_rebooted_modem_error">Das Gerät wurde auf Grund eines Problems im Modem des Telefons neu gestartet.</string>
</resources>
View
8 MmParts/res/values/strings.xml
@@ -41,4 +41,12 @@
<string name="ui_status_bar_oneperc_battery_title">1% battery steps</string>
<string name="ui_status_bar_oneperc_battery_summary">Show battery percentage in 1% steps. May cause issues with third party batteries and AC adapters. (Requires reboot)</string>
+ <string name="modem_error">Telephony problem</string>
+ <string name="touch_for_info">Touch for information</string>
+ <string name="reboot_timeout_msg">If no action is selected, the device will reboot in %1$d seconds.</string>
+ <string name="modem_error_msg">A problem was detected in the phone\'s telephony layer. A reboot of the phone is required to repair the phone state.\nWhat do you want to do?</string>
+ <string name="reboot_btn">Reboot now</string>
+ <string name="snooze_btn">Remind again later</string>
+ <string name="dismiss_btn">Don\'t remind again</string>
+ <string name="device_rebooted_modem_error">The device was rebooted due to a problem in the phone\'s telephony layer.</string>
</resources>
View
134 MmParts/src/com/cyanogenmod/mmparts/BpPanicHandlerService.java
@@ -0,0 +1,134 @@
+package com.cyanogenmod.mmparts;
+
+import android.app.AlarmManager;
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.SharedPreferences;
+import android.graphics.Color;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.PowerManager;
+import android.preference.PreferenceManager;
+import android.text.TextUtils;
+import android.util.Log;
+
+public class BpPanicHandlerService extends Service {
+ private static final String TAG = "BpPanicHandlerService";
+ private static final int NOTIFICATION_ID = 1;
+
+ private static final String ACTION_HANDLE_PANIC = "com.cyanogenmod.mmparts.action.HANDLE_BP_PANIC";
+ static final String ACTION_TIMER_UPDATE = "com.cyanogenmod.mmparts.action.TIMER_UPDATE";
+ static final String ACTION_REBOOT = "com.cyanogenmod.mmparts.action.BP_PANIC_REBOOT";
+ static final String ACTION_SNOOZE = "com.cyanogenmod.mmparts.action.REMIND_LATER";
+ static final String ACTION_DISMISS = "com.cyanogenmod.mmparts.action.DISMISS";
+
+ static final String EXTRA_TIMEOUT = "timeout";
+
+ static final String KEY_NEED_REBOOT_NOTICE = "need_bppanic_reboot_notice";
+
+ private static final long SNOOZE_DELAY = 5 * 60 * 1000; /* 5 minutes */
+ private static final long REBOOT_TIMEOUT = 60 * 1000; /* 1 minute */
+
+ private SharedPreferences mPrefs;
+ private AlarmManager mAM;
+ private long mRebootTimeout = -1;
+ private Notification mNotification;
+ private Intent mNotifyIntent;
+ private PendingIntent mTimerUpdateIntent;
+ private PendingIntent mPanicHandleIntent;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+
+ mAM = (AlarmManager) getSystemService(ALARM_SERVICE);
+ mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
+
+ Intent intent = new Intent(this, getClass());
+ intent.setAction(ACTION_HANDLE_PANIC);
+ mPanicHandleIntent = PendingIntent.getService(this, 0, intent, 0);
+
+ intent = new Intent(this, getClass());
+ intent.setAction(ACTION_TIMER_UPDATE);
+ mTimerUpdateIntent = PendingIntent.getService(this, 1, intent, 0);
+
+ mNotifyIntent = new Intent(this, BpPanicNotifyActivity.class);
+ mNotifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ String action = intent.getAction();
+
+ if (TextUtils.equals(action, ACTION_HANDLE_PANIC)) {
+ Log.d(TAG, "Got BP panic intent");
+ if (mNotification == null) {
+ mNotification = createNotification();
+ }
+ mRebootTimeout = System.currentTimeMillis() + REBOOT_TIMEOUT;
+ updateTimeout();
+ startActivity(mNotifyIntent);
+ startForeground(NOTIFICATION_ID, mNotification);
+ } else if (TextUtils.equals(action, ACTION_REBOOT)) {
+ doReboot(false);
+ } else if (TextUtils.equals(action, ACTION_SNOOZE)) {
+ cancelTimeout();
+ schedule(mPanicHandleIntent, SNOOZE_DELAY);
+ } else if (TextUtils.equals(action, ACTION_DISMISS)) {
+ cancelTimeout();
+ } else if (TextUtils.equals(action, ACTION_TIMER_UPDATE)) {
+ updateTimeout();
+ }
+
+ return START_STICKY;
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ private void schedule(PendingIntent intent, long timeout) {
+ mAM.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + timeout, intent);
+ }
+
+ private void cancelTimeout() {
+ removeStickyBroadcast(new Intent(ACTION_TIMER_UPDATE));
+ mRebootTimeout = -1;
+ mAM.cancel(mTimerUpdateIntent);
+ }
+
+ private Notification createNotification() {
+ Notification notification = new Notification(android.R.drawable.stat_notify_error, null, System.currentTimeMillis());
+ notification.defaults |= Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE;
+ notification.flags |= Notification.FLAG_ONGOING_EVENT | Notification.FLAG_SHOW_LIGHTS;
+ notification.ledARGB = Color.RED;
+ notification.ledOnMS = 1000;
+ notification.ledOffMS = 0;
+ notification.setLatestEventInfo(this,
+ getString(R.string.modem_error),
+ getString(R.string.touch_for_info),
+ PendingIntent.getActivity(this, 0, mNotifyIntent, 0));
+
+ return notification;
+ }
+
+ private void updateTimeout() {
+ int timeout = (int) (mRebootTimeout - System.currentTimeMillis() + 500) / 1000;
+ if (timeout <= 0) {
+ doReboot(true);
+ } else {
+ Intent intent = new Intent(ACTION_TIMER_UPDATE);
+ intent.putExtra(EXTRA_TIMEOUT, timeout);
+ sendStickyBroadcast(intent);
+ schedule(mTimerUpdateIntent, timeout <= 5 ? 1000 : 5000);
+ }
+ }
+
+ private void doReboot(boolean requireNotice) {
+ PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
+ mPrefs.edit().putBoolean(KEY_NEED_REBOOT_NOTICE, requireNotice).commit();
+ pm.reboot("bppanic");
+ }
+}
View
100 MmParts/src/com/cyanogenmod/mmparts/BpPanicNotifyActivity.java
@@ -0,0 +1,100 @@
+package com.cyanogenmod.mmparts;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+
+public class BpPanicNotifyActivity extends Activity implements DialogInterface.OnClickListener {
+ private static final int DIALOG_ACTION_SELECT = 1;
+
+ private AlertDialog mDialog;
+
+ private BroadcastReceiver mTimerUpdateReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int timeout = intent.getIntExtra(BpPanicHandlerService.EXTRA_TIMEOUT, -1);
+ updateDialogMessage(timeout);
+ }
+ };
+
+ @Override
+ protected Dialog onCreateDialog(int id, Bundle args) {
+ if (id == DIALOG_ACTION_SELECT) {
+ mDialog = new AlertDialog.Builder(this)
+ .setTitle(R.string.modem_error)
+ .setMessage(R.string.modem_error_msg)
+ .setCancelable(false)
+ .setPositiveButton(R.string.reboot_btn, this)
+ .setNeutralButton(R.string.snooze_btn, this)
+ .setNegativeButton(R.string.dismiss_btn, this)
+ .create();
+ return mDialog;
+ }
+
+ return super.onCreateDialog(id, args);
+ }
+
+ @Override
+ protected void onPrepareDialog(int id, Dialog dialog, Bundle args) {
+ if (id == DIALOG_ACTION_SELECT) {
+ updateDialogMessage(-1);
+ }
+ super.onPrepareDialog(id, dialog, args);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ showDialog(DIALOG_ACTION_SELECT);
+ registerReceiver(mTimerUpdateReceiver, new IntentFilter(BpPanicHandlerService.ACTION_TIMER_UPDATE));
+ }
+
+ @Override
+ protected void onPause() {
+ unregisterReceiver(mTimerUpdateReceiver);
+ super.onPause();
+ }
+
+ private void doServiceAction(String action) {
+ Intent intent = new Intent(this, BpPanicHandlerService.class);
+ intent.setAction(action);
+ startService(intent);
+ }
+
+ public void onClick(DialogInterface dialog, int which) {
+ String action;
+
+ switch (which) {
+ case DialogInterface.BUTTON_POSITIVE:
+ action = BpPanicHandlerService.ACTION_REBOOT;
+ break;
+ case DialogInterface.BUTTON_NEUTRAL:
+ action = BpPanicHandlerService.ACTION_SNOOZE;
+ break;
+ case DialogInterface.BUTTON_NEGATIVE:
+ action = BpPanicHandlerService.ACTION_DISMISS;
+ break;
+ default:
+ return;
+ }
+
+ doServiceAction(action);
+ finish();
+ }
+
+ private void updateDialogMessage(int timeout) {
+ StringBuilder message = new StringBuilder();
+ message.append(getString(R.string.modem_error_msg));
+ if (timeout >= 0) {
+ message.append("\n\n");
+ message.append(getString(R.string.reboot_timeout_msg, timeout));
+ }
+ mDialog.setMessage(message.toString());
+ }
+}
View
47 MmParts/src/com/cyanogenmod/mmparts/BpPanicRebootNoticeActivity.java
@@ -0,0 +1,47 @@
+package com.cyanogenmod.mmparts;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+
+public class BpPanicRebootNoticeActivity extends Activity {
+ private static final int DIALOG_NOTICE = 1;
+
+ @Override
+ protected Dialog onCreateDialog(int id, Bundle args) {
+ if (id == DIALOG_NOTICE) {
+ return new AlertDialog.Builder(this)
+ .setTitle(R.string.modem_error)
+ .setMessage(R.string.device_rebooted_modem_error)
+ .setNegativeButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.cancel();
+ }
+ })
+ .setOnCancelListener(new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ finish();
+ }
+ })
+ .create();
+ }
+
+ return super.onCreateDialog(id, args);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ showDialog(DIALOG_NOTICE);
+ }
+
+ @Override
+ protected void onPause() {
+ dismissDialog(DIALOG_NOTICE);
+ super.onPause();
+ }
+}
View
26 MmParts/src/com/cyanogenmod/mmparts/BpPanicReceiver.java
@@ -0,0 +1,26 @@
+package com.cyanogenmod.mmparts;
+
+import android.app.AlertDialog;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+
+public class BpPanicReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+
+ if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ if (prefs.getBoolean(BpPanicHandlerService.KEY_NEED_REBOOT_NOTICE, false)) {
+ Intent noticeIntent = new Intent(context, BpPanicRebootNoticeActivity.class);
+ noticeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ context.startActivity(noticeIntent);
+ prefs.edit().putBoolean(BpPanicHandlerService.KEY_NEED_REBOOT_NOTICE, false).commit();
+ }
+ }
+ }
+}
View
11 prebuilt/bin/handle_bp_panic.sh
@@ -0,0 +1,11 @@
+#!/system/bin/sh
+
+# stop panic_daemon restarting
+setprop ctl.stop panic_daemon
+
+# let UI handle the failure
+am startservice -a com.cyanogenmod.mmparts.action.HANDLE_BP_PANIC -n com.cyanogenmod.mmparts/.BpPanicHandlerService 2>&1 | grep Error
+if [ $? -eq 0 ]; then
+ # some error occured, use fallback and reboot directly
+ reboot bppanic
+fi
View
2 rootfs/init.mapphone_umts.rc
@@ -501,7 +501,7 @@ service panic_daemon /system/bin/panic_daemon
user radio
group radio system graphics
socket panic_daemon stream 660 radio radio
- onrestart exec /system/bin/reboot
+ onrestart exec /system/bin/sh /system/bin/handle_bp_panic.sh
# Ecompass daemon
service akmd2 /system/bin/akmd2
View
3 umts_sholes.mk
@@ -64,6 +64,9 @@ PRODUCT_COPY_FILES += \
PRODUCT_COPY_FILES += \
device/motorola/umts_sholes/sysctl.conf:system/etc/sysctl.conf
+PRODUCT_COPY_FILES += \
+ device/motorola/umts_sholes/prebuilt/bin/handle_bp_panic.sh:system/bin/handle_bp_panic.sh
+
# TLS enable hack
# /system/bin/akmd2 - proprietary binary daemon patched for compatibility
# with real TLS register usage

0 comments on commit a0ad7d2

Please sign in to comment.
Something went wrong with that request. Please try again.