Prevent display sleep while on a call
This commit is contained in:
		
					parent
					
						
							
								34fd945f83
							
						
					
				
			
			
				commit
				
					
						0e3d12c457
					
				
			
		
					 3 changed files with 152 additions and 0 deletions
				
			
		
							
								
								
									
										40
									
								
								app/PreventDisplaySleepService.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								app/PreventDisplaySleepService.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,40 @@ | ||||||
|  | // Copyright 2021 Signal Messenger, LLC
 | ||||||
|  | // SPDX-License-Identifier: AGPL-3.0-only
 | ||||||
|  | 
 | ||||||
|  | import type { PowerSaveBlocker } from 'electron'; | ||||||
|  | import * as log from '../ts/logging/log'; | ||||||
|  | 
 | ||||||
|  | export class PreventDisplaySleepService { | ||||||
|  |   private blockerId: undefined | number; | ||||||
|  | 
 | ||||||
|  |   constructor(private powerSaveBlocker: PowerSaveBlocker) {} | ||||||
|  | 
 | ||||||
|  |   setEnabled(isEnabled: boolean): void { | ||||||
|  |     log.info( | ||||||
|  |       `Prevent display sleep service: ${ | ||||||
|  |         isEnabled ? 'preventing' : 'allowing' | ||||||
|  |       } display sleep` | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|  |     if (isEnabled) { | ||||||
|  |       this.enable(); | ||||||
|  |     } else { | ||||||
|  |       this.disable(); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   private enable(): void { | ||||||
|  |     if (this.blockerId !== undefined) { | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |     this.blockerId = this.powerSaveBlocker.start('prevent-display-sleep'); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   private disable(): void { | ||||||
|  |     if (this.blockerId === undefined) { | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |     this.powerSaveBlocker.stop(this.blockerId); | ||||||
|  |     delete this.blockerId; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | @ -19,6 +19,7 @@ import { | ||||||
|   dialog, |   dialog, | ||||||
|   ipcMain as ipc, |   ipcMain as ipc, | ||||||
|   Menu, |   Menu, | ||||||
|  |   powerSaveBlocker, | ||||||
|   protocol as electronProtocol, |   protocol as electronProtocol, | ||||||
|   screen, |   screen, | ||||||
|   shell, |   shell, | ||||||
|  | @ -54,6 +55,7 @@ import * as attachments from './attachments'; | ||||||
| import * as attachmentChannel from './attachment_channel'; | import * as attachmentChannel from './attachment_channel'; | ||||||
| import * as bounce from '../ts/services/bounce'; | import * as bounce from '../ts/services/bounce'; | ||||||
| import * as updater from '../ts/updater/index'; | import * as updater from '../ts/updater/index'; | ||||||
|  | import { PreventDisplaySleepService } from './PreventDisplaySleepService'; | ||||||
| import { SystemTrayService } from './SystemTrayService'; | import { SystemTrayService } from './SystemTrayService'; | ||||||
| import { SystemTraySettingCache } from './SystemTraySettingCache'; | import { SystemTraySettingCache } from './SystemTraySettingCache'; | ||||||
| import { | import { | ||||||
|  | @ -120,6 +122,10 @@ const enableCI = config.get<boolean>('enableCI'); | ||||||
| const sql = new MainSQL(); | const sql = new MainSQL(); | ||||||
| const heicConverter = getHeicConverter(); | const heicConverter = getHeicConverter(); | ||||||
| 
 | 
 | ||||||
|  | const preventDisplaySleepService = new PreventDisplaySleepService( | ||||||
|  |   powerSaveBlocker | ||||||
|  | ); | ||||||
|  | 
 | ||||||
| let systemTrayService: SystemTrayService | undefined; | let systemTrayService: SystemTrayService | undefined; | ||||||
| const systemTraySettingCache = new SystemTraySettingCache( | const systemTraySettingCache = new SystemTraySettingCache( | ||||||
|   sql, |   sql, | ||||||
|  | @ -761,6 +767,8 @@ ipc.on('title-bar-double-click', () => { | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| ipc.on('set-is-call-active', (_event, isCallActive) => { | ipc.on('set-is-call-active', (_event, isCallActive) => { | ||||||
|  |   preventDisplaySleepService.setEnabled(isCallActive); | ||||||
|  | 
 | ||||||
|   if (!mainWindow) { |   if (!mainWindow) { | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|  |  | ||||||
							
								
								
									
										104
									
								
								ts/test-node/app/PreventDisplaySleepService_test.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								ts/test-node/app/PreventDisplaySleepService_test.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,104 @@ | ||||||
|  | // Copyright 2021 Signal Messenger, LLC
 | ||||||
|  | // SPDX-License-Identifier: AGPL-3.0-only
 | ||||||
|  | 
 | ||||||
|  | import { assert } from 'chai'; | ||||||
|  | import * as sinon from 'sinon'; | ||||||
|  | import type { PowerSaveBlocker } from 'electron'; | ||||||
|  | 
 | ||||||
|  | import { PreventDisplaySleepService } from '../../../app/PreventDisplaySleepService'; | ||||||
|  | 
 | ||||||
|  | describe('PreventDisplaySleepService', () => { | ||||||
|  |   class FakePowerSaveBlocker implements PowerSaveBlocker { | ||||||
|  |     private nextId = 0; | ||||||
|  |     private idsStarted = new Set<number>(); | ||||||
|  | 
 | ||||||
|  |     isStarted(id: number): boolean { | ||||||
|  |       return this.idsStarted.has(id); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     start(type: 'prevent-app-suspension' | 'prevent-display-sleep'): number { | ||||||
|  |       assert.strictEqual(type, 'prevent-display-sleep'); | ||||||
|  | 
 | ||||||
|  |       const result = this.nextId; | ||||||
|  |       this.nextId += 1; | ||||||
|  |       this.idsStarted.add(result); | ||||||
|  |       return result; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     stop(id: number): void { | ||||||
|  |       assert(this.idsStarted.has(id), `${id} was never started`); | ||||||
|  |       this.idsStarted.delete(id); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // This is only for testing.
 | ||||||
|  |     _idCount(): number { | ||||||
|  |       return this.idsStarted.size; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   let sandbox: sinon.SinonSandbox; | ||||||
|  |   let powerSaveBlocker: FakePowerSaveBlocker; | ||||||
|  |   let service: PreventDisplaySleepService; | ||||||
|  | 
 | ||||||
|  |   beforeEach(() => { | ||||||
|  |     sandbox = sinon.createSandbox(); | ||||||
|  |     powerSaveBlocker = new FakePowerSaveBlocker(); | ||||||
|  |     service = new PreventDisplaySleepService(powerSaveBlocker); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   afterEach(() => { | ||||||
|  |     sandbox.restore(); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('does nothing if disabling when it was already disabled', () => { | ||||||
|  |     const startStub = sandbox.stub(powerSaveBlocker, 'start'); | ||||||
|  |     const stopStub = sandbox.stub(powerSaveBlocker, 'stop'); | ||||||
|  | 
 | ||||||
|  |     service.setEnabled(false); | ||||||
|  | 
 | ||||||
|  |     assert.strictEqual(powerSaveBlocker._idCount(), 0); | ||||||
|  |     sinon.assert.notCalled(startStub); | ||||||
|  |     sinon.assert.notCalled(stopStub); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('can start power blocking', () => { | ||||||
|  |     service.setEnabled(true); | ||||||
|  | 
 | ||||||
|  |     assert.strictEqual(powerSaveBlocker._idCount(), 1); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('only starts power blocking once', () => { | ||||||
|  |     service.setEnabled(true); | ||||||
|  |     service.setEnabled(true); | ||||||
|  |     service.setEnabled(true); | ||||||
|  | 
 | ||||||
|  |     assert.strictEqual(powerSaveBlocker._idCount(), 1); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('can start and stop power blocking', () => { | ||||||
|  |     const startSpy = sandbox.spy(powerSaveBlocker, 'start'); | ||||||
|  |     const stopStub = sandbox.spy(powerSaveBlocker, 'stop'); | ||||||
|  | 
 | ||||||
|  |     service.setEnabled(true); | ||||||
|  |     service.setEnabled(false); | ||||||
|  | 
 | ||||||
|  |     assert.strictEqual(powerSaveBlocker._idCount(), 0); | ||||||
|  |     sinon.assert.calledOnce(startSpy); | ||||||
|  |     sinon.assert.calledOnce(stopStub); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('can toggle power blocking several times', () => { | ||||||
|  |     const startSpy = sandbox.spy(powerSaveBlocker, 'start'); | ||||||
|  |     const stopStub = sandbox.spy(powerSaveBlocker, 'stop'); | ||||||
|  | 
 | ||||||
|  |     service.setEnabled(true); | ||||||
|  |     service.setEnabled(false); | ||||||
|  |     service.setEnabled(true); | ||||||
|  |     service.setEnabled(false); | ||||||
|  |     service.setEnabled(true); | ||||||
|  | 
 | ||||||
|  |     assert.strictEqual(powerSaveBlocker._idCount(), 1); | ||||||
|  |     sinon.assert.calledThrice(startSpy); | ||||||
|  |     sinon.assert.calledTwice(stopStub); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Evan Hahn
				Evan Hahn