Skip to content

Commit 58f0d18

Browse files
authored
Merge pull request #542 from smartdevicelink/bugfix/softbutton-image-upload
Bugfix/softbutton image upload
2 parents d75186a + 87fc444 commit 58f0d18

3 files changed

Lines changed: 106 additions & 3 deletions

File tree

lib/js/src/manager/screen/_SoftButtonManagerBase.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@ class _SoftButtonManagerBase extends _SubManagerBase {
6060
this._currentMainField1 = null;
6161
this._currentHmiLevel = null;
6262
this._batchUpdates = false; // whether to wait on sending the updates
63+
let displayCapabilities = null;
64+
if (lifecycleManager.getSystemCapabilityManager() !== null) {
65+
displayCapabilities = lifecycleManager.getSystemCapabilityManager().getDisplayCapabilities();
66+
}
67+
this._isDynamicGraphicSupported = (displayCapabilities !== null && displayCapabilities.getGraphicSupported() !== null) ? displayCapabilities.getGraphicSupported() : true;
68+
6369
this._updateListener = () => {
6470
this._transitionSoftButton();
6571
};
@@ -137,7 +143,7 @@ class _SoftButtonManagerBase extends _SubManagerBase {
137143

138144
// Auto-send an updated Show if we have new capabilities
139145
if (this._softButtonObjects.length !== 0 && this._softButtonCapabilities !== null && this._softButtonCapabilities !== undefined && !this._softButtonCapabilitiesEquals(oldSoftButtonCapabilities, this._softButtonCapabilities)) {
140-
const operation = new _SoftButtonReplaceOperation(this._lifecycleManager, this._fileManager, this._softButtonCapabilities, this._softButtonObjects, this.getCurrentMainField1());
146+
const operation = new _SoftButtonReplaceOperation(this._lifecycleManager, this._fileManager, this._softButtonCapabilities, this._softButtonObjects, this.getCurrentMainField1(), this._isDynamicGraphicSupported);
141147
this._addTask(operation);
142148
}
143149
};
@@ -243,7 +249,7 @@ class _SoftButtonManagerBase extends _SubManagerBase {
243249
this._softButtonObjects = softButtonObjects;
244250

245251
// 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).
246-
const operation = new _SoftButtonReplaceOperation(this._lifecycleManager, this._fileManager, this._softButtonCapabilities, this._softButtonObjects, this.getCurrentMainField1());
252+
const operation = new _SoftButtonReplaceOperation(this._lifecycleManager, this._fileManager, this._softButtonCapabilities, this._softButtonObjects, this.getCurrentMainField1(), this._isDynamicGraphicSupported);
247253

248254
if (this._batchUpdates) {
249255
this._batchQueue.splice(0, this._batchQueue.length); // clear out the array

lib/js/src/manager/screen/_SoftButtonReplaceOperation.js

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import { _Task } from '../_Task';
3434
import { Show } from '../../rpc/messages/Show.js';
3535
import { SoftButton } from '../../rpc/structs/SoftButton.js';
3636
import { SoftButtonType } from '../../rpc/enums/SoftButtonType.js';
37+
import { ImageType } from '../../rpc/enums/ImageType.js';
3738

3839
class _SoftButtonReplaceOperation extends _Task {
3940
/**
@@ -45,14 +46,16 @@ class _SoftButtonReplaceOperation extends _Task {
4546
* @param {SoftButtonCapabilities} softButtonCapabilities - The soft button capabilities
4647
* @param {SoftButtonObject[]} softButtonObjects - A list of soft button objects
4748
* @param {String} currentMainField1 - The main field value text shown on the head unit
49+
* @param {Boolean} isDynamicGraphicSupported - Whether dynamic graphics are supported
4850
*/
49-
constructor (lifecycleManager, fileManager = null, softButtonCapabilities = null, softButtonObjects = null, currentMainField1 = null) {
51+
constructor (lifecycleManager, fileManager = null, softButtonCapabilities = null, softButtonObjects = null, currentMainField1 = null, isDynamicGraphicSupported) {
5052
super('SoftButtonTransitionOperation');
5153
this._lifecycleManager = lifecycleManager;
5254
this._fileManager = fileManager;
5355
this._softButtonCapabilities = softButtonCapabilities;
5456
this._softButtonObjects = softButtonObjects;
5557
this._currentMainField1 = currentMainField1;
58+
this._isDynamicGraphicSupported = isDynamicGraphicSupported;
5659
}
5760

5861
/**
@@ -83,6 +86,12 @@ class _SoftButtonReplaceOperation extends _Task {
8386
if (!success) {
8487
console.error('SoftButtonTransitionOperation - Head unit does not support images and some of the soft buttons do not have text, so none of the buttons will be sent.');
8588
}
89+
} else if (!this._supportsDynamicSoftButtonImages()) {
90+
console.info('SoftButtonTransitionOperation - 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.');
91+
const success = await this._sendCurrentStateStaticImageOnlySoftButtons();
92+
if (!success) {
93+
console.error('SoftButtonTransitionOperation - 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.');
94+
}
8695
} else if (this._currentStateHasImages() && !this._allCurrentStateImagesAreUploaded()) {
8796
// If there are images that aren't uploaded
8897
// Send text buttons if all the soft buttons have text
@@ -154,6 +163,59 @@ class _SoftButtonReplaceOperation extends _Task {
154163
return response.getSuccess();
155164
}
156165

166+
/**
167+
* Send soft buttons for the current state that only contain text and static images only, if possible.
168+
* @private
169+
* @returns {Promise} - Resolves to whether the operation is successful
170+
*/
171+
async _sendCurrentStateStaticImageOnlySoftButtons () {
172+
if (this.getState() === _Task.CANCELED) {
173+
return false;
174+
}
175+
176+
console.log('SoftButtonTransitionOperation - Preparing to send text and static image only soft buttons.');
177+
const textButtons = [];
178+
179+
for (const softButtonObject of this._softButtonObjects) {
180+
const softButton = softButtonObject.getCurrentStateSoftButton();
181+
if (softButton.getText() === null && softButton.getImage() !== null && softButton.getImage().getImageType() === ImageType.DYNAMIC) {
182+
console.warn('SoftButtonTransitionOperation - 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.');
183+
return false;
184+
}
185+
186+
if (softButton.getImage() !== null && softButton.getImage().getImageType() === ImageType.DYNAMIC) {
187+
// We should create a new softButtonObject rather than modifying the original one
188+
const textAndStaticImageOnlySoftButton = new SoftButton()
189+
.setType(SoftButtonType.SBT_TEXT)
190+
.setText(softButton.getText())
191+
.setImage(softButton.getImage())
192+
.setIsHighlighted(softButton.getIsHighlighted())
193+
.setSoftButtonID(softButton.getSoftButtonID())
194+
.setSystemAction(softButton.getSystemAction());
195+
textButtons.push(textAndStaticImageOnlySoftButton);
196+
} else {
197+
textButtons.push(softButton);
198+
}
199+
}
200+
201+
if (this._lifecycleManager === null) {
202+
console.error('SoftButtonTransitionOperation: LifecycleManager is null');
203+
return false;
204+
}
205+
206+
const show = new Show()
207+
.setMainField1(this._currentMainField1)
208+
.setSoftButtons(textButtons);
209+
210+
const response = await this._lifecycleManager.sendRpcResolve(show);
211+
if (response.getSuccess()) {
212+
console.log('SoftButtonTransitionOperation - Finished sending text and static image only soft buttons.');
213+
} else {
214+
console.warn('SoftButtonTransitionOperation - Failed to update soft buttons with text and static image only buttons.');
215+
}
216+
return response.getSuccess();
217+
}
218+
157219
/**
158220
* Uploads soft buttons representing the current states of the button objects
159221
* @private
@@ -211,6 +273,11 @@ class _SoftButtonReplaceOperation extends _Task {
211273
return false;
212274
}
213275

276+
if (!this._supportsDynamicSoftButtonImages()) {
277+
console.log('Head unit does not support dynamic images, skipping upload.');
278+
return false;
279+
}
280+
214281
console.log('SoftButtonTransitionOperation: Uploading soft button initial artworks');
215282
if (this._fileManager === null) {
216283
return false;
@@ -265,6 +332,15 @@ class _SoftButtonReplaceOperation extends _Task {
265332
return true;
266333
}
267334

335+
/**
336+
* Checks if dynamic soft button images are supported
337+
* @private
338+
* @returns {Boolean} - Whether dynamic soft button images are supported
339+
*/
340+
_supportsDynamicSoftButtonImages () {
341+
return this._softButtonCapabilities !== null && this._isDynamicGraphicSupported && this._softButtonCapabilities.getImageSupported();
342+
}
343+
268344
/**
269345
* Checks if soft button images are supported
270346
* @private

tests/managers/screen/SoftButtonManagerTests.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ module.exports = function (appClient) {
1111

1212
const screenManager = appClient._sdlManager.getScreenManager();
1313
const sbm = screenManager._softButtonManager;
14+
sbm._isDynamicGraphicSupported = true;
1415
let fileManagerUploadArtworksListenerCalledCounter = 0;
1516
let internalInterfaceSendRpcListenerCalledCounter = 0;
1617
const softButtonObject1Id = 1000;
@@ -233,6 +234,26 @@ module.exports = function (appClient) {
233234
Validator.assertEquals(softButtonState1, softButtonState2);
234235
});
235236

237+
it('testSoftButtonManagerGraphicNotSupported', function () {
238+
sbm._isDynamicGraphicSupported = false;
239+
fileManagerUploadArtworksListenerCalledCounter = 0;
240+
internalInterfaceSendRpcListenerCalledCounter = 0;
241+
const softButtonObjects = [softButtonObject1, softButtonObject2];
242+
sbm.setSoftButtonObjects(softButtonObjects);
243+
Validator.assertEquals(0, fileManagerUploadArtworksListenerCalledCounter);
244+
});
245+
246+
it('testSoftButtonManagerDynamicImageNotSupportedNoText', function () {
247+
sbm._isDynamicGraphicSupported = false;
248+
fileManagerUploadArtworksListenerCalledCounter = 0;
249+
internalInterfaceSendRpcListenerCalledCounter = 0;
250+
251+
const softButtonState = new SDL.manager.screen.utils.SoftButtonState('testState', null, new SDL.manager.file.filetypes.SdlArtwork('image', SDL.rpc.enums.FileType.GRAPHIC_PNG, '1', true));
252+
const softButtonObject = new SDL.manager.screen.utils.SoftButtonObject('obj1', softButtonState, softButtonState.getName());
253+
sbm.setSoftButtonObjects([softButtonObject]);
254+
Validator.assertEquals(0, fileManagerUploadArtworksListenerCalledCounter);
255+
});
256+
236257
/**
237258
* Pauses execution
238259
* @param {Number} timeout - How long in milliseconds to pause

0 commit comments

Comments
 (0)