From ecf9da8218279f778dbdd207cdd9096fb5e2db42 Mon Sep 17 00:00:00 2001 From: Netta Peterbursky Date: Mon, 18 Dec 2017 11:07:59 -0800 Subject: [PATCH 1/3] Print out CRASH info when monkey encounters tombstone. Bug: 68762010 Test: Run monkey + manually add tombstone Change-Id: I8c819ad42d1dd09b98a575a8a761041dded3d7ba (cherry picked from commit 7dcd1ea28aa85748b0b01d05277158c21829110f) --- .../com/android/commands/monkey/Monkey.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/cmds/monkey/src/com/android/commands/monkey/Monkey.java b/cmds/monkey/src/com/android/commands/monkey/Monkey.java index 3b1e39b46..6cf9cecc9 100644 --- a/cmds/monkey/src/com/android/commands/monkey/Monkey.java +++ b/cmds/monkey/src/com/android/commands/monkey/Monkey.java @@ -44,6 +44,9 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Writer; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.ArrayList; import java.util.HashSet; @@ -51,6 +54,8 @@ import java.util.Iterator; import java.util.List; import java.util.Random; import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * Application that injects random key events and other actions into the system. @@ -240,6 +245,10 @@ public class Monkey { private static final String TOMBSTONE_PREFIX = "tombstone_"; + /** Example: "pid: 5379, tid: 8345, name: RenderThread >>> com.google.android.gms.ui <<<" */ + private static final Pattern TOMBSTONE_PROCESS_PATTERN = + Pattern.compile("^pid: (\\d+).*\\>\\>\\> (.*) \\<\\<\\<$"); + private HashSet mTombstones = null; float[] mFactors = new float[MonkeySourceRandom.FACTORZ_COUNT]; @@ -1293,6 +1302,7 @@ public class Monkey { newStones.add(f.lastModified()); if (mTombstones == null || !mTombstones.contains(f.lastModified())) { result = true; + printNativeCrashFromTombstone(Paths.get(TOMBSTONES_PATH.getPath(), t)); Logger.out.println("** New tombstone found: " + f.getAbsolutePath() + ", size: " + f.length()); } @@ -1305,6 +1315,24 @@ public class Monkey { return result; } + private void printNativeCrashFromTombstone(Path path) { + try { + List lines = Files.readAllLines(path); + for (String line : lines) { + final Matcher matcher = TOMBSTONE_PROCESS_PATTERN.matcher(line); + if (!matcher.matches()) + continue; + final String pid = matcher.group(1); + final String process = matcher.group(2); + Logger.out.println("// CRASH: " + process + " (pid " + pid + ")"); + return; + } + Logger.err.println("Process not found in tombstone file."); + } catch (IOException e) { + Logger.err.println("Failed to read tombstone file: " + e.toString()); + } + } + /** * Return the next command line option. This has a number of special cases * which closely, but not exactly, follow the POSIX command line options From 665141334fdeeeb337bcc667dd320942a95f2243 Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Thu, 25 Jan 2018 12:55:58 -0800 Subject: [PATCH 2/3] Revert "Fix issue #72116995: Add permission guarding Service#startForeground" This reverts commit cbe2f1bf274a5fb31f20f6da9810c9b7552b23d4. Test: NA Bug: 72116995 (cherry picked from commit 0d3c8bac64616e3dce61fa49321e5205422adc9d) Change-Id: I1edc9a03f9ff3c655a8ebc2d181aaf8366aeec0b --- samples/ApiDemos/AndroidManifest.xml | 1 - .../android/apis/app/ForegroundService.java | 137 +++++++++++++++--- samples/ToyVpn/AndroidManifest.xml | 1 - .../AndroidManifest.xml | 1 - .../MediaBrowserService/AndroidManifest.xml | 1 - 5 files changed, 116 insertions(+), 25 deletions(-) diff --git a/samples/ApiDemos/AndroidManifest.xml b/samples/ApiDemos/AndroidManifest.xml index 7efa922b6..030184982 100644 --- a/samples/ApiDemos/AndroidManifest.xml +++ b/samples/ApiDemos/AndroidManifest.xml @@ -39,7 +39,6 @@ - diff --git a/samples/ApiDemos/src/com/example/android/apis/app/ForegroundService.java b/samples/ApiDemos/src/com/example/android/apis/app/ForegroundService.java index 8d34b0c9f..a8c3b868b 100644 --- a/samples/ApiDemos/src/com/example/android/apis/app/ForegroundService.java +++ b/samples/ApiDemos/src/com/example/android/apis/app/ForegroundService.java @@ -52,7 +52,119 @@ public class ForegroundService extends Service { static final String ACTION_BACKGROUND = "com.example.android.apis.BACKGROUND"; static final String ACTION_BACKGROUND_WAKELOCK = "com.example.android.apis.BACKGROUND_WAKELOCK"; + // BEGIN_INCLUDE(foreground_compatibility) + private static final Class[] mSetForegroundSignature = new Class[] { + boolean.class}; + private static final Class[] mStartForegroundSignature = new Class[] { + int.class, Notification.class}; + private static final Class[] mStopForegroundSignature = new Class[] { + boolean.class}; + private NotificationManager mNM; + private Method mSetForeground; + private Method mStartForeground; + private Method mStopForeground; + private Object[] mSetForegroundArgs = new Object[1]; + private Object[] mStartForegroundArgs = new Object[2]; + private Object[] mStopForegroundArgs = new Object[1]; + + void invokeMethod(Method method, Object[] args) { + try { + method.invoke(this, args); + } catch (InvocationTargetException e) { + // Should not happen. + Log.w("ApiDemos", "Unable to invoke method", e); + } catch (IllegalAccessException e) { + // Should not happen. + Log.w("ApiDemos", "Unable to invoke method", e); + } + } + + /** + * This is a wrapper around the new startForeground method, using the older + * APIs if it is not available. + */ + void startForegroundCompat(int id, Notification notification) { + // If we have the new startForeground API, then use it. + if (mStartForeground != null) { + mStartForegroundArgs[0] = Integer.valueOf(id); + mStartForegroundArgs[1] = notification; + invokeMethod(mStartForeground, mStartForegroundArgs); + return; + } + + // Fall back on the old API. + mSetForegroundArgs[0] = Boolean.TRUE; + invokeMethod(mSetForeground, mSetForegroundArgs); + mNM.notify(id, notification); + } + + /** + * This is a wrapper around the new stopForeground method, using the older + * APIs if it is not available. + */ + void stopForegroundCompat(int id) { + // If we have the new stopForeground API, then use it. + if (mStopForeground != null) { + mStopForegroundArgs[0] = Boolean.TRUE; + invokeMethod(mStopForeground, mStopForegroundArgs); + return; + } + + // Fall back on the old API. Note to cancel BEFORE changing the + // foreground state, since we could be killed at that point. + mNM.cancel(id); + mSetForegroundArgs[0] = Boolean.FALSE; + invokeMethod(mSetForeground, mSetForegroundArgs); + } + + @Override + public void onCreate() { + mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); + try { + mStartForeground = getClass().getMethod("startForeground", + mStartForegroundSignature); + mStopForeground = getClass().getMethod("stopForeground", + mStopForegroundSignature); + return; + } catch (NoSuchMethodException e) { + // Running on an older platform. + mStartForeground = mStopForeground = null; + } + try { + mSetForeground = getClass().getMethod("setForeground", + mSetForegroundSignature); + } catch (NoSuchMethodException e) { + throw new IllegalStateException( + "OS doesn't have Service.startForeground OR Service.setForeground!"); + } + } + + @Override + public void onDestroy() { + handleDestroy(); + // Make sure our notification is gone. + stopForegroundCompat(R.string.foreground_service_started); + } +// END_INCLUDE(foreground_compatibility) + +// BEGIN_INCLUDE(start_compatibility) + // This is the old onStart method that will be called on the pre-2.0 + // platform. On 2.0 or later we override onStartCommand() so this + // method will not be called. + @Override + public void onStart(Intent intent, int startId) { + handleCommand(intent); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + handleCommand(intent); + // We want this service to continue running until it is explicitly + // stopped, so return sticky. + return START_STICKY; + } +// END_INCLUDE(start_compatibility) private PowerManager.WakeLock mWakeLock; private Handler mHandler = new Handler(); @@ -63,20 +175,7 @@ public class ForegroundService extends Service { } }; - @Override - public void onCreate() { - mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); - } - - @Override - public void onDestroy() { - handleDestroy(); - // Make sure our notification is gone. - stopForeground(R.string.foreground_service_started); - } - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { + void handleCommand(Intent intent) { if (ACTION_FOREGROUND.equals(intent.getAction()) || ACTION_FOREGROUND_WAKELOCK.equals(intent.getAction())) { // In this sample, we'll use the same text for the ticker and the expanded notification @@ -95,11 +194,11 @@ public class ForegroundService extends Service { .setContentIntent(contentIntent) // The intent to send when clicked .build(); - startForeground(R.string.foreground_service_started, notification); - + startForegroundCompat(R.string.foreground_service_started, notification); + } else if (ACTION_BACKGROUND.equals(intent.getAction()) || ACTION_BACKGROUND_WAKELOCK.equals(intent.getAction())) { - stopForeground(R.string.foreground_service_started); + stopForegroundCompat(R.string.foreground_service_started); } if (ACTION_FOREGROUND_WAKELOCK.equals(intent.getAction()) @@ -115,10 +214,6 @@ public class ForegroundService extends Service { mHandler.removeCallbacks(mPulser); mPulser.run(); - - // We want this service to continue running until it is explicitly - // stopped, so return sticky. - return START_STICKY; } void releaseWakeLock() { diff --git a/samples/ToyVpn/AndroidManifest.xml b/samples/ToyVpn/AndroidManifest.xml index 5f1cc2b09..8366dd6bc 100644 --- a/samples/ToyVpn/AndroidManifest.xml +++ b/samples/ToyVpn/AndroidManifest.xml @@ -17,7 +17,6 @@ - diff --git a/samples/browseable/BluetoothAdvertisements/AndroidManifest.xml b/samples/browseable/BluetoothAdvertisements/AndroidManifest.xml index 571a08f5f..cd2a65e59 100644 --- a/samples/browseable/BluetoothAdvertisements/AndroidManifest.xml +++ b/samples/browseable/BluetoothAdvertisements/AndroidManifest.xml @@ -21,7 +21,6 @@ - - From 52eee0e1514f866da1d6086cb550093707a8d095 Mon Sep 17 00:00:00 2001 From: Ian Pedowitz Date: Mon, 12 Feb 2018 16:12:26 +0000 Subject: [PATCH 3/3] Revert "Fix issue #72116995: Add permission guarding Service#startForeground" This reverts commit 7890baea48dba67c3c4aa2b07709ead409f16240. Reason for revert: b/73224471 Bug: 73224471 Bug: 72116995 Change-Id: Ife5dc5c14026ae7dcb126b0b3c3e7701ed3eaebe (cherry picked from commit b19c1b8ec6b26e16466ae3a6ccbf0e10a1efd9b0) --- samples/ApiDemos/AndroidManifest.xml | 1 - .../android/apis/app/ForegroundService.java | 137 +++++++++++++++--- samples/ToyVpn/AndroidManifest.xml | 1 - .../AndroidManifest.xml | 1 - .../MediaBrowserService/AndroidManifest.xml | 1 - 5 files changed, 116 insertions(+), 25 deletions(-) diff --git a/samples/ApiDemos/AndroidManifest.xml b/samples/ApiDemos/AndroidManifest.xml index 7efa922b6..030184982 100644 --- a/samples/ApiDemos/AndroidManifest.xml +++ b/samples/ApiDemos/AndroidManifest.xml @@ -39,7 +39,6 @@ - diff --git a/samples/ApiDemos/src/com/example/android/apis/app/ForegroundService.java b/samples/ApiDemos/src/com/example/android/apis/app/ForegroundService.java index 8d34b0c9f..a8c3b868b 100644 --- a/samples/ApiDemos/src/com/example/android/apis/app/ForegroundService.java +++ b/samples/ApiDemos/src/com/example/android/apis/app/ForegroundService.java @@ -52,7 +52,119 @@ public class ForegroundService extends Service { static final String ACTION_BACKGROUND = "com.example.android.apis.BACKGROUND"; static final String ACTION_BACKGROUND_WAKELOCK = "com.example.android.apis.BACKGROUND_WAKELOCK"; + // BEGIN_INCLUDE(foreground_compatibility) + private static final Class[] mSetForegroundSignature = new Class[] { + boolean.class}; + private static final Class[] mStartForegroundSignature = new Class[] { + int.class, Notification.class}; + private static final Class[] mStopForegroundSignature = new Class[] { + boolean.class}; + private NotificationManager mNM; + private Method mSetForeground; + private Method mStartForeground; + private Method mStopForeground; + private Object[] mSetForegroundArgs = new Object[1]; + private Object[] mStartForegroundArgs = new Object[2]; + private Object[] mStopForegroundArgs = new Object[1]; + + void invokeMethod(Method method, Object[] args) { + try { + method.invoke(this, args); + } catch (InvocationTargetException e) { + // Should not happen. + Log.w("ApiDemos", "Unable to invoke method", e); + } catch (IllegalAccessException e) { + // Should not happen. + Log.w("ApiDemos", "Unable to invoke method", e); + } + } + + /** + * This is a wrapper around the new startForeground method, using the older + * APIs if it is not available. + */ + void startForegroundCompat(int id, Notification notification) { + // If we have the new startForeground API, then use it. + if (mStartForeground != null) { + mStartForegroundArgs[0] = Integer.valueOf(id); + mStartForegroundArgs[1] = notification; + invokeMethod(mStartForeground, mStartForegroundArgs); + return; + } + + // Fall back on the old API. + mSetForegroundArgs[0] = Boolean.TRUE; + invokeMethod(mSetForeground, mSetForegroundArgs); + mNM.notify(id, notification); + } + + /** + * This is a wrapper around the new stopForeground method, using the older + * APIs if it is not available. + */ + void stopForegroundCompat(int id) { + // If we have the new stopForeground API, then use it. + if (mStopForeground != null) { + mStopForegroundArgs[0] = Boolean.TRUE; + invokeMethod(mStopForeground, mStopForegroundArgs); + return; + } + + // Fall back on the old API. Note to cancel BEFORE changing the + // foreground state, since we could be killed at that point. + mNM.cancel(id); + mSetForegroundArgs[0] = Boolean.FALSE; + invokeMethod(mSetForeground, mSetForegroundArgs); + } + + @Override + public void onCreate() { + mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); + try { + mStartForeground = getClass().getMethod("startForeground", + mStartForegroundSignature); + mStopForeground = getClass().getMethod("stopForeground", + mStopForegroundSignature); + return; + } catch (NoSuchMethodException e) { + // Running on an older platform. + mStartForeground = mStopForeground = null; + } + try { + mSetForeground = getClass().getMethod("setForeground", + mSetForegroundSignature); + } catch (NoSuchMethodException e) { + throw new IllegalStateException( + "OS doesn't have Service.startForeground OR Service.setForeground!"); + } + } + + @Override + public void onDestroy() { + handleDestroy(); + // Make sure our notification is gone. + stopForegroundCompat(R.string.foreground_service_started); + } +// END_INCLUDE(foreground_compatibility) + +// BEGIN_INCLUDE(start_compatibility) + // This is the old onStart method that will be called on the pre-2.0 + // platform. On 2.0 or later we override onStartCommand() so this + // method will not be called. + @Override + public void onStart(Intent intent, int startId) { + handleCommand(intent); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + handleCommand(intent); + // We want this service to continue running until it is explicitly + // stopped, so return sticky. + return START_STICKY; + } +// END_INCLUDE(start_compatibility) private PowerManager.WakeLock mWakeLock; private Handler mHandler = new Handler(); @@ -63,20 +175,7 @@ public class ForegroundService extends Service { } }; - @Override - public void onCreate() { - mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); - } - - @Override - public void onDestroy() { - handleDestroy(); - // Make sure our notification is gone. - stopForeground(R.string.foreground_service_started); - } - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { + void handleCommand(Intent intent) { if (ACTION_FOREGROUND.equals(intent.getAction()) || ACTION_FOREGROUND_WAKELOCK.equals(intent.getAction())) { // In this sample, we'll use the same text for the ticker and the expanded notification @@ -95,11 +194,11 @@ public class ForegroundService extends Service { .setContentIntent(contentIntent) // The intent to send when clicked .build(); - startForeground(R.string.foreground_service_started, notification); - + startForegroundCompat(R.string.foreground_service_started, notification); + } else if (ACTION_BACKGROUND.equals(intent.getAction()) || ACTION_BACKGROUND_WAKELOCK.equals(intent.getAction())) { - stopForeground(R.string.foreground_service_started); + stopForegroundCompat(R.string.foreground_service_started); } if (ACTION_FOREGROUND_WAKELOCK.equals(intent.getAction()) @@ -115,10 +214,6 @@ public class ForegroundService extends Service { mHandler.removeCallbacks(mPulser); mPulser.run(); - - // We want this service to continue running until it is explicitly - // stopped, so return sticky. - return START_STICKY; } void releaseWakeLock() { diff --git a/samples/ToyVpn/AndroidManifest.xml b/samples/ToyVpn/AndroidManifest.xml index 5f1cc2b09..8366dd6bc 100644 --- a/samples/ToyVpn/AndroidManifest.xml +++ b/samples/ToyVpn/AndroidManifest.xml @@ -17,7 +17,6 @@ - diff --git a/samples/browseable/BluetoothAdvertisements/AndroidManifest.xml b/samples/browseable/BluetoothAdvertisements/AndroidManifest.xml index 571a08f5f..cd2a65e59 100644 --- a/samples/browseable/BluetoothAdvertisements/AndroidManifest.xml +++ b/samples/browseable/BluetoothAdvertisements/AndroidManifest.xml @@ -21,7 +21,6 @@ - -