android: add a uncaught exception handler
Its main task is to cleanup conferences (specially the connection services stuff) to make sure the system is left in a working state even when the unexpected happens.
This commit is contained in:
parent
bf67a4a675
commit
803870ef8f
|
@ -29,6 +29,7 @@ import com.facebook.react.bridge.ReadableMap;
|
||||||
import com.rnimmersive.RNImmersiveModule;
|
import com.rnimmersive.RNImmersiveModule;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -77,6 +78,15 @@ public abstract class BaseReactView<ListenerT>
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all registered React views.
|
||||||
|
*
|
||||||
|
* @return An {@link ArrayList} containing all views currently held by React.
|
||||||
|
*/
|
||||||
|
static ArrayList<BaseReactView> getViews() {
|
||||||
|
return new ArrayList<>(views);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The unique identifier of this {@code BaseReactView} within the process
|
* The unique identifier of this {@code BaseReactView} within the process
|
||||||
* for the purposes of {@link ExternalAPIModule}. The name scope was
|
* for the purposes of {@link ExternalAPIModule}. The name scope was
|
||||||
|
|
|
@ -63,6 +63,16 @@ public class ConnectionService extends android.telecom.ConnectionService {
|
||||||
static private final HashMap<String, Promise> startCallPromises
|
static private final HashMap<String, Promise> startCallPromises
|
||||||
= new HashMap<>();
|
= new HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Aborts all ongoing connections. This is a last resort mechanism which forces all resources to
|
||||||
|
* be freed on the system in case of fatal error.
|
||||||
|
*/
|
||||||
|
static void abortConnections() {
|
||||||
|
for (ConnectionImpl connection: getConnections()) {
|
||||||
|
connection.onAbort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds {@link ConnectionImpl} to the list.
|
* Adds {@link ConnectionImpl} to the list.
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Copyright @ 2018-present 8x8, Inc.
|
||||||
|
* Copyright @ 2017-2018 Atlassian Pty Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jitsi.meet.sdk;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
class JitsiMeetUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
|
||||||
|
private final Thread.UncaughtExceptionHandler defaultUncaughtExceptionHandler;
|
||||||
|
|
||||||
|
public static void register() {
|
||||||
|
Thread.UncaughtExceptionHandler defaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
|
||||||
|
|
||||||
|
JitsiMeetUncaughtExceptionHandler uncaughtExceptionHandler
|
||||||
|
= new JitsiMeetUncaughtExceptionHandler(defaultUncaughtExceptionHandler);
|
||||||
|
|
||||||
|
Thread.setDefaultUncaughtExceptionHandler(uncaughtExceptionHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
private JitsiMeetUncaughtExceptionHandler(Thread.UncaughtExceptionHandler defaultUncaughtExceptionHandler) {
|
||||||
|
this.defaultUncaughtExceptionHandler = defaultUncaughtExceptionHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void uncaughtException(Thread t, Throwable e) {
|
||||||
|
Log.e(this.getClass().getSimpleName(), "FATAL ERROR", e);
|
||||||
|
|
||||||
|
// Terminate all conferences
|
||||||
|
for (BaseReactView view: BaseReactView.getViews()) {
|
||||||
|
if (view instanceof JitsiMeetView) {
|
||||||
|
((JitsiMeetView) view).leave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Abort all ConnectionService ongoing calls
|
||||||
|
if (AudioModeModule.useConnectionService()) {
|
||||||
|
ConnectionService.abortConnections();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defaultUncaughtExceptionHandler != null) {
|
||||||
|
defaultUncaughtExceptionHandler.uncaughtException(t, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -182,5 +182,8 @@ class ReactInstanceManagerHolder {
|
||||||
if (devSettings != null) {
|
if (devSettings != null) {
|
||||||
devSettings.setBundleDeltasEnabled(false);
|
devSettings.setBundleDeltasEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Register our uncaught exception handler.
|
||||||
|
JitsiMeetUncaughtExceptionHandler.register();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue