Skip to content

Commit 26203ec

Browse files
committed
Merge branch 'develop' into bugfix/issue_1857_android_14_broadcast
2 parents 43942d5 + 7873fb5 commit 26203ec

16 files changed

Lines changed: 343 additions & 34 deletions

File tree

.github/workflows/android.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,3 @@ jobs:
5555
- name: Sdl JavaEE Tests
5656
run: ./javaEE/gradlew -p ./javaEE/javaEE test
5757

58-
59-

android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/choiceset/ChoiceSetManagerTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ public void tearDown() throws Exception {
113113
assertNull(csm.currentSystemContext);
114114
assertNull(csm.defaultMainWindowCapability);
115115

116-
assertEquals(csm.transactionQueue.getTasksAsList().size(), 0);
116+
assertNull(csm.transactionQueue);
117117

118118
assertFalse(csm.isVROptional);
119119

android/sdl_android/src/androidTest/java/com/smartdevicelink/transport/TransportBrokerTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,24 +117,24 @@ public void testSendMessageToRouterService() {
117117
broker.routerServiceMessenger = null;
118118
broker.isBound = true;
119119

120-
assertFalse(broker.sendMessageToRouterService(message));
120+
assertFalse(broker.sendMessageToRouterService(message, 0));
121121

122122
broker.routerServiceMessenger = new Messenger(handler); //So it's not ambiguous
123123

124124
broker.isBound = false;
125125

126-
assertFalse(broker.sendMessageToRouterService(message));
126+
assertFalse(broker.sendMessageToRouterService(message, 0));
127127

128128
broker.isBound = true;
129129
broker.registeredWithRouterService = true;
130130

131131
message = null;
132132

133-
assertFalse(broker.sendMessageToRouterService(message));
133+
assertFalse(broker.sendMessageToRouterService(message, 0));
134134

135135
message = new Message();
136136

137-
assertTrue(broker.sendMessageToRouterService(message));
137+
assertTrue(broker.sendMessageToRouterService(message, 0));
138138

139139
}
140140

android/sdl_android/src/main/java/com/smartdevicelink/managers/audio/AudioStreamManager.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,11 @@ public void onDecoderError(Exception e) {
437437
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
438438
decoder = new AudioDecoder(audioSource, context.get(), sdlSampleRate, sdlSampleType, decoderListener);
439439
} else {
440+
if (getTransactionQueue() == null) {
441+
DebugTool.logError(TAG, "Queue is null, cannot push audio source");
442+
finish(completionListener, false);
443+
return;
444+
}
440445
// this BaseAudioDecoder subclass uses methods deprecated with api 21
441446
decoder = new AudioDecoderCompat(getTransactionQueue(), audioSource, context.get(), sdlSampleRate, sdlSampleType, decoderListener);
442447
}

android/sdl_android/src/main/java/com/smartdevicelink/managers/lifecycle/LifecycleManager.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ void onTransportDisconnected(String info, boolean availablePrimary, BaseTranspor
167167
DebugTool.logInfo(TAG, "notifying RPC session ended, but potential primary transport available");
168168
cycle(SdlDisconnectedReason.PRIMARY_TRANSPORT_CYCLE_REQUEST);
169169
} else {
170+
clean(false);
170171
onClose(info, null, null);
171172
}
172173
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package com.smartdevicelink.transport;
2+
3+
import android.os.Message;
4+
5+
import androidx.annotation.RestrictTo;
6+
7+
import java.util.LinkedList;
8+
import java.util.Queue;
9+
10+
@RestrictTo(RestrictTo.Scope.LIBRARY)
11+
public class RouterServiceMessageEmitter extends Thread {
12+
13+
protected final Object QUEUE_LOCK = new Object();
14+
private boolean isHalted = false, isWaiting = false;
15+
private final Callback callback;
16+
private final Queue<Message> queue = new LinkedList<>();
17+
18+
public RouterServiceMessageEmitter(Callback callback) {
19+
this.setName("RouterServiceMessageEmitter");
20+
this.setDaemon(true);
21+
this.callback = callback;
22+
}
23+
24+
@Override
25+
public void run() {
26+
while (!isHalted) {
27+
try {
28+
Message message;
29+
synchronized (QUEUE_LOCK) {
30+
message = getNextTask();
31+
if (message != null && callback != null) {
32+
callback.onMessageToSend(message);
33+
} else {
34+
isWaiting = true;
35+
QUEUE_LOCK.wait();
36+
isWaiting = false;
37+
}
38+
}
39+
} catch (InterruptedException e) {
40+
break;
41+
}
42+
}
43+
}
44+
45+
protected void alert() {
46+
if (isWaiting) {
47+
synchronized (QUEUE_LOCK) {
48+
QUEUE_LOCK.notify();
49+
}
50+
}
51+
}
52+
53+
protected void close() {
54+
this.isHalted = true;
55+
if (queue != null) {
56+
queue.clear();
57+
}
58+
}
59+
60+
/**
61+
* Insert the task in the queue where it belongs
62+
*
63+
* @param message the new Message that needs to be added to the queue to be handled
64+
*/
65+
public void add(Message message) {
66+
synchronized (this) {
67+
if (message != null && queue != null) {
68+
queue.add(message);
69+
}
70+
}
71+
}
72+
73+
/**
74+
* Remove the head of the queue
75+
*
76+
* @return the old head of the queue
77+
*/
78+
private Message getNextTask() {
79+
synchronized (this) {
80+
if (queue != null) {
81+
return queue.poll();
82+
} else {
83+
return null;
84+
}
85+
}
86+
}
87+
88+
protected interface Callback {
89+
boolean onMessageToSend(Message message);
90+
}
91+
}

android/sdl_android/src/main/java/com/smartdevicelink/transport/SdlBroadcastReceiver.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ public void onReceive(Context context, Intent intent) {
129129

130130
if (action.equalsIgnoreCase(TransportConstants.ACTION_USB_ACCESSORY_ATTACHED)) {
131131
DebugTool.logInfo(TAG, "Usb connected");
132+
setForegroundExceptionHandler();
132133
intent.setAction(null);
133134
onSdlEnabled(context, intent);
134135
return;
@@ -189,6 +190,7 @@ public void onListObtained(boolean successful) {
189190
finalIntent.putExtra(UsbManager.EXTRA_ACCESSORY, (Parcelable) null);
190191
}
191192
}
193+
setForegroundExceptionHandler();
192194
onSdlEnabled(finalContext, finalIntent);
193195
}
194196

@@ -421,7 +423,7 @@ static protected void setForegroundExceptionHandler() {
421423
public void uncaughtException(Thread t, Throwable e) {
422424
if (e != null
423425
&& e instanceof AndroidRuntimeException
424-
&& ("android.app.RemoteServiceException".equals(e.getClass().getName()) || "android.app.ForegroundServiceDidNotStartInTimeException".equals(e.getClass().getName())) //android.app.RemoteServiceException is a private class
426+
&& ("android.app.RemoteServiceException".equals(e.getClass().getName()) || e.getClass().getName().contains("ForegroundService")) //android.app.RemoteServiceException is a private class
425427
&& e.getMessage() != null
426428
&& (e.getMessage().contains("SdlRouterService") || e.getMessage().contains(serviceName))) {
427429
DebugTool.logInfo(TAG, "Handling failed startForegroundService call");

android/sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2943,6 +2943,9 @@ protected PacketWriteTask getNextTask(TransportType transportType) {
29432943
long currentPriority = -Long.MAX_VALUE, peekWeight;
29442944
synchronized (REGISTERED_APPS_LOCK) {
29452945
PacketWriteTask peekTask;
2946+
if (registeredApps == null) {
2947+
return null;
2948+
}
29462949
for (RegisteredApp app : registeredApps.values()) {
29472950
peekTask = app.peekNextTask(transportType);
29482951
if (peekTask != null) {
@@ -3913,6 +3916,13 @@ public void clear() {
39133916
@TargetApi(11)
39143917
@SuppressLint("NewApi")
39153918
private void notifySppError() {
3919+
synchronized (FOREGROUND_NOTIFICATION_LOCK) {
3920+
// Check first to see if the RouterService is in the Foreground
3921+
// This is to prevent the notification appearing in error
3922+
if (!this.isForeground) {
3923+
return;
3924+
}
3925+
}
39163926
Notification.Builder builder;
39173927
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
39183928
builder = new Notification.Builder(getApplicationContext());

android/sdl_android/src/main/java/com/smartdevicelink/transport/TransportBroker.java

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ public class TransportBroker {
9191

9292
Messenger routerServiceMessenger = null;
9393
final Messenger clientMessenger;
94+
private RouterServiceMessageEmitter routerServiceMessageEmitter;
9495

9596
boolean isBound = false, registeredWithRouterService = false;
9697
private String routerPackage = null, routerClassName = null;
@@ -109,6 +110,13 @@ private void initRouterConnection() {
109110

110111
public void onServiceConnected(ComponentName className, IBinder service) {
111112
DebugTool.logInfo(TAG, "Bound to service " + className.toString());
113+
routerServiceMessageEmitter = new RouterServiceMessageEmitter(new RouterServiceMessageEmitter.Callback() {
114+
@Override
115+
public boolean onMessageToSend(Message message) {
116+
return sendMessageToRouterService(message, 0);
117+
}
118+
});
119+
routerServiceMessageEmitter.start();
112120
routerServiceMessenger = new Messenger(service);
113121
isBound = true;
114122
//So we just established our connection
@@ -118,7 +126,7 @@ public void onServiceConnected(ComponentName className, IBinder service) {
118126

119127
public void onServiceDisconnected(ComponentName className) {
120128
DebugTool.logInfo(TAG, "Unbound from service " + className.getClassName());
121-
routerServiceMessenger = null;
129+
shutDownRouterServiceMessenger();
122130
registeredWithRouterService = false;
123131
isBound = false;
124132
onHardwareDisconnected(null, null);
@@ -127,7 +135,12 @@ public void onServiceDisconnected(ComponentName className) {
127135
}
128136

129137
protected boolean sendMessageToRouterService(Message message) {
130-
return sendMessageToRouterService(message, 0);
138+
if (routerServiceMessageEmitter != null) {
139+
routerServiceMessageEmitter.add(message);
140+
routerServiceMessageEmitter.alert();
141+
}
142+
// Updated to only return true as we have added sending messages to SdlRouterService to be on a different thread.
143+
return true;
131144
}
132145

133146
protected boolean sendMessageToRouterService(Message message, int retryCount) {
@@ -152,7 +165,7 @@ protected boolean sendMessageToRouterService(Message message, int retryCount) {
152165
} catch (InterruptedException e1) {
153166
e1.printStackTrace();
154167
}
155-
return sendMessageToRouterService(message, retryCount++);
168+
return sendMessageToRouterService(message, ++retryCount);
156169
} else {
157170
//DeadObject, time to kill our connection
158171
DebugTool.logInfo(TAG, "Dead object while attempting to send packet");
@@ -431,7 +444,7 @@ public boolean start() {
431444
public void resetSession() {
432445
synchronized (INIT_LOCK) {
433446
unregisterWithRouterService();
434-
routerServiceMessenger = null;
447+
shutDownRouterServiceMessenger();
435448
unBindFromRouterService();
436449
isBound = false;
437450
}
@@ -445,7 +458,7 @@ public void stop() {
445458
synchronized (INIT_LOCK) {
446459
unregisterWithRouterService();
447460
unBindFromRouterService();
448-
routerServiceMessenger = null;
461+
shutDownRouterServiceMessenger();
449462
currentContext = null;
450463

451464
}
@@ -629,8 +642,7 @@ private void unregisterWithRouterService() {
629642
} else {
630643
DebugTool.logWarning(TAG, "Unable to unregister, not bound to router service");
631644
}
632-
633-
routerServiceMessenger = null;
645+
shutDownRouterServiceMessenger();
634646
}
635647

636648
protected ComponentName getRouterService() {
@@ -747,4 +759,15 @@ public void removeSession(long sessionId) {
747759
msg.setData(bundle);
748760
this.sendMessageToRouterService(msg);
749761
}
762+
763+
/**
764+
* Method to shut down RouterServiceMessenger
765+
*/
766+
private void shutDownRouterServiceMessenger() {
767+
routerServiceMessenger = null;
768+
if (routerServiceMessageEmitter != null) {
769+
routerServiceMessageEmitter.close();
770+
}
771+
routerServiceMessageEmitter = null;
772+
}
750773
}

base/src/main/java/com/smartdevicelink/managers/file/BaseFileManager.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,13 @@ public void onComplete(boolean success, int bytesAvailable, Collection<String> f
159159
}
160160

161161
private void listRemoteFilesWithCompletionListener(final FileManagerCompletionListener completionListener) {
162+
if (transactionQueue == null) {
163+
DebugTool.logError(TAG, "Queue is null, cannot retrieve uploaded files");
164+
if (completionListener != null) {
165+
completionListener.onComplete(false, bytesAvailable, null, "Queue is null, cannot upload files");
166+
}
167+
return;
168+
}
162169
ListFilesOperation operation = new ListFilesOperation(internalInterface, new FileManagerCompletionListener() {
163170
@Override
164171
public void onComplete(boolean success, int bytesAvailable, Collection<String> fileNames, String errorMessage) {
@@ -196,6 +203,13 @@ public void onComplete(boolean success, int bytesAvailable, Collection<String> f
196203
}
197204

198205
private void deleteRemoteFileWithNamePrivate(@NonNull final String fileName, final FileManagerCompletionListener listener) {
206+
if (transactionQueue == null) {
207+
DebugTool.logError(TAG, "Queue is null, cannot delete files");
208+
if (listener != null) {
209+
listener.onComplete(false, bytesAvailable, null, "Queue is null, cannot delete files");
210+
}
211+
return;
212+
}
199213
DeleteFileOperation operation = new DeleteFileOperation(internalInterface, fileName, mutableRemoteFileNames, new FileManagerCompletionListener() {
200214
@Override
201215
public void onComplete(boolean success, int bytesAvailable, Collection<String> fileNames, String errorMessage) {
@@ -406,6 +420,14 @@ private void uploadFilePrivate(@NonNull final SdlFile file, final FileManagerCom
406420
}
407421

408422
private void sdl_uploadFilePrivate(@NonNull final SdlFile file, final FileManagerCompletionListener listener) {
423+
424+
if (transactionQueue == null) {
425+
DebugTool.logError(TAG, "Queue is null, cannot upload files");
426+
if (listener != null) {
427+
listener.onComplete(false, bytesAvailable, null, "Queue is null, cannot upload files");
428+
}
429+
return;
430+
}
409431
final SdlFile fileClone = file.clone();
410432

411433
SdlFileWrapper fileWrapper = new SdlFileWrapper(fileClone, new FileManagerCompletionListener() {

0 commit comments

Comments
 (0)