From: Jack He Date: Tue, 21 Mar 2017 23:50:56 +0000 (-0700) Subject: Call System.exit(0) in onDestroy X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=33e325b5c50001d9eb6c9d53cc0a258aa93c9dd1;p=android-x86%2Fpackages-apps-Bluetooth.git Call System.exit(0) in onDestroy Call System.exit(0) in onDestroy() to make sure state is cleared in the Bluetooth stack when Bluetooth is disabled Bug: 27859763 Bug: 36487153 Test: Build, run unit tests, Bluetooth enable/disable Change-Id: I34917ca3302b01c4da74b969da08860d6fbf8274 --- diff --git a/src/com/android/bluetooth/btservice/AdapterService.java b/src/com/android/bluetooth/btservice/AdapterService.java index 124f22ad..10e2e01e 100644 --- a/src/com/android/bluetooth/btservice/AdapterService.java +++ b/src/com/android/bluetooth/btservice/AdapterService.java @@ -464,6 +464,11 @@ public class AdapterService extends Service { public void onDestroy() { debugLog("onDestroy()"); mProfileObserver.stop(); + if (!isMock()) { + // TODO(b/27859763) + Log.i(TAG, "Force exit to cleanup internal state in Bluetooth stack"); + System.exit(0); + } } void BleOnProcessStart() { @@ -2302,4 +2307,14 @@ public class AdapterService extends Service { } } } + + // Returns if this is a mock object. This is currently used in testing so that we may not call + // System.exit() while finalizing the object. Otherwise GC of mock objects unfortunately ends up + // calling finalize() which in turn calls System.exit() and the process crashes. + // + // Mock this in your testing framework to return true to avoid the mentioned behavior. In + // production this has no effect. + public boolean isMock() { + return false; + } } diff --git a/tests/src/com/android/bluetooth/btservice/PhonePolicyTest.java b/tests/src/com/android/bluetooth/btservice/PhonePolicyTest.java index 1ae45717..6713539e 100644 --- a/tests/src/com/android/bluetooth/btservice/PhonePolicyTest.java +++ b/tests/src/com/android/bluetooth/btservice/PhonePolicyTest.java @@ -91,6 +91,9 @@ public class PhonePolicyTest extends AndroidTestCase { // Mock the looper when(mockAdapterService.getMainLooper()).thenReturn(mHandlerThread.getLooper()); + // Tell the AdapterService that it is a mock (see isMock documentation) + when(mockAdapterService.isMock()).thenReturn(true); + PhonePolicy phPol = new PhonePolicy(mockAdapterService, mockServiceFactory); // Get the broadcast receiver to inject events. @@ -147,6 +150,9 @@ public class PhonePolicyTest extends AndroidTestCase { // Mock the looper when(mockAdapterService.getMainLooper()).thenReturn(mHandlerThread.getLooper()); + // Tell the AdapterService that it is a mock (see isMock documentation) + when(mockAdapterService.isMock()).thenReturn(true); + PhonePolicy phPol = new PhonePolicy(mockAdapterService, mockServiceFactory); // Get the broadcast receiver to inject events @@ -195,6 +201,9 @@ public class PhonePolicyTest extends AndroidTestCase { // Mock the looper when(mockAdapterService.getMainLooper()).thenReturn(mHandlerThread.getLooper()); + // Tell the AdapterService that it is a mock (see isMock documentation) + when(mockAdapterService.isMock()).thenReturn(true); + PhonePolicy phPol = new PhonePolicy(mockAdapterService, mockServiceFactory); // Get the broadcast receiver to inject events @@ -254,6 +263,9 @@ public class PhonePolicyTest extends AndroidTestCase { // Mock the looper when(mockAdapterService.getMainLooper()).thenReturn(mHandlerThread.getLooper()); + // Tell the AdapterService that it is a mock (see isMock documentation) + when(mockAdapterService.isMock()).thenReturn(true); + PhonePolicy phPol = new PhonePolicy(mockAdapterService, mockServiceFactory); // Get the broadcast receiver to inject events