From 7261f75549a929c06d7990498bfdc117da02942e Mon Sep 17 00:00:00 2001 From: Andy Scherzinger Date: Tue, 27 Dec 2022 19:11:55 +0100 Subject: [PATCH 01/23] Spotbugs: remove needless boxing of boolean constant Signed-off-by: Andy Scherzinger --- .../main/java/com/nextcloud/talk/activities/CallActivity.java | 2 +- .../java/com/nextcloud/talk/activities/CallBaseActivity.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java index 2402579e6..f9b90ac04 100644 --- a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java +++ b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java @@ -592,7 +592,7 @@ public class CallActivity extends CallBaseActivity { private void handleFromNotification() { int apiVersion = ApiUtils.getConversationApiVersion(conversationUser, new int[]{ApiUtils.APIv4, 1}); - ncApi.getRooms(credentials, ApiUtils.getUrlForRooms(apiVersion, baseUrl), false) + ncApi.getRooms(credentials, ApiUtils.getUrlForRooms(apiVersion, baseUrl), Boolean.FALSE) .retry(3) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) diff --git a/app/src/main/java/com/nextcloud/talk/activities/CallBaseActivity.java b/app/src/main/java/com/nextcloud/talk/activities/CallBaseActivity.java index 8401fd9ea..6f13a2aae 100644 --- a/app/src/main/java/com/nextcloud/talk/activities/CallBaseActivity.java +++ b/app/src/main/java/com/nextcloud/talk/activities/CallBaseActivity.java @@ -21,7 +21,7 @@ public abstract class CallBaseActivity extends BaseActivity { public static final String TAG = "CallBaseActivity"; public PictureInPictureParams.Builder mPictureInPictureParamsBuilder; - public Boolean isInPipMode = false; + public Boolean isInPipMode = Boolean.FALSE; long onCreateTime; @SuppressLint("ClickableViewAccessibility") From 698ebdfd1c3e30abd6ecd25538a2c440de3b5213 Mon Sep 17 00:00:00 2001 From: Andy Scherzinger Date: Wed, 28 Dec 2022 09:46:58 +0100 Subject: [PATCH 02/23] remove unneeded toString() call Signed-off-by: Andy Scherzinger --- .../nextcloud/talk/callbacks/MentionAutocompleteCallback.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java b/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java index 07e733e26..4c4ea0413 100644 --- a/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java +++ b/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java @@ -73,7 +73,7 @@ public class MentionAutocompleteCallback implements AutocompleteCallback Date: Wed, 28 Dec 2022 10:42:49 +0100 Subject: [PATCH 03/23] Spotbugs: precize allocation of a collection Signed-off-by: Andy Scherzinger --- .../nextcloud/talk/components/filebrowser/webdav/DavUtils.java | 2 +- .../components/filebrowser/webdav/ReadFilesystemOperation.java | 2 +- .../talk/presenters/MentionAutocompletePresenter.java | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/components/filebrowser/webdav/DavUtils.java b/app/src/main/java/com/nextcloud/talk/components/filebrowser/webdav/DavUtils.java index 2b96ee1db..8bf10c5f2 100644 --- a/app/src/main/java/com/nextcloud/talk/components/filebrowser/webdav/DavUtils.java +++ b/app/src/main/java/com/nextcloud/talk/components/filebrowser/webdav/DavUtils.java @@ -74,7 +74,7 @@ public class DavUtils { public static final String PROPERTY_QUOTA_AVAILABLE_BYTES = "quota-available-bytes"; static Property.Name[] getAllPropSet() { - List props = new ArrayList<>(); + List props = new ArrayList<>(20); props.add(DisplayName.NAME); props.add(GetContentType.NAME); diff --git a/app/src/main/java/com/nextcloud/talk/components/filebrowser/webdav/ReadFilesystemOperation.java b/app/src/main/java/com/nextcloud/talk/components/filebrowser/webdav/ReadFilesystemOperation.java index 31b08d1ec..b8cb247c0 100644 --- a/app/src/main/java/com/nextcloud/talk/components/filebrowser/webdav/ReadFilesystemOperation.java +++ b/app/src/main/java/com/nextcloud/talk/components/filebrowser/webdav/ReadFilesystemOperation.java @@ -69,7 +69,6 @@ public class ReadFilesystemOperation { DavResponse davResponse = new DavResponse(); final List memberElements = new ArrayList<>(); final Response[] rootElement = new Response[1]; - final List remoteFiles = new ArrayList<>(); try { new DavResource(okHttpClient, HttpUrl.parse(url)).propfind(depth, DavUtils.getAllPropSet(), @@ -94,6 +93,7 @@ public class ReadFilesystemOperation { Log.w(TAG, "Error reading remote path"); } + final List remoteFiles = new ArrayList<>(1 + memberElements.size()); remoteFiles.add(BrowserFile.Companion.getModelFromResponse(rootElement[0], rootElement[0].getHref().toString().substring(basePath.length()))); for (Response memberElement : memberElements) { diff --git a/app/src/main/java/com/nextcloud/talk/presenters/MentionAutocompletePresenter.java b/app/src/main/java/com/nextcloud/talk/presenters/MentionAutocompletePresenter.java index f6a28dab8..8aa553714 100644 --- a/app/src/main/java/com/nextcloud/talk/presenters/MentionAutocompletePresenter.java +++ b/app/src/main/java/com/nextcloud/talk/presenters/MentionAutocompletePresenter.java @@ -147,7 +147,8 @@ public class MentionAutocompletePresenter extends RecyclerViewPresenter if (mentionsList.size() == 0) { adapter.clear(); } else { - List internalAbstractFlexibleItemList = new ArrayList<>(); + List internalAbstractFlexibleItemList = + new ArrayList<>(mentionsList.size()); for (Mention mention : mentionsList) { internalAbstractFlexibleItemList.add( new MentionAutocompleteItem( From 7eef68ef3655f4c04eafbf731a2851cb3463f321 Mon Sep 17 00:00:00 2001 From: Andy Scherzinger Date: Wed, 28 Dec 2022 11:09:49 +0100 Subject: [PATCH 04/23] use proper register-method instead of reflection Signed-off-by: Andy Scherzinger --- .../filebrowser/webdav/DavUtils.java | 22 +++++-------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/components/filebrowser/webdav/DavUtils.java b/app/src/main/java/com/nextcloud/talk/components/filebrowser/webdav/DavUtils.java index 8bf10c5f2..ec144d8ab 100644 --- a/app/src/main/java/com/nextcloud/talk/components/filebrowser/webdav/DavUtils.java +++ b/app/src/main/java/com/nextcloud/talk/components/filebrowser/webdav/DavUtils.java @@ -104,22 +104,12 @@ public class DavUtils { public static void registerCustomFactories() { PropertyRegistry propertyRegistry = PropertyRegistry.INSTANCE; - try { - Field factories = propertyRegistry.getClass().getDeclaredField("factories"); - factories.setAccessible(true); - Map reflectionMap = (HashMap) factories.get(propertyRegistry); - reflectionMap.put(OCId.NAME, new OCId.Factory()); - reflectionMap.put(NCPreview.NAME, new NCPreview.Factory()); - reflectionMap.put(NCEncrypted.NAME, new NCEncrypted.Factory()); - reflectionMap.put(OCFavorite.NAME, new OCFavorite.Factory()); - reflectionMap.put(OCSize.NAME, new OCSize.Factory()); - reflectionMap.put(NCPermission.NAME, new NCPermission.Factory()); - - factories.set(propertyRegistry, reflectionMap); - } catch (NoSuchFieldException | IllegalAccessException e) { - Log.w(TAG, "Error registering custom factories", e); - } + propertyRegistry.register(new OCId.Factory()); + propertyRegistry.register(new NCPreview.Factory()); + propertyRegistry.register(new NCEncrypted.Factory()); + propertyRegistry.register(new OCFavorite.Factory()); + propertyRegistry.register(new OCSize.Factory()); + propertyRegistry.register(new NCPermission.Factory()); } } From 6cd0481d1490b21f0756da76ca6c4c5f260bdf04 Mon Sep 17 00:00:00 2001 From: Andy Scherzinger Date: Wed, 28 Dec 2022 11:17:02 +0100 Subject: [PATCH 05/23] remove unneeded logging statement Signed-off-by: Andy Scherzinger --- .../com/nextcloud/talk/ui/dialog/SortingOrderDialogFragment.java | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/com/nextcloud/talk/ui/dialog/SortingOrderDialogFragment.java b/app/src/main/java/com/nextcloud/talk/ui/dialog/SortingOrderDialogFragment.java index d3744072a..ac75659df 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/dialog/SortingOrderDialogFragment.java +++ b/app/src/main/java/com/nextcloud/talk/ui/dialog/SortingOrderDialogFragment.java @@ -177,7 +177,6 @@ public class SortingOrderDialogFragment extends DialogFragment implements View.O binding.cancel.setOnClickListener(view -> dismiss()); for (View view : taggedViews) { - Log.i("SortOrder", "view="+view.getTag().toString()); view.setOnClickListener(this); } } From deada5cf945c9fddd5c92de7e27347e1c821986d Mon Sep 17 00:00:00 2001 From: Andy Scherzinger Date: Wed, 28 Dec 2022 11:18:47 +0100 Subject: [PATCH 06/23] Spotbug: remove toString() output concatenation Signed-off-by: Andy Scherzinger --- .../java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java b/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java index da98e27f3..eab0c6cdb 100644 --- a/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java +++ b/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java @@ -165,7 +165,7 @@ public class MagicWebSocketInstance extends WebSocketListener { @Override public void onMessage(WebSocket webSocket, String text) { if (webSocket == internalWebSocket) { - Log.d(TAG, "Receiving : " + webSocket.toString() + " " + text); + Log.d(TAG, "Receiving : " + webSocket + " " + text); try { BaseWebSocketMessage baseWebSocketMessage = LoganSquare.parse(text, BaseWebSocketMessage.class); From ff3dffd0514642be8c47b726244d432f5f69f6b6 Mon Sep 17 00:00:00 2001 From: Andy Scherzinger Date: Wed, 28 Dec 2022 11:35:51 +0100 Subject: [PATCH 07/23] Spotbugs: literal string comparison Signed-off-by: Andy Scherzinger --- .../nextcloud/talk/activities/CallActivity.java | 2 +- .../talk/adapters/items/ParticipantItem.java | 14 ++++++++++---- .../nextcloud/talk/utils/AuthenticatorService.java | 9 +++------ .../java/com/nextcloud/talk/utils/DeviceUtils.java | 13 ++++++++----- .../preferencestorage/DatabaseStorageModule.java | 14 +++++++------- .../talk/webrtc/PeerConnectionWrapper.java | 9 +++++---- .../talk/webrtc/WebRtcBluetoothManager.java | 12 +++++++----- 7 files changed, 41 insertions(+), 32 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java index f9b90ac04..5b86aa37e 100644 --- a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java +++ b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java @@ -367,7 +367,7 @@ public class CallActivity extends CallBaseActivity { powerManagerUtils = new PowerManagerUtils(); - if (extras.getString("state", "").equalsIgnoreCase("resume")) { + if ("resume".equalsIgnoreCase(extras.getString("state", ""))) { setCallState(CallStatus.IN_CONVERSATION); } else { setCallState(CallStatus.CONNECTING); diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/ParticipantItem.java b/app/src/main/java/com/nextcloud/talk/adapters/items/ParticipantItem.java index 6bc572d68..0d2a3cc9e 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/items/ParticipantItem.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/items/ParticipantItem.java @@ -154,8 +154,11 @@ public class ParticipantItem extends AbstractFlexibleItem appOpsUtilsClass = Class.forName("android.miui.AppOpsUtils"); if (appOpsUtilsClass != null) { Method setApplicationAutoStartMethod = appOpsUtilsClass.getMethod("setApplicationAutoStart", Context .class, String.class, Boolean.TYPE); if (setApplicationAutoStartMethod != null) { - Context applicationContext = NextcloudTalkApplication.Companion.getSharedApplication().getApplicationContext(); + Context applicationContext = NextcloudTalkApplication + .Companion + .getSharedApplication() + .getApplicationContext(); setApplicationAutoStartMethod.invoke(appOpsUtilsClass, applicationContext, applicationContext .getPackageName(), Boolean.TRUE); } @@ -56,10 +59,10 @@ public class DeviceUtils { } catch (InvocationTargetException e) { Log.e(TAG, "InvocationTargetException"); } - } else if (Build.MANUFACTURER.equalsIgnoreCase("huawei")) { + } else if ("huawei".equalsIgnoreCase(Build.MANUFACTURER)) { try { - @SuppressLint("PrivateApi") Class protectAppControlClass = Class.forName("com.huawei.systemmanager.optimize.process" + - ".ProtectAppControl"); + @SuppressLint("PrivateApi") Class protectAppControlClass = Class.forName( + "com.huawei.systemmanager.optimize.process.ProtectAppControl"); if (protectAppControlClass != null) { Context applicationContext = NextcloudTalkApplication.Companion.getSharedApplication().getApplicationContext(); diff --git a/app/src/main/java/com/nextcloud/talk/utils/preferences/preferencestorage/DatabaseStorageModule.java b/app/src/main/java/com/nextcloud/talk/utils/preferences/preferencestorage/DatabaseStorageModule.java index 9e891efec..3b4d59cf5 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/preferences/preferencestorage/DatabaseStorageModule.java +++ b/app/src/main/java/com/nextcloud/talk/utils/preferences/preferencestorage/DatabaseStorageModule.java @@ -78,7 +78,7 @@ public class DatabaseStorageModule implements StorageModule { @Override public void saveBoolean(String key, boolean value) { - if (key.equals("call_notifications")) { + if ("call_notifications".equals(key)) { int apiVersion = ApiUtils.getConversationApiVersion(conversationUser, new int[]{4}); ncApi.notificationCalls(ApiUtils.getCredentials(conversationUser.getUsername(), conversationUser.getToken()), @@ -112,7 +112,7 @@ public class DatabaseStorageModule implements StorageModule { ); } - if (!key.equals("conversation_lobby")) { + if (!"conversation_lobby".equals(key)) { arbitraryStorageManager.storeStorageSetting(accountIdentifier, key, Boolean.toString(value), @@ -124,7 +124,7 @@ public class DatabaseStorageModule implements StorageModule { @Override public void saveString(String key, String value) { - if (key.equals("message_expire_key")) { + if ("message_expire_key".equals(key)) { int apiVersion = ApiUtils.getConversationApiVersion(conversationUser, new int[]{4}); String trimmedValue = value.replace("expire_", ""); @@ -163,7 +163,7 @@ public class DatabaseStorageModule implements StorageModule { } }); - } else if (key.equals("message_notification_level")) { + } else if ("message_notification_level".equals(key)) { if (CapabilitiesUtilNew.hasSpreedFeatureCapability(conversationUser, "notification-levels")) { if (!TextUtils.isEmpty(messageNotificationLevel) && !messageNotificationLevel.equals(value)) { int intValue; @@ -232,7 +232,7 @@ public class DatabaseStorageModule implements StorageModule { @Override public boolean getBoolean(String key, boolean defaultVal) { - if (key.equals("conversation_lobby")) { + if ("conversation_lobby".equals(key)) { return lobbyValue; } else { return arbitraryStorageManager @@ -244,7 +244,7 @@ public class DatabaseStorageModule implements StorageModule { @Override public String getString(String key, String defaultVal) { - if (key.equals("message_expire_key")) { + if ("message_expire_key".equals(key)) { switch (messageExpiration) { case 2419200: return "expire_2419200"; @@ -259,7 +259,7 @@ public class DatabaseStorageModule implements StorageModule { default: return "expire_0"; } - } else if (key.equals("message_notification_level")) { + } else if ("message_notification_level".equals(key)) { return messageNotificationLevel; } else { return arbitraryStorageManager diff --git a/app/src/main/java/com/nextcloud/talk/webrtc/PeerConnectionWrapper.java b/app/src/main/java/com/nextcloud/talk/webrtc/PeerConnectionWrapper.java index f4a7d6b7e..98ef3ba5d 100644 --- a/app/src/main/java/com/nextcloud/talk/webrtc/PeerConnectionWrapper.java +++ b/app/src/main/java/com/nextcloud/talk/webrtc/PeerConnectionWrapper.java @@ -171,7 +171,7 @@ public class PeerConnectionWrapper { dataChannel.registerObserver(new MagicDataChannelObserver()); if (isMCUPublisher) { peerConnection.createOffer(magicSdpObserver, mediaConstraints); - } else if (hasMCU && this.videoStreamType.equals("video")) { + } else if (hasMCU && "video".equals(this.videoStreamType)) { // If the connection type is "screen" the client sharing the screen will send an // offer; offers should be requested only for videos. // "to" property is not actually needed in the "requestoffer" signaling message, but it is used to @@ -360,8 +360,9 @@ public class PeerConnectionWrapper { @Override public void onStateChange() { - if (dataChannel != null && dataChannel.state() == DataChannel.State.OPEN && - dataChannel.label().equals("status")) { + if (dataChannel != null && + dataChannel.state() == DataChannel.State.OPEN && + "status".equals(dataChannel.label())) { sendInitialMediaStatus(); } } @@ -493,7 +494,7 @@ public class PeerConnectionWrapper { @Override public void onDataChannel(DataChannel dataChannel) { - if (dataChannel.label().equals("status") || dataChannel.label().equals("JanusDataChannel")) { + if ("status".equals(dataChannel.label()) || "JanusDataChannel".equals(dataChannel.label())) { PeerConnectionWrapper.this.dataChannel = dataChannel; PeerConnectionWrapper.this.dataChannel.registerObserver(new MagicDataChannelObserver()); } diff --git a/app/src/main/java/com/nextcloud/talk/webrtc/WebRtcBluetoothManager.java b/app/src/main/java/com/nextcloud/talk/webrtc/WebRtcBluetoothManager.java index 2655f9ba7..65e115af9 100644 --- a/app/src/main/java/com/nextcloud/talk/webrtc/WebRtcBluetoothManager.java +++ b/app/src/main/java/com/nextcloud/talk/webrtc/WebRtcBluetoothManager.java @@ -109,8 +109,6 @@ public class WebRtcBluetoothManager { return bluetoothState; } - ; - /** * Activates components required to detect Bluetooth devices and to enable * BT SCO (audio is routed via BT SCO) for the headset profile. The end @@ -502,8 +500,10 @@ public class WebRtcBluetoothManager { Log.d(TAG, "onServiceConnected done: BT state=" + bluetoothState); } + /** + * Notifies the client when the proxy object has been disconnected from the service. + */ @Override - /** Notifies the client when the proxy object has been disconnected from the service. */ public void onServiceDisconnected(int profile) { if (profile != BluetoothProfile.HEADSET || bluetoothState == State.UNINITIALIZED) { return; @@ -531,7 +531,7 @@ public class WebRtcBluetoothManager { // change does not tell us anything about whether we're streaming // audio to BT over SCO. Typically received when user turns on a BT // headset while audio is active using another audio device. - if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) { + if (BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED.equals(action)) { final int state = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_DISCONNECTED); Log.d(TAG, "BluetoothHeadsetBroadcastReceiver.onReceive: " @@ -543,8 +543,10 @@ public class WebRtcBluetoothManager { scoConnectionAttempts = 0; updateAudioDeviceState(); } else if (state == BluetoothHeadset.STATE_CONNECTING) { + Log.d(TAG, "+++ Bluetooth is connecting..."); // No action needed. } else if (state == BluetoothHeadset.STATE_DISCONNECTING) { + Log.d(TAG, "+++ Bluetooth is disconnecting..."); // No action needed. } else if (state == BluetoothHeadset.STATE_DISCONNECTED) { // Bluetooth is probably powered off during the call. @@ -553,7 +555,7 @@ public class WebRtcBluetoothManager { } // Change in the audio (SCO) connection state of the Headset profile. // Typically received after call to startScoAudio() has finalized. - } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) { + } else if (BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED.equals(action)) { final int state = intent.getIntExtra( BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_AUDIO_DISCONNECTED); Log.d(TAG, "BluetoothHeadsetBroadcastReceiver.onReceive: " From 946ec09315be258f67d425803ed57ae815844de7 Mon Sep 17 00:00:00 2001 From: Andy Scherzinger Date: Wed, 28 Dec 2022 11:50:51 +0100 Subject: [PATCH 08/23] Spotbug: don't access Array with constant index Signed-off-by: Andy Scherzinger --- .../MentionAutocompleteCallback.java | 10 ++--- .../nextcloud/talk/utils/DisplayUtils.java | 2 +- .../nextcloud/talk/utils/MagicCharPolicy.java | 41 +++++++++++++------ 3 files changed, 34 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java b/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java index 4c4ea0413..2d1283301 100644 --- a/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java +++ b/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java @@ -60,12 +60,10 @@ public class MentionAutocompleteCallback implements AutocompleteCallback 1) { - // Do absolutely nothing + if (span == null || span.length == 0) { + return null; + } else { + QuerySpan sp = span[0]; + return new TextSpan(text.getSpanStart(sp), text.getSpanEnd(sp)); } - QuerySpan sp = span[0]; - return new int[]{text.getSpanStart(sp), text.getSpanEnd(sp)}; } - private int[] checkText(Spannable text, int cursorPos) { + private TextSpan checkText(Spannable text, int cursorPos) { if (text.length() == 0) { return null; } - int[] span = new int[2]; Pattern pattern = Pattern.compile("@+\\S*", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); Matcher matcher = pattern.matcher(text); while (matcher.find()) { if (cursorPos >= matcher.start() && cursorPos <= matcher.end()) { - span[0] = matcher.start(); - span[1] = matcher.end(); if (text.subSequence(matcher.start(), matcher.end()).charAt(0) == character) { - return span; + return new TextSpan(matcher.start(), matcher.end()); } } } @@ -69,11 +66,29 @@ public class MagicCharPolicy implements AutocompletePolicy { return null; } + public static class TextSpan { + int start; + int end; + + public TextSpan(int start, int end) { + this.start = start; + this.end = end; + } + + public int getStart() { + return start; + } + + public int getEnd() { + return end; + } + } + @Override public boolean shouldShowPopup(Spannable text, int cursorPos) { - int[] show = checkText(text, cursorPos); + TextSpan show = checkText(text, cursorPos); if (show != null) { - text.setSpan(new QuerySpan(), show[0], show[1], Spanned.SPAN_INCLUSIVE_INCLUSIVE); + text.setSpan(new QuerySpan(), show.getStart(), show.getEnd(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); return true; } return false; From bf8c113f9a4d38f18f96a968e39a4ef690d3a492 Mon Sep 17 00:00:00 2001 From: Andy Scherzinger Date: Wed, 28 Dec 2022 11:54:56 +0100 Subject: [PATCH 09/23] Spotbugs: prevent possible NPE deference Signed-off-by: Andy Scherzinger --- .../java/com/nextcloud/talk/utils/DisplayUtils.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java b/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java index 48beb604e..e48ed823a 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java +++ b/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java @@ -369,8 +369,6 @@ public class DisplayUtils { decor.setSystemUiVisibility(0); } window.setStatusBarColor(color); - } else if (isLightTheme) { - window.setStatusBarColor(Color.BLACK); } } @@ -455,10 +453,12 @@ public class DisplayUtils { avatarId = user.getUsername(); } - if (deleteCache) { - ImageViewExtensionsKt.replaceAvatar(avatarImageView, user, avatarId, true); - } else { - ImageViewExtensionsKt.loadAvatar(avatarImageView, user, avatarId, true); + if (avatarId != null) { + if (deleteCache) { + ImageViewExtensionsKt.replaceAvatar(avatarImageView, user, avatarId, true); + } else { + ImageViewExtensionsKt.loadAvatar(avatarImageView, user, avatarId, true); + } } } From 093e6a15bcfc9c398bf72e808c5570ed8881b2a2 Mon Sep 17 00:00:00 2001 From: Andy Scherzinger Date: Wed, 28 Dec 2022 12:00:35 +0100 Subject: [PATCH 10/23] Spotbugs: proper equals and hashCode Signed-off-by: Andy Scherzinger --- .../adapters/items/NotificationSoundItem.java | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/NotificationSoundItem.java b/app/src/main/java/com/nextcloud/talk/adapters/items/NotificationSoundItem.java index 5f2359b1e..93cbc99bf 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/items/NotificationSoundItem.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/items/NotificationSoundItem.java @@ -28,6 +28,7 @@ import com.nextcloud.talk.R; import com.nextcloud.talk.databinding.RvItemNotificationSoundBinding; import java.util.List; +import java.util.Objects; import eu.davidea.flexibleadapter.FlexibleAdapter; import eu.davidea.flexibleadapter.items.AbstractFlexibleItem; @@ -54,7 +55,26 @@ public class NotificationSoundItem extends AbstractFlexibleItem Date: Wed, 28 Dec 2022 12:05:16 +0100 Subject: [PATCH 11/23] Spotbugs: remove superclass field masking fields inherited from BaseActivity Signed-off-by: Andy Scherzinger --- .../java/com/nextcloud/talk/activities/CallActivity.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java index 5b86aa37e..e38afe2aa 100644 --- a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java +++ b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java @@ -178,14 +178,13 @@ public class CallActivity extends CallBaseActivity { @Inject NcApi ncApi; - @Inject - EventBus eventBus; + @Inject UserManager userManager; - @Inject - AppPreferences appPreferences; + @Inject Cache cache; + @Inject PlatformPermissionUtil permissionUtil; From 8b61808fda6afad9f5914c592d6ca28592119cad Mon Sep 17 00:00:00 2001 From: Andy Scherzinger Date: Wed, 28 Dec 2022 12:06:48 +0100 Subject: [PATCH 12/23] Spotbug: make constructor-called methods final Signed-off-by: Andy Scherzinger --- .../java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java | 2 +- .../main/java/com/nextcloud/talk/webrtc/WebRtcAudioManager.java | 2 +- .../java/com/nextcloud/talk/webrtc/WebRtcBluetoothManager.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java b/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java index eab0c6cdb..4dd49f69b 100644 --- a/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java +++ b/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java @@ -152,7 +152,7 @@ public class MagicWebSocketInstance extends WebSocketListener { resumeId = ""; } - public void restartWebSocket() { + public final void restartWebSocket() { reconnecting = true; // TODO when improving logging, keep in mind this issue: https://github.com/nextcloud/talk-android/issues/1013 diff --git a/app/src/main/java/com/nextcloud/talk/webrtc/WebRtcAudioManager.java b/app/src/main/java/com/nextcloud/talk/webrtc/WebRtcAudioManager.java index f7e36034e..a3cf70773 100644 --- a/app/src/main/java/com/nextcloud/talk/webrtc/WebRtcAudioManager.java +++ b/app/src/main/java/com/nextcloud/talk/webrtc/WebRtcAudioManager.java @@ -399,7 +399,7 @@ public class WebRtcAudioManager { return false; } - public void updateAudioDeviceState() { + public final void updateAudioDeviceState() { ThreadUtils.checkIsOnMainThread(); Log.d(TAG, "--- updateAudioDeviceState: " + "wired headset=" + hasWiredHeadset + ", " diff --git a/app/src/main/java/com/nextcloud/talk/webrtc/WebRtcBluetoothManager.java b/app/src/main/java/com/nextcloud/talk/webrtc/WebRtcBluetoothManager.java index 65e115af9..ba530f1c3 100644 --- a/app/src/main/java/com/nextcloud/talk/webrtc/WebRtcBluetoothManager.java +++ b/app/src/main/java/com/nextcloud/talk/webrtc/WebRtcBluetoothManager.java @@ -295,7 +295,7 @@ public class WebRtcBluetoothManager { /** * Stubs for test mocks. */ - protected AudioManager getAudioManager(Context context) { + protected final AudioManager getAudioManager(Context context) { return (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); } From b07ee434fe5bcce696ec262b03dae6aeefb59073 Mon Sep 17 00:00:00 2001 From: Andy Scherzinger Date: Wed, 28 Dec 2022 12:14:07 +0100 Subject: [PATCH 13/23] housekeeping: cleanup after spotbug fixes Signed-off-by: Andy Scherzinger --- .../talk/activities/CallActivity.java | 2 -- .../filebrowser/webdav/DavUtils.java | 18 ++++++------------ .../nextcloud/talk/utils/MagicCharPolicy.java | 7 +++---- 3 files changed, 9 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java index e38afe2aa..81c1030d2 100644 --- a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java +++ b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java @@ -90,7 +90,6 @@ import com.nextcloud.talk.utils.NotificationUtils; import com.nextcloud.talk.utils.animations.PulseAnimation; import com.nextcloud.talk.utils.permissions.PlatformPermissionUtil; import com.nextcloud.talk.utils.power.PowerManagerUtils; -import com.nextcloud.talk.utils.preferences.AppPreferences; import com.nextcloud.talk.utils.singletons.ApplicationWideCurrentRoomHolder; import com.nextcloud.talk.webrtc.MagicWebRTCUtils; import com.nextcloud.talk.webrtc.MagicWebSocketInstance; @@ -100,7 +99,6 @@ import com.nextcloud.talk.webrtc.WebSocketConnectionHelper; import com.wooplr.spotlight.SpotlightView; import org.apache.commons.lang3.StringEscapeUtils; -import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; import org.webrtc.AudioSource; diff --git a/app/src/main/java/com/nextcloud/talk/components/filebrowser/webdav/DavUtils.java b/app/src/main/java/com/nextcloud/talk/components/filebrowser/webdav/DavUtils.java index ec144d8ab..6b18f5a32 100644 --- a/app/src/main/java/com/nextcloud/talk/components/filebrowser/webdav/DavUtils.java +++ b/app/src/main/java/com/nextcloud/talk/components/filebrowser/webdav/DavUtils.java @@ -22,8 +22,6 @@ package com.nextcloud.talk.components.filebrowser.webdav; -import android.util.Log; - import com.nextcloud.talk.components.filebrowser.models.properties.NCEncrypted; import com.nextcloud.talk.components.filebrowser.models.properties.NCPermission; import com.nextcloud.talk.components.filebrowser.models.properties.NCPreview; @@ -31,14 +29,10 @@ import com.nextcloud.talk.components.filebrowser.models.properties.OCFavorite; import com.nextcloud.talk.components.filebrowser.models.properties.OCId; import com.nextcloud.talk.components.filebrowser.models.properties.OCSize; -import java.lang.reflect.Field; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import at.bitfire.dav4jvm.Property; -import at.bitfire.dav4jvm.PropertyFactory; import at.bitfire.dav4jvm.PropertyRegistry; import at.bitfire.dav4jvm.property.CreationDate; import at.bitfire.dav4jvm.property.DisplayName; @@ -49,7 +43,6 @@ import at.bitfire.dav4jvm.property.GetLastModified; import at.bitfire.dav4jvm.property.ResourceType; public class DavUtils { - private static final String TAG = "DavUtils"; public static final String OC_NAMESPACE = "http://owncloud.org/ns"; public static final String NC_NAMESPACE = "http://nextcloud.org/ns"; @@ -66,12 +59,13 @@ public class DavUtils { public static final String EXTENDED_PROPERTY_UNREAD_COMMENTS = "comments-unread"; public static final String EXTENDED_PROPERTY_HAS_PREVIEW = "has-preview"; public static final String EXTENDED_PROPERTY_NOTE = "note"; - public static final String TRASHBIN_FILENAME = "trashbin-filename"; - public static final String TRASHBIN_ORIGINAL_LOCATION = "trashbin-original-location"; - public static final String TRASHBIN_DELETION_TIME = "trashbin-deletion-time"; - public static final String PROPERTY_QUOTA_USED_BYTES = "quota-used-bytes"; - public static final String PROPERTY_QUOTA_AVAILABLE_BYTES = "quota-available-bytes"; + // public static final String TRASHBIN_FILENAME = "trashbin-filename"; + // public static final String TRASHBIN_ORIGINAL_LOCATION = "trashbin-original-location"; + // public static final String TRASHBIN_DELETION_TIME = "trashbin-deletion-time"; + + // public static final String PROPERTY_QUOTA_USED_BYTES = "quota-used-bytes"; + // public static final String PROPERTY_QUOTA_AVAILABLE_BYTES = "quota-available-bytes"; static Property.Name[] getAllPropSet() { List props = new ArrayList<>(20); diff --git a/app/src/main/java/com/nextcloud/talk/utils/MagicCharPolicy.java b/app/src/main/java/com/nextcloud/talk/utils/MagicCharPolicy.java index d6af8a29a..d198732eb 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/MagicCharPolicy.java +++ b/app/src/main/java/com/nextcloud/talk/utils/MagicCharPolicy.java @@ -56,10 +56,9 @@ public class MagicCharPolicy implements AutocompletePolicy { Matcher matcher = pattern.matcher(text); while (matcher.find()) { - if (cursorPos >= matcher.start() && cursorPos <= matcher.end()) { - if (text.subSequence(matcher.start(), matcher.end()).charAt(0) == character) { - return new TextSpan(matcher.start(), matcher.end()); - } + if (cursorPos >= matcher.start() && cursorPos <= matcher.end() && + text.subSequence(matcher.start(), matcher.end()).charAt(0) == character) { + return new TextSpan(matcher.start(), matcher.end()); } } From 08936279b69ae47ca0f30dfd0372894bb4c65841 Mon Sep 17 00:00:00 2001 From: Andy Scherzinger Date: Wed, 28 Dec 2022 12:15:18 +0100 Subject: [PATCH 14/23] codacy: inefficient use of StringBuffer.toString using call StringBuffer.length instead Signed-off-by: Andy Scherzinger --- .../nextcloud/talk/callbacks/MentionAutocompleteCallback.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java b/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java index 2d1283301..fe8434393 100644 --- a/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java +++ b/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java @@ -85,7 +85,7 @@ public class MentionAutocompleteCallback implements AutocompleteCallback Date: Wed, 28 Dec 2022 12:57:24 +0100 Subject: [PATCH 15/23] Spotbugs prevent NPR deference Signed-off-by: Andy Scherzinger --- .../com/nextcloud/talk/adapters/items/AdvancedUserItem.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/AdvancedUserItem.java b/app/src/main/java/com/nextcloud/talk/adapters/items/AdvancedUserItem.java index 36f652da1..a5ac03a25 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/items/AdvancedUserItem.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/items/AdvancedUserItem.java @@ -125,9 +125,9 @@ public class AdvancedUserItem extends AbstractFlexibleItem Date: Wed, 28 Dec 2022 13:47:51 +0100 Subject: [PATCH 16/23] Spotbug: split message processing to reduce complexity Signed-off-by: Andy Scherzinger --- .../talk/webrtc/MagicWebSocketInstance.java | 267 ++++++++++-------- 1 file changed, 149 insertions(+), 118 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java b/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java index 4dd49f69b..42ad896e1 100644 --- a/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java +++ b/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java @@ -54,6 +54,7 @@ import java.util.Map; import javax.inject.Inject; +import androidx.annotation.NonNull; import autodagger.AutoInjector; import okhttp3.OkHttpClient; import okhttp3.Request; @@ -163,131 +164,39 @@ public class MagicWebSocketInstance extends WebSocketListener { } @Override - public void onMessage(WebSocket webSocket, String text) { + public void onMessage(@NonNull WebSocket webSocket, @NonNull String text) { if (webSocket == internalWebSocket) { Log.d(TAG, "Receiving : " + webSocket + " " + text); try { BaseWebSocketMessage baseWebSocketMessage = LoganSquare.parse(text, BaseWebSocketMessage.class); String messageType = baseWebSocketMessage.getType(); - switch (messageType) { - case "hello": - connected = true; - reconnecting = false; - restartCount = 0; - String oldResumeId = resumeId; - HelloResponseOverallWebSocketMessage helloResponseWebSocketMessage = LoganSquare.parse(text, HelloResponseOverallWebSocketMessage.class); - resumeId = helloResponseWebSocketMessage.getHelloResponseWebSocketMessage().getResumeId(); - sessionId = helloResponseWebSocketMessage.getHelloResponseWebSocketMessage().getSessionId(); - hasMCU = helloResponseWebSocketMessage.getHelloResponseWebSocketMessage().serverHasMCUSupport(); - - for (int i = 0; i < messagesQueue.size(); i++) { - webSocket.send(messagesQueue.get(i)); - } - - messagesQueue = new ArrayList<>(); - HashMap helloHasHap = new HashMap<>(); - if (!TextUtils.isEmpty(oldResumeId)) { - helloHasHap.put("oldResumeId", oldResumeId); - } else { - currentRoomToken = ""; - } - - if (!TextUtils.isEmpty(currentRoomToken)) { - helloHasHap.put(ROOM_TOKEN, currentRoomToken); - } - eventBus.post(new WebSocketCommunicationEvent("hello", helloHasHap)); - break; - case "error": - Log.e(TAG, "Received error: " + text); - ErrorOverallWebSocketMessage errorOverallWebSocketMessage = LoganSquare.parse(text, ErrorOverallWebSocketMessage.class); - if (("no_such_session").equals(errorOverallWebSocketMessage.getErrorWebSocketMessage().getCode())) { - Log.d(TAG, "WebSocket " + webSocket.hashCode() + " resumeID " + resumeId + " expired"); + if (messageType != null) { + switch (messageType) { + case "hello": + processHelloMessage(webSocket, text); + break; + case "error": + processErrorMessage(webSocket, text); + break; + case "room": + processJoinedRoomMessage(text); + break; + case "event": + processEventMessage(text); + break; + case "message": + processMessage(text); + break; + case "bye": + connected = false; resumeId = ""; - currentRoomToken = ""; - restartWebSocket(); - } else if (("hello_expected").equals(errorOverallWebSocketMessage.getErrorWebSocketMessage().getCode())) { - restartWebSocket(); - } - - break; - case "room": - JoinedRoomOverallWebSocketMessage joinedRoomOverallWebSocketMessage = LoganSquare.parse(text, JoinedRoomOverallWebSocketMessage.class); - currentRoomToken = joinedRoomOverallWebSocketMessage.getRoomWebSocketMessage().getRoomId(); - if (joinedRoomOverallWebSocketMessage.getRoomWebSocketMessage().getRoomPropertiesWebSocketMessage() != null && !TextUtils.isEmpty(currentRoomToken)) { - sendRoomJoinedEvent(); - } - break; - case "event": - EventOverallWebSocketMessage eventOverallWebSocketMessage = LoganSquare.parse(text, EventOverallWebSocketMessage.class); - if (eventOverallWebSocketMessage.getEventMap() != null) { - String target = (String) eventOverallWebSocketMessage.getEventMap().get("target"); - switch (target) { - case "room": - if (eventOverallWebSocketMessage.getEventMap().get("type").equals("message")) { - Map messageHashMap = - (Map) eventOverallWebSocketMessage.getEventMap().get("message"); - if (messageHashMap.containsKey("data")) { - Map dataHashMap = (Map) messageHashMap.get( - "data"); - if (dataHashMap.containsKey("chat")) { - boolean shouldRefreshChat; - Map chatMap = (Map) dataHashMap.get("chat"); - if (chatMap.containsKey("refresh")) { - shouldRefreshChat = (boolean) chatMap.get("refresh"); - if (shouldRefreshChat) { - HashMap refreshChatHashMap = new HashMap<>(); - refreshChatHashMap.put(BundleKeys.KEY_ROOM_TOKEN, (String) messageHashMap.get("roomid")); - refreshChatHashMap.put(BundleKeys.KEY_INTERNAL_USER_ID, Long.toString(conversationUser.getId())); - eventBus.post(new WebSocketCommunicationEvent("refreshChat", refreshChatHashMap)); - } - } - } - } - } else if (eventOverallWebSocketMessage.getEventMap().get("type").equals("join")) { - List> joinEventList = (List>) eventOverallWebSocketMessage.getEventMap().get("join"); - HashMap internalHashMap; - Participant participant; - for (int i = 0; i < joinEventList.size(); i++) { - internalHashMap = joinEventList.get(i); - HashMap userMap = (HashMap) internalHashMap.get("user"); - participant = new Participant(); - String userId = (String) internalHashMap.get("userid"); - if (userId != null) { - participant.setActorType(USERS); - participant.setActorId(userId); - } else { - participant.setActorType(GUESTS); - // FIXME seems to be not given by the HPB: participant.setActorId(); - } - if (userMap != null) { - // There is no "user" attribute for guest participants. - participant.setDisplayName((String) userMap.get("displayname")); - } - usersHashMap.put((String) internalHashMap.get("sessionid"), participant); - } - } - break; - case TARGET_PARTICIPANTS: - signalingMessageReceiver.process(eventOverallWebSocketMessage.getEventMap()); - break; - } - } - break; - case "message": - CallOverallWebSocketMessage callOverallWebSocketMessage = LoganSquare.parse(text, CallOverallWebSocketMessage.class); - NCSignalingMessage ncSignalingMessage = callOverallWebSocketMessage.getCallWebSocketMessage().getNcSignalingMessage(); - if (TextUtils.isEmpty(ncSignalingMessage.getFrom()) && callOverallWebSocketMessage.getCallWebSocketMessage().getSenderWebSocketMessage() != null) { - ncSignalingMessage.setFrom(callOverallWebSocketMessage.getCallWebSocketMessage().getSenderWebSocketMessage().getSessionId()); - } - - signalingMessageReceiver.process(ncSignalingMessage); - break; - case "bye": - connected = false; - resumeId = ""; - default: - break; + break; + default: + break; + } + } else { + Log.e(TAG, "Received message with type: null"); } } catch (IOException e) { Log.e(TAG, "Failed to recognize WebSocket message", e); @@ -295,6 +204,128 @@ public class MagicWebSocketInstance extends WebSocketListener { } } + private void processMessage(String text) throws IOException { + CallOverallWebSocketMessage callOverallWebSocketMessage = LoganSquare.parse(text, CallOverallWebSocketMessage.class); + NCSignalingMessage ncSignalingMessage = callOverallWebSocketMessage.getCallWebSocketMessage().getNcSignalingMessage(); + if (TextUtils.isEmpty(ncSignalingMessage.getFrom()) && callOverallWebSocketMessage.getCallWebSocketMessage().getSenderWebSocketMessage() != null) { + ncSignalingMessage.setFrom(callOverallWebSocketMessage.getCallWebSocketMessage().getSenderWebSocketMessage().getSessionId()); + } + + signalingMessageReceiver.process(ncSignalingMessage); + } + + private void processEventMessage(String text) throws IOException { + EventOverallWebSocketMessage eventOverallWebSocketMessage = LoganSquare.parse(text, EventOverallWebSocketMessage.class); + if (eventOverallWebSocketMessage.getEventMap() != null) { + String target = (String) eventOverallWebSocketMessage.getEventMap().get("target"); + switch (target) { + case "room": + if (eventOverallWebSocketMessage.getEventMap().get("type").equals("message")) { + processRoomMessageMessage(eventOverallWebSocketMessage); + } else if (eventOverallWebSocketMessage.getEventMap().get("type").equals("join")) { + processRoomJoinMessage(eventOverallWebSocketMessage); + } + break; + case TARGET_PARTICIPANTS: + signalingMessageReceiver.process(eventOverallWebSocketMessage.getEventMap()); + break; + } + } + } + + private void processRoomMessageMessage(EventOverallWebSocketMessage eventOverallWebSocketMessage) { + Map messageHashMap = (Map) eventOverallWebSocketMessage + .getEventMap() + .get("message"); + if (messageHashMap != null && messageHashMap.containsKey("data")) { + Map dataHashMap = (Map) messageHashMap.get("data"); + if (dataHashMap != null && dataHashMap.containsKey("chat")) { + Map chatMap = (Map) dataHashMap.get("chat"); + if (chatMap != null && chatMap.containsKey("refresh") && (boolean) chatMap.get("refresh")) { + HashMap refreshChatHashMap = new HashMap<>(); + refreshChatHashMap.put(BundleKeys.KEY_ROOM_TOKEN, (String) messageHashMap.get("roomid")); + refreshChatHashMap.put(BundleKeys.KEY_INTERNAL_USER_ID, Long.toString(conversationUser.getId())); + eventBus.post(new WebSocketCommunicationEvent("refreshChat", refreshChatHashMap)); + } + } + } + } + + private void processRoomJoinMessage(EventOverallWebSocketMessage eventOverallWebSocketMessage) { + List> joinEventList = (List>) eventOverallWebSocketMessage + .getEventMap() + .get("join"); + HashMap internalHashMap; + Participant participant; + for (int i = 0; i < joinEventList.size(); i++) { + internalHashMap = joinEventList.get(i); + HashMap userMap = (HashMap) internalHashMap.get("user"); + participant = new Participant(); + String userId = (String) internalHashMap.get("userid"); + if (userId != null) { + participant.setActorType(USERS); + participant.setActorId(userId); + } else { + participant.setActorType(GUESTS); + // FIXME seems to be not given by the HPB: participant.setActorId(); + } + if (userMap != null) { + // There is no "user" attribute for guest participants. + participant.setDisplayName((String) userMap.get("displayname")); + } + usersHashMap.put((String) internalHashMap.get("sessionid"), participant); + } + } + + private void processJoinedRoomMessage(String text) throws IOException { + JoinedRoomOverallWebSocketMessage joinedRoomOverallWebSocketMessage = LoganSquare.parse(text, JoinedRoomOverallWebSocketMessage.class); + currentRoomToken = joinedRoomOverallWebSocketMessage.getRoomWebSocketMessage().getRoomId(); + if (joinedRoomOverallWebSocketMessage.getRoomWebSocketMessage().getRoomPropertiesWebSocketMessage() != null && !TextUtils.isEmpty(currentRoomToken)) { + sendRoomJoinedEvent(); + } + } + + private void processErrorMessage(WebSocket webSocket, String text) throws IOException { + Log.e(TAG, "Received error: " + text); + ErrorOverallWebSocketMessage errorOverallWebSocketMessage = LoganSquare.parse(text, ErrorOverallWebSocketMessage.class); + if ("no_such_session".equals(errorOverallWebSocketMessage.getErrorWebSocketMessage().getCode())) { + Log.d(TAG, "WebSocket " + webSocket.hashCode() + " resumeID " + resumeId + " expired"); + resumeId = ""; + currentRoomToken = ""; + restartWebSocket(); + } else if ("hello_expected".equals(errorOverallWebSocketMessage.getErrorWebSocketMessage().getCode())) { + restartWebSocket(); + } + } + + private void processHelloMessage(WebSocket webSocket, String text) throws IOException { + connected = true; + reconnecting = false; + restartCount = 0; + String oldResumeId = resumeId; + HelloResponseOverallWebSocketMessage helloResponseWebSocketMessage = LoganSquare.parse(text, HelloResponseOverallWebSocketMessage.class); + resumeId = helloResponseWebSocketMessage.getHelloResponseWebSocketMessage().getResumeId(); + sessionId = helloResponseWebSocketMessage.getHelloResponseWebSocketMessage().getSessionId(); + hasMCU = helloResponseWebSocketMessage.getHelloResponseWebSocketMessage().serverHasMCUSupport(); + + for (int i = 0; i < messagesQueue.size(); i++) { + webSocket.send(messagesQueue.get(i)); + } + + messagesQueue = new ArrayList<>(); + HashMap helloHasHap = new HashMap<>(); + if (!TextUtils.isEmpty(oldResumeId)) { + helloHasHap.put("oldResumeId", oldResumeId); + } else { + currentRoomToken = ""; + } + + if (!TextUtils.isEmpty(currentRoomToken)) { + helloHasHap.put(ROOM_TOKEN, currentRoomToken); + } + eventBus.post(new WebSocketCommunicationEvent("hello", helloHasHap)); + } + private void sendRoomJoinedEvent() { HashMap joinRoomHashMap = new HashMap<>(); joinRoomHashMap.put(ROOM_TOKEN, currentRoomToken); From f48575bfec03fb997c569eef10ee88d8ff832dc4 Mon Sep 17 00:00:00 2001 From: Andy Scherzinger Date: Wed, 28 Dec 2022 14:33:10 +0100 Subject: [PATCH 17/23] Spotbug: Method stores return result in local before immediately returning it Signed-off-by: Andy Scherzinger --- .../com/nextcloud/talk/adapters/items/ContactItem.java | 8 +++++++- .../talk/adapters/items/NotificationSoundItem.java | 3 +-- .../talk/components/filebrowser/models/DavResponse.java | 3 +-- .../com/nextcloud/talk/dagger/modules/RestModule.java | 4 +--- .../main/java/com/nextcloud/talk/events/EventStatus.java | 3 +-- .../com/nextcloud/talk/events/MoreMenuClickEvent.java | 3 +-- .../main/java/com/nextcloud/talk/events/NetworkEvent.java | 3 +-- .../com/nextcloud/talk/events/UserMentionClickEvent.java | 3 +-- .../talk/events/WebSocketCommunicationEvent.java | 3 +-- .../java/com/nextcloud/talk/models/ImportAccount.java | 3 +-- .../main/java/com/nextcloud/talk/utils/text/Spans.java | 4 +--- 11 files changed, 17 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/ContactItem.java b/app/src/main/java/com/nextcloud/talk/adapters/items/ContactItem.java index b1504b45d..1d1b5c453 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/items/ContactItem.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/items/ContactItem.java @@ -38,6 +38,7 @@ import com.nextcloud.talk.models.json.participants.Participant; import com.nextcloud.talk.ui.theme.ViewThemeUtils; import java.util.List; +import java.util.Objects; import java.util.regex.Pattern; import androidx.core.content.res.ResourcesCompat; @@ -171,10 +172,15 @@ public class ContactItem extends AbstractFlexibleItem>> 32 ^ $userId); final Object $eventType = this.getEventType(); result = result * PRIME + ($eventType == null ? 43 : $eventType.hashCode()); - result = result * PRIME + (this.isAllGood() ? 79 : 97); - return result; + return result * PRIME + (this.isAllGood() ? 79 : 97); } public String toString() { diff --git a/app/src/main/java/com/nextcloud/talk/events/MoreMenuClickEvent.java b/app/src/main/java/com/nextcloud/talk/events/MoreMenuClickEvent.java index 38d452a79..742c948a3 100644 --- a/app/src/main/java/com/nextcloud/talk/events/MoreMenuClickEvent.java +++ b/app/src/main/java/com/nextcloud/talk/events/MoreMenuClickEvent.java @@ -58,8 +58,7 @@ public class MoreMenuClickEvent { final int PRIME = 59; int result = 1; final Object $conversation = this.getConversation(); - result = result * PRIME + ($conversation == null ? 43 : $conversation.hashCode()); - return result; + return result * PRIME + ($conversation == null ? 43 : $conversation.hashCode()); } public String toString() { diff --git a/app/src/main/java/com/nextcloud/talk/events/NetworkEvent.java b/app/src/main/java/com/nextcloud/talk/events/NetworkEvent.java index 2167c92c4..7489c053b 100644 --- a/app/src/main/java/com/nextcloud/talk/events/NetworkEvent.java +++ b/app/src/main/java/com/nextcloud/talk/events/NetworkEvent.java @@ -56,8 +56,7 @@ public class NetworkEvent { final int PRIME = 59; int result = 1; final Object $networkConnectionEvent = this.getNetworkConnectionEvent(); - result = result * PRIME + ($networkConnectionEvent == null ? 43 : $networkConnectionEvent.hashCode()); - return result; + return result * PRIME + ($networkConnectionEvent == null ? 43 : $networkConnectionEvent.hashCode()); } public String toString() { diff --git a/app/src/main/java/com/nextcloud/talk/events/UserMentionClickEvent.java b/app/src/main/java/com/nextcloud/talk/events/UserMentionClickEvent.java index 467a18412..b19aab076 100644 --- a/app/src/main/java/com/nextcloud/talk/events/UserMentionClickEvent.java +++ b/app/src/main/java/com/nextcloud/talk/events/UserMentionClickEvent.java @@ -56,8 +56,7 @@ public class UserMentionClickEvent { final int PRIME = 59; int result = 1; final Object $userId = this.getUserId(); - result = result * PRIME + ($userId == null ? 43 : $userId.hashCode()); - return result; + return result * PRIME + ($userId == null ? 43 : $userId.hashCode()); } public String toString() { diff --git a/app/src/main/java/com/nextcloud/talk/events/WebSocketCommunicationEvent.java b/app/src/main/java/com/nextcloud/talk/events/WebSocketCommunicationEvent.java index 532869e9f..3662b4e80 100644 --- a/app/src/main/java/com/nextcloud/talk/events/WebSocketCommunicationEvent.java +++ b/app/src/main/java/com/nextcloud/talk/events/WebSocketCommunicationEvent.java @@ -75,8 +75,7 @@ public class WebSocketCommunicationEvent { final Object $type = this.getType(); result = result * PRIME + ($type == null ? 43 : $type.hashCode()); final Object $hashMap = this.getHashMap(); - result = result * PRIME + ($hashMap == null ? 43 : $hashMap.hashCode()); - return result; + return result * PRIME + ($hashMap == null ? 43 : $hashMap.hashCode()); } public String toString() { diff --git a/app/src/main/java/com/nextcloud/talk/models/ImportAccount.java b/app/src/main/java/com/nextcloud/talk/models/ImportAccount.java index 56dd426d8..6fd952897 100644 --- a/app/src/main/java/com/nextcloud/talk/models/ImportAccount.java +++ b/app/src/main/java/com/nextcloud/talk/models/ImportAccount.java @@ -98,8 +98,7 @@ public class ImportAccount { final Object $token = this.getToken(); result = result * PRIME + ($token == null ? 43 : $token.hashCode()); final Object $baseUrl = this.getBaseUrl(); - result = result * PRIME + ($baseUrl == null ? 43 : $baseUrl.hashCode()); - return result; + return result * PRIME + ($baseUrl == null ? 43 : $baseUrl.hashCode()); } public String toString() { diff --git a/app/src/main/java/com/nextcloud/talk/utils/text/Spans.java b/app/src/main/java/com/nextcloud/talk/utils/text/Spans.java index 50d6bfa07..12de790a1 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/text/Spans.java +++ b/app/src/main/java/com/nextcloud/talk/utils/text/Spans.java @@ -87,13 +87,11 @@ public class Spans { final Object $id = this.getId(); result = result * PRIME + ($id == null ? 43 : $id.hashCode()); final Object $label = this.getLabel(); - result = result * PRIME + ($label == null ? 43 : $label.hashCode()); - return result; + return result * PRIME + ($label == null ? 43 : $label.hashCode()); } public String toString() { return "Spans.MentionChipSpan(id=" + this.getId() + ", label=" + this.getLabel() + ")"; } } - } From a33f3fe40012c82316058a3417f51c2f6a9b3b4d Mon Sep 17 00:00:00 2001 From: Andy Scherzinger Date: Wed, 28 Dec 2022 14:44:38 +0100 Subject: [PATCH 18/23] Spotbug: Simple field is used like an enum Signed-off-by: Andy Scherzinger --- .../com/nextcloud/talk/ui/StatusDrawable.java | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/ui/StatusDrawable.java b/app/src/main/java/com/nextcloud/talk/ui/StatusDrawable.java index 258263327..b2a1fe1b8 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/StatusDrawable.java +++ b/app/src/main/java/com/nextcloud/talk/ui/StatusDrawable.java @@ -42,9 +42,9 @@ import androidx.core.content.res.ResourcesCompat; */ public class StatusDrawable extends Drawable { private String text; - private @DrawableRes int icon = -1; + private StatusDrawableType icon = StatusDrawableType.UNDEFINED; private Paint textPaint; - private int backgroundColor; + private final int backgroundColor; private final float radius; private Context context; @@ -54,17 +54,17 @@ public class StatusDrawable extends Drawable { if ("dnd".equals(status)) { - icon = R.drawable.ic_user_status_dnd; + icon = StatusDrawableType.DND; this.context = context; } else if (TextUtils.isEmpty(statusIcon) && status != null) { switch (status) { case "online": - icon = R.drawable.online_status; + icon = StatusDrawableType.ONLINE; this.context = context; break; case "away": - icon = R.drawable.ic_user_status_away; + icon = StatusDrawableType.AWAY; this.context = context; break; @@ -95,7 +95,7 @@ public class StatusDrawable extends Drawable { canvas.drawText(text, radius, radius - ((textPaint.descent() + textPaint.ascent()) / 2), textPaint); } - if (icon != -1) { + if (icon != StatusDrawableType.UNDEFINED) { Paint backgroundPaint = new Paint(); backgroundPaint.setStyle(Paint.Style.FILL); @@ -104,7 +104,7 @@ public class StatusDrawable extends Drawable { canvas.drawCircle(radius, radius, radius, backgroundPaint); - Drawable drawable = ResourcesCompat.getDrawable(context.getResources(), icon, null); + Drawable drawable = ResourcesCompat.getDrawable(context.getResources(), icon.drawableId, null); if (drawable != null) { drawable.setBounds(0, @@ -130,4 +130,18 @@ public class StatusDrawable extends Drawable { public int getOpacity() { return PixelFormat.TRANSLUCENT; } + + private enum StatusDrawableType { + DND(R.drawable.ic_user_status_dnd), + ONLINE(R.drawable.online_status), + AWAY(R.drawable.ic_user_status_away), + UNDEFINED(-1); + + @DrawableRes + private final int drawableId; + + StatusDrawableType(int drawableId) { + this.drawableId = drawableId; + } + } } From 8b9996814fe00953a9cde955da800512b331532d Mon Sep 17 00:00:00 2001 From: Andy Scherzinger Date: Thu, 29 Dec 2022 09:23:21 +0100 Subject: [PATCH 19/23] Spotbugs: NPE deference, NPE-equals, unused variable, make vars final, reformat code for line-length 120 chars Signed-off-by: Andy Scherzinger --- .../com/nextcloud/talk/webrtc/Globals.java | 1 + .../talk/webrtc/MagicWebSocketInstance.java | 114 +++++++++++------- 2 files changed, 72 insertions(+), 43 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/webrtc/Globals.java b/app/src/main/java/com/nextcloud/talk/webrtc/Globals.java index 5e27542ee..317e2939e 100644 --- a/app/src/main/java/com/nextcloud/talk/webrtc/Globals.java +++ b/app/src/main/java/com/nextcloud/talk/webrtc/Globals.java @@ -4,4 +4,5 @@ public class Globals { public static final String ROOM_TOKEN = "roomToken"; public static final String TARGET_PARTICIPANTS = "participants"; + public static final String TARGET_ROOM = "room"; } diff --git a/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java b/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java index 42ad896e1..ce3e317d6 100644 --- a/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java +++ b/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java @@ -67,12 +67,12 @@ import static com.nextcloud.talk.models.json.participants.Participant.ActorType. import static com.nextcloud.talk.models.json.participants.Participant.ActorType.USERS; import static com.nextcloud.talk.webrtc.Globals.ROOM_TOKEN; import static com.nextcloud.talk.webrtc.Globals.TARGET_PARTICIPANTS; +import static com.nextcloud.talk.webrtc.Globals.TARGET_ROOM; @AutoInjector(NextcloudTalkApplication.class) public class MagicWebSocketInstance extends WebSocketListener { private static final String TAG = "MagicWebSocketInstance"; - @Inject OkHttpClient okHttpClient; @@ -82,18 +82,17 @@ public class MagicWebSocketInstance extends WebSocketListener { @Inject Context context; - private User conversationUser; - private String webSocketTicket; + private final User conversationUser; + private final String webSocketTicket; private String resumeId; private String sessionId; private boolean hasMCU; private boolean connected; - private WebSocketConnectionHelper webSocketConnectionHelper; + private final WebSocketConnectionHelper webSocketConnectionHelper; private WebSocket internalWebSocket; - private String connectionUrl; + private final String connectionUrl; private String currentRoomToken; - private int restartCount = 0; private boolean reconnecting = false; private HashMap usersHashMap; @@ -122,9 +121,13 @@ public class MagicWebSocketInstance extends WebSocketListener { private void sendHello() { try { if (TextUtils.isEmpty(resumeId)) { - internalWebSocket.send(LoganSquare.serialize(webSocketConnectionHelper.getAssembledHelloModel(conversationUser, webSocketTicket))); + internalWebSocket.send( + LoganSquare.serialize(webSocketConnectionHelper + .getAssembledHelloModel(conversationUser, webSocketTicket))); } else { - internalWebSocket.send(LoganSquare.serialize(webSocketConnectionHelper.getAssembledHelloModelForResume(resumeId))); + internalWebSocket.send( + LoganSquare.serialize(webSocketConnectionHelper + .getAssembledHelloModelForResume(resumeId))); } } catch (IOException e) { Log.e(TAG, "Failed to serialize hello model"); @@ -160,7 +163,6 @@ public class MagicWebSocketInstance extends WebSocketListener { Log.d(TAG, "restartWebSocket: " + connectionUrl); Request request = new Request.Builder().url(connectionUrl).build(); okHttpClient.newWebSocket(request, this); - restartCount++; } @Override @@ -205,30 +207,43 @@ public class MagicWebSocketInstance extends WebSocketListener { } private void processMessage(String text) throws IOException { - CallOverallWebSocketMessage callOverallWebSocketMessage = LoganSquare.parse(text, CallOverallWebSocketMessage.class); - NCSignalingMessage ncSignalingMessage = callOverallWebSocketMessage.getCallWebSocketMessage().getNcSignalingMessage(); - if (TextUtils.isEmpty(ncSignalingMessage.getFrom()) && callOverallWebSocketMessage.getCallWebSocketMessage().getSenderWebSocketMessage() != null) { - ncSignalingMessage.setFrom(callOverallWebSocketMessage.getCallWebSocketMessage().getSenderWebSocketMessage().getSessionId()); + CallOverallWebSocketMessage callOverallWebSocketMessage = + LoganSquare.parse(text, CallOverallWebSocketMessage.class); + NCSignalingMessage ncSignalingMessage = callOverallWebSocketMessage + .getCallWebSocketMessage() + .getNcSignalingMessage(); + if (TextUtils.isEmpty(ncSignalingMessage.getFrom()) && + callOverallWebSocketMessage.getCallWebSocketMessage().getSenderWebSocketMessage() != null) { + ncSignalingMessage.setFrom( + callOverallWebSocketMessage.getCallWebSocketMessage().getSenderWebSocketMessage().getSessionId()); } signalingMessageReceiver.process(ncSignalingMessage); } private void processEventMessage(String text) throws IOException { - EventOverallWebSocketMessage eventOverallWebSocketMessage = LoganSquare.parse(text, EventOverallWebSocketMessage.class); + EventOverallWebSocketMessage eventOverallWebSocketMessage = + LoganSquare.parse(text, EventOverallWebSocketMessage.class); if (eventOverallWebSocketMessage.getEventMap() != null) { String target = (String) eventOverallWebSocketMessage.getEventMap().get("target"); - switch (target) { - case "room": - if (eventOverallWebSocketMessage.getEventMap().get("type").equals("message")) { - processRoomMessageMessage(eventOverallWebSocketMessage); - } else if (eventOverallWebSocketMessage.getEventMap().get("type").equals("join")) { - processRoomJoinMessage(eventOverallWebSocketMessage); - } - break; - case TARGET_PARTICIPANTS: - signalingMessageReceiver.process(eventOverallWebSocketMessage.getEventMap()); - break; + if (target != null) { + switch (target) { + case TARGET_ROOM: + if ("message".equals(eventOverallWebSocketMessage.getEventMap().get("type"))) { + processRoomMessageMessage(eventOverallWebSocketMessage); + } else if ("join".equals(eventOverallWebSocketMessage.getEventMap().get("type"))) { + processRoomJoinMessage(eventOverallWebSocketMessage); + } + break; + case TARGET_PARTICIPANTS: + signalingMessageReceiver.process(eventOverallWebSocketMessage.getEventMap()); + break; + default: + Log.i(TAG, "Received unknown/ignored event target: " + target); + break; + } + } else { + Log.w(TAG, "Received message with event target: null"); } } } @@ -278,16 +293,24 @@ public class MagicWebSocketInstance extends WebSocketListener { } private void processJoinedRoomMessage(String text) throws IOException { - JoinedRoomOverallWebSocketMessage joinedRoomOverallWebSocketMessage = LoganSquare.parse(text, JoinedRoomOverallWebSocketMessage.class); - currentRoomToken = joinedRoomOverallWebSocketMessage.getRoomWebSocketMessage().getRoomId(); - if (joinedRoomOverallWebSocketMessage.getRoomWebSocketMessage().getRoomPropertiesWebSocketMessage() != null && !TextUtils.isEmpty(currentRoomToken)) { - sendRoomJoinedEvent(); + JoinedRoomOverallWebSocketMessage joinedRoomOverallWebSocketMessage = + LoganSquare.parse(text, JoinedRoomOverallWebSocketMessage.class); + if (joinedRoomOverallWebSocketMessage.getRoomWebSocketMessage() != null) { + currentRoomToken = joinedRoomOverallWebSocketMessage.getRoomWebSocketMessage().getRoomId(); + + if (joinedRoomOverallWebSocketMessage + .getRoomWebSocketMessage() + .getRoomPropertiesWebSocketMessage() != null && + !TextUtils.isEmpty(currentRoomToken)) { + sendRoomJoinedEvent(); + } } } private void processErrorMessage(WebSocket webSocket, String text) throws IOException { Log.e(TAG, "Received error: " + text); - ErrorOverallWebSocketMessage errorOverallWebSocketMessage = LoganSquare.parse(text, ErrorOverallWebSocketMessage.class); + ErrorOverallWebSocketMessage errorOverallWebSocketMessage = + LoganSquare.parse(text, ErrorOverallWebSocketMessage.class); if ("no_such_session".equals(errorOverallWebSocketMessage.getErrorWebSocketMessage().getCode())) { Log.d(TAG, "WebSocket " + webSocket.hashCode() + " resumeID " + resumeId + " expired"); resumeId = ""; @@ -301,12 +324,14 @@ public class MagicWebSocketInstance extends WebSocketListener { private void processHelloMessage(WebSocket webSocket, String text) throws IOException { connected = true; reconnecting = false; - restartCount = 0; String oldResumeId = resumeId; - HelloResponseOverallWebSocketMessage helloResponseWebSocketMessage = LoganSquare.parse(text, HelloResponseOverallWebSocketMessage.class); - resumeId = helloResponseWebSocketMessage.getHelloResponseWebSocketMessage().getResumeId(); - sessionId = helloResponseWebSocketMessage.getHelloResponseWebSocketMessage().getSessionId(); - hasMCU = helloResponseWebSocketMessage.getHelloResponseWebSocketMessage().serverHasMCUSupport(); + HelloResponseOverallWebSocketMessage helloResponseWebSocketMessage = + LoganSquare.parse(text, HelloResponseOverallWebSocketMessage.class); + if (helloResponseWebSocketMessage.getHelloResponseWebSocketMessage() != null) { + resumeId = helloResponseWebSocketMessage.getHelloResponseWebSocketMessage().getResumeId(); + sessionId = helloResponseWebSocketMessage.getHelloResponseWebSocketMessage().getSessionId(); + hasMCU = helloResponseWebSocketMessage.getHelloResponseWebSocketMessage().serverHasMCUSupport(); + } for (int i = 0; i < messagesQueue.size(); i++) { webSocket.send(messagesQueue.get(i)); @@ -333,12 +358,12 @@ public class MagicWebSocketInstance extends WebSocketListener { } @Override - public void onMessage(WebSocket webSocket, ByteString bytes) { + public void onMessage(@NonNull WebSocket webSocket, ByteString bytes) { Log.d(TAG, "Receiving bytes : " + bytes.hex()); } @Override - public void onClosing(WebSocket webSocket, int code, String reason) { + public void onClosing(@NonNull WebSocket webSocket, int code, @NonNull String reason) { Log.d(TAG, "Closing : " + code + " / " + reason); } @@ -361,7 +386,8 @@ public class MagicWebSocketInstance extends WebSocketListener { Log.d(TAG, " roomToken: " + roomToken); Log.d(TAG, " session: " + normalBackendSession); try { - String message = LoganSquare.serialize(webSocketConnectionHelper.getAssembledJoinOrLeaveRoomModel(roomToken, normalBackendSession)); + String message = LoganSquare.serialize( + webSocketConnectionHelper.getAssembledJoinOrLeaveRoomModel(roomToken, normalBackendSession)); if (!connected || reconnecting) { messagesQueue.add(message); } else { @@ -378,7 +404,8 @@ public class MagicWebSocketInstance extends WebSocketListener { private void sendCallMessage(NCSignalingMessage ncSignalingMessage) { try { - String message = LoganSquare.serialize(webSocketConnectionHelper.getAssembledCallMessageModel(ncSignalingMessage)); + String message = LoganSquare.serialize( + webSocketConnectionHelper.getAssembledCallMessageModel(ncSignalingMessage)); if (!connected || reconnecting) { messagesQueue.add(message); } else { @@ -419,7 +446,8 @@ public class MagicWebSocketInstance extends WebSocketListener { @Subscribe(threadMode = ThreadMode.BACKGROUND) public void onMessageEvent(NetworkEvent networkEvent) { - if (networkEvent.getNetworkConnectionEvent() == NetworkEvent.NetworkConnectionEvent.NETWORK_CONNECTED && !isConnected()) { + if (networkEvent.getNetworkConnectionEvent() == NetworkEvent.NetworkConnectionEvent.NETWORK_CONNECTED && + !isConnected()) { restartWebSocket(); } } @@ -435,9 +463,9 @@ public class MagicWebSocketInstance extends WebSocketListener { /** * Temporary implementation of SignalingMessageReceiver until signaling related code is extracted to a Signaling * class. - * - * All listeners are called in the WebSocket reader thread. This thread should be the same as long as the - * WebSocket stays connected, but it may change whenever it is connected again. + *

+ * All listeners are called in the WebSocket reader thread. This thread should be the same as long as the WebSocket + * stays connected, but it may change whenever it is connected again. */ private static class ExternalSignalingMessageReceiver extends SignalingMessageReceiver { public void process(Map eventMap) { From efdfe8350791a1366e43c702a6da8386c157fbb4 Mon Sep 17 00:00:00 2001 From: Andy Scherzinger Date: Thu, 29 Dec 2022 09:30:41 +0100 Subject: [PATCH 20/23] Spotbugs: remove NPE deference Signed-off-by: Andy Scherzinger --- .../talk/webrtc/MagicWebSocketInstance.java | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java b/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java index ce3e317d6..f8333d4c9 100644 --- a/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java +++ b/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java @@ -209,16 +209,19 @@ public class MagicWebSocketInstance extends WebSocketListener { private void processMessage(String text) throws IOException { CallOverallWebSocketMessage callOverallWebSocketMessage = LoganSquare.parse(text, CallOverallWebSocketMessage.class); - NCSignalingMessage ncSignalingMessage = callOverallWebSocketMessage - .getCallWebSocketMessage() - .getNcSignalingMessage(); - if (TextUtils.isEmpty(ncSignalingMessage.getFrom()) && - callOverallWebSocketMessage.getCallWebSocketMessage().getSenderWebSocketMessage() != null) { - ncSignalingMessage.setFrom( - callOverallWebSocketMessage.getCallWebSocketMessage().getSenderWebSocketMessage().getSessionId()); - } - signalingMessageReceiver.process(ncSignalingMessage); + if (callOverallWebSocketMessage.getCallWebSocketMessage() != null) { + NCSignalingMessage ncSignalingMessage = callOverallWebSocketMessage + .getCallWebSocketMessage() + .getNcSignalingMessage(); + if (ncSignalingMessage != null && TextUtils.isEmpty(ncSignalingMessage.getFrom()) && + callOverallWebSocketMessage.getCallWebSocketMessage().getSenderWebSocketMessage() != null) { + ncSignalingMessage.setFrom( + callOverallWebSocketMessage.getCallWebSocketMessage().getSenderWebSocketMessage().getSessionId()); + } + + signalingMessageReceiver.process(ncSignalingMessage); + } } private void processEventMessage(String text) throws IOException { From 9ae722659fb36066de25fe12522bba367b905327 Mon Sep 17 00:00:00 2001 From: Andy Scherzinger Date: Thu, 29 Dec 2022 09:31:14 +0100 Subject: [PATCH 21/23] Spotbugs: don't doubleCheck Map contains value, just check for null Signed-off-by: Andy Scherzinger --- .../talk/webrtc/WebSocketConnectionHelper.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/webrtc/WebSocketConnectionHelper.java b/app/src/main/java/com/nextcloud/talk/webrtc/WebSocketConnectionHelper.java index 096e71b10..52259b03c 100644 --- a/app/src/main/java/com/nextcloud/talk/webrtc/WebSocketConnectionHelper.java +++ b/app/src/main/java/com/nextcloud/talk/webrtc/WebSocketConnectionHelper.java @@ -60,11 +60,13 @@ public class WebSocketConnectionHelper { @SuppressLint("LongLogTag") public static synchronized MagicWebSocketInstance getMagicWebSocketInstanceForUserId(long userId) { - if (userId != -1 && magicWebSocketInstanceMap.containsKey(userId)) { - return magicWebSocketInstanceMap.get(userId); + MagicWebSocketInstance webSocketInstance = magicWebSocketInstanceMap.get(userId); + + if (webSocketInstance == null) { + Log.d(TAG, "No magicWebSocketInstance found for user " + userId); } - Log.d(TAG, "no magicWebSocketInstance found"); - return null; + + return webSocketInstance; } public static synchronized MagicWebSocketInstance getExternalSignalingInstanceForServer(String url, From b36195dc9a69701410cee4f1cd74597bca2d99cb Mon Sep 17 00:00:00 2001 From: Andy Scherzinger Date: Thu, 29 Dec 2022 11:14:16 +0100 Subject: [PATCH 22/23] UI binding can never be null Signed-off-by: Andy Scherzinger --- .../talk/adapters/items/ParticipantItem.java | 90 +++++++++---------- 1 file changed, 44 insertions(+), 46 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/ParticipantItem.java b/app/src/main/java/com/nextcloud/talk/adapters/items/ParticipantItem.java index 0d2a3cc9e..2eb6a22df 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/items/ParticipantItem.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/items/ParticipantItem.java @@ -196,63 +196,61 @@ public class ParticipantItem extends AbstractFlexibleItem Date: Thu, 29 Dec 2022 11:17:08 +0100 Subject: [PATCH 23/23] Spotbugs: Defere NPE Signed-off-by: Andy Scherzinger --- .../talk/webrtc/MagicWebSocketInstance.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java b/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java index f8333d4c9..9c7cc3f94 100644 --- a/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java +++ b/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java @@ -35,6 +35,7 @@ import com.nextcloud.talk.models.json.websocket.BaseWebSocketMessage; import com.nextcloud.talk.models.json.websocket.ByeWebSocketMessage; import com.nextcloud.talk.models.json.websocket.CallOverallWebSocketMessage; import com.nextcloud.talk.models.json.websocket.ErrorOverallWebSocketMessage; +import com.nextcloud.talk.models.json.websocket.ErrorWebSocketMessage; import com.nextcloud.talk.models.json.websocket.EventOverallWebSocketMessage; import com.nextcloud.talk.models.json.websocket.HelloResponseOverallWebSocketMessage; import com.nextcloud.talk.models.json.websocket.JoinedRoomOverallWebSocketMessage; @@ -314,13 +315,17 @@ public class MagicWebSocketInstance extends WebSocketListener { Log.e(TAG, "Received error: " + text); ErrorOverallWebSocketMessage errorOverallWebSocketMessage = LoganSquare.parse(text, ErrorOverallWebSocketMessage.class); - if ("no_such_session".equals(errorOverallWebSocketMessage.getErrorWebSocketMessage().getCode())) { - Log.d(TAG, "WebSocket " + webSocket.hashCode() + " resumeID " + resumeId + " expired"); - resumeId = ""; - currentRoomToken = ""; - restartWebSocket(); - } else if ("hello_expected".equals(errorOverallWebSocketMessage.getErrorWebSocketMessage().getCode())) { - restartWebSocket(); + ErrorWebSocketMessage message = errorOverallWebSocketMessage.getErrorWebSocketMessage(); + + if(message != null) { + if ("no_such_session".equals(message.getCode())) { + Log.d(TAG, "WebSocket " + webSocket.hashCode() + " resumeID " + resumeId + " expired"); + resumeId = ""; + currentRoomToken = ""; + restartWebSocket(); + } else if ("hello_expected".equals(message.getCode())) { + restartWebSocket(); + } } }