Procházet zdrojové kódy

android: handle ConnectionService failures more resiliently

Some Samsung devices will fail to fully engage ConnectionService if no SIM card
was ever installed on the device. We could check for it, but it would require
the CALL_PHONE permission, which is not something we want to do, so fallback to
not using ConnectionService.
master
Saúl Ibarra Corretgé před 5 roky
rodič
revize
a622a4c713

+ 5
- 2
android/sdk/src/main/java/org/jitsi/meet/sdk/ConnectionService.java Zobrazit soubor

@@ -123,14 +123,17 @@ public class ConnectionService extends android.telecom.ConnectionService {
123 123
      * {@link android.telecom.Connection#STATE_ACTIVE}.
124 124
      *
125 125
      * @param callUUID the call UUID which identifies the connection.
126
+     * @return Whether the connection was set as active or not.
126 127
      */
127
-    static void setConnectionActive(String callUUID) {
128
+    static boolean setConnectionActive(String callUUID) {
128 129
         ConnectionImpl connection = connections.get(callUUID);
129 130
 
130 131
         if (connection != null) {
131 132
             connection.setActive();
133
+            return true;
132 134
         } else {
133
-            JitsiMeetLogger.e("%s setConnectionActive - no connection for UUID: %s", TAG, callUUID);
135
+            JitsiMeetLogger.w("%s setConnectionActive - no connection for UUID: %s", TAG, callUUID);
136
+            return false;
134 137
         }
135 138
     }
136 139
 

+ 5
- 2
android/sdk/src/main/java/org/jitsi/meet/sdk/RNConnectionService.java Zobrazit soubor

@@ -158,8 +158,11 @@ class RNConnectionService extends ReactContextBaseJavaModule {
158 158
     @ReactMethod
159 159
     public void reportConnectedOutgoingCall(String callUUID, Promise promise) {
160 160
         JitsiMeetLogger.d(TAG + " reportConnectedOutgoingCall " + callUUID);
161
-        ConnectionService.setConnectionActive(callUUID);
162
-        promise.resolve(null);
161
+        if (ConnectionService.setConnectionActive(callUUID)) {
162
+            promise.resolve(null);
163
+        } else {
164
+            promise.reject("CONNECTION_NOT_FOUND_ERROR", "Connection wasn't found.");
165
+        }
163 166
     }
164 167
 
165 168
     @Override

+ 50
- 17
react/features/mobile/call-integration/middleware.js Zobrazit soubor

@@ -186,13 +186,25 @@ function _conferenceJoined({ getState }, next, action) {
186 186
     const { callUUID } = action.conference;
187 187
 
188 188
     if (callUUID) {
189
-        CallIntegration.reportConnectedOutgoingCall(callUUID).then(() => {
190
-            // iOS 13 doesn't like the mute state to be false before the call is started
191
-            // so we update it here in case the user selected startWithAudioMuted.
192
-            if (Platform.OS === 'ios') {
193
-                _updateCallIntegrationMuted(action.conference, getState());
194
-            }
195
-        });
189
+        CallIntegration.reportConnectedOutgoingCall(callUUID)
190
+            .then(() => {
191
+                // iOS 13 doesn't like the mute state to be false before the call is started
192
+                // so we update it here in case the user selected startWithAudioMuted.
193
+                if (Platform.OS === 'ios') {
194
+                    _updateCallIntegrationMuted(action.conference, getState());
195
+                }
196
+            })
197
+            .catch(error => {
198
+                // Currently this error code is emitted only by Android.
199
+                //
200
+                if (error.code === 'CONNECTION_NOT_FOUND_ERROR') {
201
+                    // Some Samsung devices will fail to fully engage ConnectionService if no SIM card
202
+                    // was ever installed on the device. We could check for it, but it would require
203
+                    // the CALL_PHONE permission, which is not something we want to do, so fallback to
204
+                    // not using ConnectionService.
205
+                    _handleConnectionServiceFailure(getState());
206
+                }
207
+            });
196 208
     }
197 209
 
198 210
     return result;
@@ -294,22 +306,43 @@ function _conferenceWillJoin({ dispatch, getState }, next, action) {
294 306
                     { cancelable: false });
295 307
             } else if (error.code === 'SECURITY_ERROR') {
296 308
                 // Some devices fail because the CALL_PHONE permission is not granted, which is
297
-                // nonsense, because it's not needed for self-managed connections. Alas, this also
298
-                // means audio device management would be broken, so fallback to not using ConnectionService.
299
-                // NOTE: We are not storing this in Settings, in case it's a transient issue, as far fetched as
300
-                // that may be.
301
-                if (AudioMode.setUseConnectionService) {
302
-                    AudioMode.setUseConnectionService(false);
303
-
304
-                    // Set the desired audio mode, since we just reset the whole thing.
305
-                    AudioMode.setMode(hasVideo ? AudioMode.VIDEO_CALL : AudioMode.AUDIO_CALL);
306
-                }
309
+                // nonsense, because it's not needed for self-managed connections.
310
+
311
+                _handleConnectionServiceFailure(state);
307 312
             }
308 313
         });
309 314
 
310 315
     return result;
311 316
 }
312 317
 
318
+/**
319
+ * Handles a ConnectionService fatal error by falling back to non-ConnectionService device management.
320
+ *
321
+ * @param {Object} state - Redux store.
322
+ * @returns {void}
323
+ */
324
+function _handleConnectionServiceFailure(state: Object) {
325
+    const conference = getCurrentConference(state);
326
+
327
+    if (conference) {
328
+        // We're not tracking the call anymore.
329
+        delete conference.callUUID;
330
+
331
+        // ConnectionService has fatally failed. Alas, this also means audio device management would be broken, so
332
+        // fallback to not using ConnectionService.
333
+        // NOTE: We are not storing this in Settings, in case it's a transient issue, as far fetched as
334
+        // that may be.
335
+        if (AudioMode.setUseConnectionService) {
336
+            AudioMode.setUseConnectionService(false);
337
+
338
+            const hasVideo = !isVideoMutedByAudioOnly(state);
339
+
340
+            // Set the desired audio mode, since we just reset the whole thing.
341
+            AudioMode.setMode(hasVideo ? AudioMode.VIDEO_CALL : AudioMode.AUDIO_CALL);
342
+        }
343
+    }
344
+}
345
+
313 346
 /**
314 347
  * Handles CallKit's event {@code performEndCallAction}.
315 348
  *

Načítá se…
Zrušit
Uložit