Skip to content

Commit a0e3890

Browse files
authored
1738 - Soft button manager image upload fix (#1811)
* check isGraphicSupported in SoftButtonManager * Remove log from testing * fix formatting * Unit test updates * Add unit test to test when graphic is not supported. Align with iOS on uploading graphic when no capability is retrieved * Fix logic to allow for static images to still be uploaded if dynamic are not supported * Fix logic in uploading softbuttons, align with iOS * Revert log back to a warning * Add unit test * Refactor isGraphicSupported to isDynamicGraphicSupported
1 parent 16b2ab6 commit a0e3890

File tree

3 files changed

+113
-4
lines changed

3 files changed

+113
-4
lines changed

android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/screen/SoftButtonManagerTests.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ public Void answer(InvocationOnMock invocation) {
140140
taskmaster.start();
141141
when(internalInterface.getTaskmaster()).thenReturn(taskmaster);
142142
softButtonManager = new SoftButtonManager(internalInterface, fileManager);
143+
softButtonManager.isDynamicGraphicSupported = true;
143144

144145

145146
// When internalInterface.sendRPC() is called inside SoftButtonManager:
@@ -516,4 +517,27 @@ public void testAssignSameNameStateListToSoftButtonObject() {
516517

517518
assertEquals(stateListUnique, softButtonObject.getStates());
518519
}
520+
521+
@Test
522+
public void testSoftButtonManagerGraphicNotSupported() {
523+
softButtonManager.isDynamicGraphicSupported = false;
524+
fileManagerUploadArtworksListenerCalledCounter = 0;
525+
internalInterfaceSendRPCListenerCalledCounter = 0;
526+
527+
softButtonManager.setSoftButtonObjects(Arrays.asList(softButtonObject1, softButtonObject2));
528+
assertEquals("SoftButtonManager is uploading artwork, when graphic is not supported", 0, fileManagerUploadArtworksListenerCalledCounter);
529+
}
530+
531+
@Test
532+
public void testSoftButtonManagerDynamicImageNotSupportedNoText() {
533+
softButtonManager.isDynamicGraphicSupported = false;
534+
fileManagerUploadArtworksListenerCalledCounter = 0;
535+
internalInterfaceSendRPCListenerCalledCounter = 0;
536+
537+
SoftButtonState softButtonState = new SoftButtonState("testState", null, new SdlArtwork("image", FileType.GRAPHIC_PNG, 1, true));
538+
SoftButtonObject softButtonObject = new SoftButtonObject("obj1", softButtonState, null);
539+
540+
softButtonManager.setSoftButtonObjects(Arrays.asList(softButtonObject));
541+
assertEquals("SoftButtonManager is uploading artwork, when graphic is not supported", 0, fileManagerUploadArtworksListenerCalledCounter);
542+
}
519543
}

base/src/main/java/com/smartdevicelink/managers/screen/BaseSoftButtonManager.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import com.smartdevicelink.managers.lifecycle.SystemCapabilityManager;
4444
import com.smartdevicelink.protocol.enums.FunctionID;
4545
import com.smartdevicelink.proxy.RPCNotification;
46+
import com.smartdevicelink.proxy.rpc.DisplayCapabilities;
4647
import com.smartdevicelink.proxy.rpc.DisplayCapability;
4748
import com.smartdevicelink.proxy.rpc.OnButtonEvent;
4849
import com.smartdevicelink.proxy.rpc.OnButtonPress;
@@ -58,7 +59,6 @@
5859

5960
import java.lang.ref.WeakReference;
6061
import java.util.ArrayList;
61-
import java.util.HashSet;
6262
import java.util.List;
6363
import java.util.concurrent.CopyOnWriteArrayList;
6464

@@ -71,6 +71,7 @@ abstract class BaseSoftButtonManager extends BaseSubManager {
7171
private static final String TAG = "BaseSoftButtonManager";
7272
private final WeakReference<FileManager> fileManager;
7373
SoftButtonCapabilities softButtonCapabilities;
74+
boolean isDynamicGraphicSupported;
7475
private CopyOnWriteArrayList<SoftButtonObject> softButtonObjects;
7576
private HMILevel currentHMILevel;
7677
private final OnSystemCapabilityListener onDisplayCapabilityListener;
@@ -99,6 +100,11 @@ abstract class BaseSoftButtonManager extends BaseSubManager {
99100
this.currentHMILevel = null;
100101
this.transactionQueue = newTransactionQueue();
101102
this.batchQueue = new ArrayList<>();
103+
DisplayCapabilities displayCapabilities = null;
104+
if (internalInterface.getSystemCapabilityManager() != null) {
105+
displayCapabilities = (DisplayCapabilities) this.internalInterface.getSystemCapabilityManager().getCapability(SystemCapabilityType.DISPLAY, null, false);
106+
}
107+
isDynamicGraphicSupported = (displayCapabilities != null && displayCapabilities.getGraphicSupported() != null) ? displayCapabilities.getGraphicSupported() : true;
102108

103109
this.updateListener = new SoftButtonObject.UpdateListener() {
104110
@Override
@@ -152,7 +158,7 @@ public void onCapabilityRetrieved(Object capability) {
152158

153159
// Auto-send an updated Show if we have new capabilities
154160
if (softButtonObjects != null && !softButtonObjects.isEmpty() && softButtonCapabilities != null && !softButtonCapabilitiesEquals(oldSoftButtonCapabilities, softButtonCapabilities)) {
155-
SoftButtonReplaceOperation operation = new SoftButtonReplaceOperation(internalInterface, fileManager, softButtonCapabilities, softButtonObjects, getCurrentMainField1());
161+
SoftButtonReplaceOperation operation = new SoftButtonReplaceOperation(internalInterface, fileManager, softButtonCapabilities, softButtonObjects, getCurrentMainField1(), isDynamicGraphicSupported);
156162
transactionQueue.add(operation, false);
157163
}
158164
}
@@ -311,7 +317,7 @@ protected void setSoftButtonObjects(@NonNull List<SoftButtonObject> list) {
311317
this.softButtonObjects = softButtonObjects;
312318

313319
// We only need to pass the first softButtonCapabilities in the array due to the fact that all soft button capabilities are the same (i.e. there is no way to assign a softButtonCapabilities to a specific soft button).
314-
SoftButtonReplaceOperation operation = new SoftButtonReplaceOperation(internalInterface, fileManager.get(), softButtonCapabilities, softButtonObjects, getCurrentMainField1());
320+
SoftButtonReplaceOperation operation = new SoftButtonReplaceOperation(internalInterface, fileManager.get(), softButtonCapabilities, softButtonObjects, getCurrentMainField1(), isDynamicGraphicSupported);
315321

316322
if (batchUpdates) {
317323
batchQueue.clear();

base/src/main/java/com/smartdevicelink/managers/screen/SoftButtonReplaceOperation.java

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import com.smartdevicelink.proxy.rpc.Show;
1111
import com.smartdevicelink.proxy.rpc.SoftButton;
1212
import com.smartdevicelink.proxy.rpc.SoftButtonCapabilities;
13+
import com.smartdevicelink.proxy.rpc.enums.ImageType;
1314
import com.smartdevicelink.proxy.rpc.enums.SoftButtonType;
1415
import com.smartdevicelink.proxy.rpc.listeners.OnRPCResponseListener;
1516
import com.smartdevicelink.util.DebugTool;
@@ -30,14 +31,16 @@ class SoftButtonReplaceOperation extends Task {
3031
private final SoftButtonCapabilities softButtonCapabilities;
3132
private final CopyOnWriteArrayList<SoftButtonObject> softButtonObjects;
3233
private String currentMainField1;
34+
private Boolean isDynamicGraphicSupported;
3335

34-
SoftButtonReplaceOperation(ISdl internalInterface, FileManager fileManager, SoftButtonCapabilities softButtonCapabilities, CopyOnWriteArrayList<SoftButtonObject> softButtonObjects, String currentMainField1) {
36+
SoftButtonReplaceOperation(ISdl internalInterface, FileManager fileManager, SoftButtonCapabilities softButtonCapabilities, CopyOnWriteArrayList<SoftButtonObject> softButtonObjects, String currentMainField1, Boolean isDynamicGraphicSupported) {
3537
super("SoftButtonReplaceOperation");
3638
this.internalInterface = new WeakReference<>(internalInterface);
3739
this.fileManager = new WeakReference<>(fileManager);
3840
this.softButtonCapabilities = softButtonCapabilities;
3941
this.softButtonObjects = softButtonObjects;
4042
this.currentMainField1 = currentMainField1;
43+
this.isDynamicGraphicSupported = isDynamicGraphicSupported;
4144
}
4245

4346
@Override
@@ -65,6 +68,18 @@ public void onComplete(boolean success) {
6568
onFinished();
6669
}
6770
});
71+
} else if (!supportsDynamicSoftButtonImages()) {
72+
DebugTool.logInfo(TAG, "Soft button images are not supported. Attempting to send text and static image only soft buttons. If any button does not contain text and/or a static image, no buttons will be sent.");
73+
sendCurrentStateStaticImageOnlySoftButtons(new CompletionListener() {
74+
@Override
75+
public void onComplete(boolean success) {
76+
if (!success) {
77+
DebugTool.logError(TAG, "Buttons will not be sent because the module does not support dynamic images and some of the buttons do not have text or static images");
78+
}
79+
onFinished();
80+
}
81+
});
82+
6883
} else if (currentStateHasImages() && !allCurrentStateImagesAreUploaded()) {
6984
// If there are images that aren't uploaded
7085
// Send text buttons if all the soft buttons have text
@@ -128,6 +143,13 @@ private void uploadInitialStateImages(final CompletionListener completionListene
128143
}
129144
return;
130145
}
146+
if (!supportsDynamicSoftButtonImages()) {
147+
DebugTool.logInfo(TAG, "Head unit does not support dynamic images, skipping upload");
148+
if (completionListener != null) {
149+
completionListener.onComplete(false);
150+
}
151+
return;
152+
}
131153

132154
DebugTool.logInfo(TAG, "Uploading soft button initial artworks");
133155
if (fileManager.get() != null) {
@@ -236,6 +258,59 @@ public void onResponse(int correlationId, RPCResponse response) {
236258
}
237259
}
238260

261+
// Send soft buttons for the current state that only contain text and static images only, if possible.
262+
private void sendCurrentStateStaticImageOnlySoftButtons(final CompletionListener completionListener) {
263+
if (getState() == Task.CANCELED) {
264+
onFinished();
265+
}
266+
267+
DebugTool.logInfo(TAG, "Preparing to send text and static image only soft buttons");
268+
List<SoftButton> textButtons = new ArrayList<>();
269+
for (SoftButtonObject softButtonObject : softButtonObjects) {
270+
SoftButton softButton = softButtonObject.getCurrentStateSoftButton();
271+
if (softButton.getText() == null && softButton.getImage() != null && softButton.getImage().getImageType() == ImageType.DYNAMIC) {
272+
DebugTool.logWarning(TAG, "Attempted to create text and static image only buttons, but some buttons don't support text and have dynamic images, so no soft buttons will be sent.");
273+
if (completionListener != null) {
274+
completionListener.onComplete(false);
275+
}
276+
return;
277+
}
278+
279+
280+
if (softButton.getImage() != null && softButton.getImage().getImageType() == ImageType.DYNAMIC) {
281+
// We should create a new softButtonObject rather than modifying the original one
282+
SoftButton textAndStaticImageOnlySoftButton = new SoftButton(SoftButtonType.SBT_TEXT, softButton.getSoftButtonID());
283+
textAndStaticImageOnlySoftButton.setText(softButton.getText());
284+
textAndStaticImageOnlySoftButton.setSystemAction(softButton.getSystemAction());
285+
textAndStaticImageOnlySoftButton.setIsHighlighted(softButton.getIsHighlighted());
286+
textAndStaticImageOnlySoftButton.setImage(softButton.getImage());
287+
textButtons.add(textAndStaticImageOnlySoftButton);
288+
} else {
289+
textButtons.add(softButton);
290+
}
291+
}
292+
293+
Show show = new Show();
294+
show.setOnRPCResponseListener(new OnRPCResponseListener() {
295+
@Override
296+
public void onResponse(int correlationId, RPCResponse response) {
297+
if (response.getSuccess()) {
298+
DebugTool.logInfo(TAG, "Finished sending text and static image only soft buttons");
299+
} else {
300+
DebugTool.logWarning(TAG, "Failed to update soft buttons with text and static image only buttons");
301+
}
302+
if (completionListener != null) {
303+
completionListener.onComplete(response.getSuccess());
304+
}
305+
}
306+
});
307+
show.setMainField1(currentMainField1);
308+
show.setSoftButtons(textButtons);
309+
if (internalInterface.get() != null) {
310+
internalInterface.get().sendRPC(show);
311+
}
312+
}
313+
239314

240315
// Returns text soft buttons representing the current states of the button objects, or returns if _any_ of the buttons' current states are image only buttons.
241316
private void sendCurrentStateTextOnlySoftButtons(final CompletionListener completionListener) {
@@ -303,6 +378,10 @@ private boolean allCurrentStateImagesAreUploaded() {
303378
return true;
304379
}
305380

381+
private boolean supportsDynamicSoftButtonImages() {
382+
return softButtonCapabilities != null && Boolean.TRUE.equals(isDynamicGraphicSupported) && Boolean.TRUE.equals(softButtonCapabilities.getImageSupported());
383+
}
384+
306385
private boolean supportsSoftButtonImages() {
307386
return softButtonCapabilities != null && Boolean.TRUE.equals(softButtonCapabilities.getImageSupported());
308387
}

0 commit comments

Comments
 (0)