Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions lib/js/src/manager/screen/_SoftButtonManagerBase.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ class _SoftButtonManagerBase extends _SubManagerBase {
this._currentMainField1 = null;
this._currentHmiLevel = null;
this._batchUpdates = false; // whether to wait on sending the updates
let displayCapabilities = null;
if (lifecycleManager.getSystemCapabilityManager() !== null) {
displayCapabilities = lifecycleManager.getSystemCapabilityManager().getDisplayCapabilities();
}
this._isDynamicGraphicSupported = (displayCapabilities !== null && displayCapabilities.getGraphicSupported() !== null) ? displayCapabilities.getGraphicSupported() : true;

this._updateListener = () => {
this._transitionSoftButton();
};
Expand Down Expand Up @@ -137,7 +143,7 @@ class _SoftButtonManagerBase extends _SubManagerBase {

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

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

if (this._batchUpdates) {
this._batchQueue.splice(0, this._batchQueue.length); // clear out the array
Expand Down
78 changes: 77 additions & 1 deletion lib/js/src/manager/screen/_SoftButtonReplaceOperation.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { _Task } from '../_Task';
import { Show } from '../../rpc/messages/Show.js';
import { SoftButton } from '../../rpc/structs/SoftButton.js';
import { SoftButtonType } from '../../rpc/enums/SoftButtonType.js';
import { ImageType } from '../../rpc/enums/ImageType.js';

class _SoftButtonReplaceOperation extends _Task {
/**
Expand All @@ -45,14 +46,16 @@ class _SoftButtonReplaceOperation extends _Task {
* @param {SoftButtonCapabilities} softButtonCapabilities - The soft button capabilities
* @param {SoftButtonObject[]} softButtonObjects - A list of soft button objects
* @param {String} currentMainField1 - The main field value text shown on the head unit
* @param {Boolean} isDynamicGraphicSupported - Whether dynamic graphics are supported
*/
constructor (lifecycleManager, fileManager = null, softButtonCapabilities = null, softButtonObjects = null, currentMainField1 = null) {
constructor (lifecycleManager, fileManager = null, softButtonCapabilities = null, softButtonObjects = null, currentMainField1 = null, isDynamicGraphicSupported) {
super('SoftButtonTransitionOperation');
this._lifecycleManager = lifecycleManager;
this._fileManager = fileManager;
this._softButtonCapabilities = softButtonCapabilities;
this._softButtonObjects = softButtonObjects;
this._currentMainField1 = currentMainField1;
this._isDynamicGraphicSupported = isDynamicGraphicSupported;
}

/**
Expand Down Expand Up @@ -83,6 +86,12 @@ class _SoftButtonReplaceOperation extends _Task {
if (!success) {
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.');
}
} else if (!this._supportsDynamicSoftButtonImages()) {
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.');
const success = await this._sendCurrentStateStaticImageOnlySoftButtons();
if (!success) {
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.');
}
} else if (this._currentStateHasImages() && !this._allCurrentStateImagesAreUploaded()) {
// If there are images that aren't uploaded
// Send text buttons if all the soft buttons have text
Expand Down Expand Up @@ -154,6 +163,59 @@ class _SoftButtonReplaceOperation extends _Task {
return response.getSuccess();
}

/**
* Send soft buttons for the current state that only contain text and static images only, if possible.
* @private
* @returns {Promise} - Resolves to whether the operation is successful
*/
async _sendCurrentStateStaticImageOnlySoftButtons () {
if (this.getState() === _Task.CANCELED) {
return false;
}

console.log('SoftButtonTransitionOperation - Preparing to send text and static image only soft buttons.');
const textButtons = [];

for (const softButtonObject of this._softButtonObjects) {
const softButton = softButtonObject.getCurrentStateSoftButton();
if (softButton.getText() === null && softButton.getImage() !== null && softButton.getImage().getImageType() === ImageType.DYNAMIC) {
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.');
return false;
}

if (softButton.getImage() !== null && softButton.getImage().getImageType() === ImageType.DYNAMIC) {
// We should create a new softButtonObject rather than modifying the original one
const textAndStaticImageOnlySoftButton = new SoftButton()
.setType(SoftButtonType.SBT_TEXT)
.setText(softButton.getText())
.setImage(softButton.getImage())
.setIsHighlighted(softButton.getIsHighlighted())
.setSoftButtonID(softButton.getSoftButtonID())
.setSystemAction(softButton.getSystemAction());
textButtons.push(textAndStaticImageOnlySoftButton);
} else {
textButtons.push(softButton);
}
}

if (this._lifecycleManager === null) {
console.error('SoftButtonTransitionOperation: LifecycleManager is null');
return false;
}

const show = new Show()
.setMainField1(this._currentMainField1)
.setSoftButtons(textButtons);

const response = await this._lifecycleManager.sendRpcResolve(show);
if (response.getSuccess()) {
console.log('SoftButtonTransitionOperation - Finished sending text and static image only soft buttons.');
} else {
console.warn('SoftButtonTransitionOperation - Failed to update soft buttons with text and static image only buttons.');
}
return response.getSuccess();
}

/**
* Uploads soft buttons representing the current states of the button objects
* @private
Expand Down Expand Up @@ -211,6 +273,11 @@ class _SoftButtonReplaceOperation extends _Task {
return false;
}

if (!this._supportsDynamicSoftButtonImages()) {
console.log('Head unit does not support dynamic images, skipping upload.');
return false;
}

console.log('SoftButtonTransitionOperation: Uploading soft button initial artworks');
if (this._fileManager === null) {
return false;
Expand Down Expand Up @@ -265,6 +332,15 @@ class _SoftButtonReplaceOperation extends _Task {
return true;
}

/**
* Checks if dynamic soft button images are supported
* @private
* @returns {Boolean} - Whether dynamic soft button images are supported
*/
_supportsDynamicSoftButtonImages () {
return this._softButtonCapabilities !== null && this._isDynamicGraphicSupported && this._softButtonCapabilities.getImageSupported();
}

/**
* Checks if soft button images are supported
* @private
Expand Down
21 changes: 21 additions & 0 deletions tests/managers/screen/SoftButtonManagerTests.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module.exports = function (appClient) {

const screenManager = appClient._sdlManager.getScreenManager();
const sbm = screenManager._softButtonManager;
sbm._isDynamicGraphicSupported = true;
let fileManagerUploadArtworksListenerCalledCounter = 0;
let internalInterfaceSendRpcListenerCalledCounter = 0;
const softButtonObject1Id = 1000;
Expand Down Expand Up @@ -233,6 +234,26 @@ module.exports = function (appClient) {
Validator.assertEquals(softButtonState1, softButtonState2);
});

it('testSoftButtonManagerGraphicNotSupported', function () {
sbm._isDynamicGraphicSupported = false;
fileManagerUploadArtworksListenerCalledCounter = 0;
internalInterfaceSendRpcListenerCalledCounter = 0;
const softButtonObjects = [softButtonObject1, softButtonObject2];
sbm.setSoftButtonObjects(softButtonObjects);
Validator.assertEquals(0, fileManagerUploadArtworksListenerCalledCounter);
});

it('testSoftButtonManagerDynamicImageNotSupportedNoText', function () {
sbm._isDynamicGraphicSupported = false;
fileManagerUploadArtworksListenerCalledCounter = 0;
internalInterfaceSendRpcListenerCalledCounter = 0;

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));
const softButtonObject = new SDL.manager.screen.utils.SoftButtonObject('obj1', softButtonState, softButtonState.getName());
sbm.setSoftButtonObjects([softButtonObject]);
Validator.assertEquals(0, fileManagerUploadArtworksListenerCalledCounter);
});

/**
* Pauses execution
* @param {Number} timeout - How long in milliseconds to pause
Expand Down