OSDN Git Service

Call System.exit(0) in onDestroy
authorJack He <siyuanh@google.com>
Tue, 21 Mar 2017 23:50:56 +0000 (16:50 -0700)
committerJack He <siyuanh@google.com>
Wed, 22 Mar 2017 00:38:58 +0000 (17:38 -0700)
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

src/com/android/bluetooth/btservice/AdapterService.java
tests/src/com/android/bluetooth/btservice/PhonePolicyTest.java

index 124f22a..10e2e01 100644 (file)
@@ -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;
+    }
 }
index 1ae4571..6713539 100644 (file)
@@ -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