1/* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15import rpc from '@ohos.rpc'; 16import ServiceExtensionAbility from '@ohos.app.ability.ServiceExtensionAbility'; 17import Logger from '../model/Logger'; 18import { 19 APPLICATION_BUNDLE_NAME, 20 APPLICATION_ABILITY_NAME, 21 APPLICATION_SERVICE_NAME, 22 MusicSharedEventCode, 23 MusicConnectEvent 24} from '../common/MusicSharedDefinition'; 25 26const TAG: string = 'ServiceAbility' 27const CONNECT_REMOTE_TIMEOUT = 10000 28 29let remoteProxy: rpc.RemoteProxy = null; 30 31class DistributedMusicServiceExtension extends rpc.RemoteObject { 32 private context 33 34 constructor(des, context) { 35 super(des) 36 this.context = context 37 } 38 39 startServiceAbility(want): void { 40 try { 41 let connectOptions = { 42 onConnect(elementName, remote): void { 43 Logger.info(TAG, `Start remote service has been succeeded, elementName= ${JSON.stringify(elementName)}, remote= ${JSON.stringify(remote)}`) 44 if (remote === null) { 45 Logger.info(TAG, 'Remote is null') 46 } 47 remoteProxy = remote as rpc.RemoteProxy; 48 clearTimeout(timeoutId) 49 let remoteServiceExtensionConnectEvent = AppStorage.Get<(event: string) => void>('remoteServiceExtensionConnectEvent'); 50 if (remoteServiceExtensionConnectEvent === undefined) { 51 Logger.info(TAG, `Connect remote service callback is ${JSON.stringify(remoteServiceExtensionConnectEvent)}`); 52 return; 53 } 54 remoteServiceExtensionConnectEvent(MusicConnectEvent.EVENT_CONNECT); 55 }, 56 onDisconnect(elementName): void { 57 Logger.info(TAG, `ServiceExtension has onDisconnected,elementName= ${JSON.stringify(elementName)}`) 58 clearTimeout(timeoutId) 59 remoteProxy = null; 60 let remoteServiceExtensionConnectEvent = AppStorage.Get<(event: string) => void>('remoteServiceExtensionConnectEvent'); 61 if (remoteServiceExtensionConnectEvent === undefined) { 62 Logger.info(TAG, `Disconnect remote service callback is ${JSON.stringify(remoteServiceExtensionConnectEvent)}`); 63 return; 64 } 65 remoteServiceExtensionConnectEvent(MusicConnectEvent.EVENT_DISCONNECT); 66 }, 67 onFailed(code): void { 68 Logger.info(TAG, `ServiceExtension has onFailed, code= ${JSON.stringify(code)}`) 69 clearTimeout(timeoutId) 70 remoteProxy = null; 71 let remoteServiceExtensionConnectEvent = AppStorage.Get<(event: string) => void>('remoteServiceExtensionConnectEvent'); 72 if (remoteServiceExtensionConnectEvent === undefined) { 73 Logger.info(TAG, `Failed remote service callback is ${JSON.stringify(remoteServiceExtensionConnectEvent)}`); 74 return; 75 } 76 remoteServiceExtensionConnectEvent(MusicConnectEvent.EVENT_FAILED); 77 } 78 } 79 80 this.context.connectServiceExtensionAbility(want, connectOptions) 81 let timeoutId = setTimeout(() => { 82 Logger.info(TAG, 'Connect remote service extension timeout') 83 let remoteServiceExtensionConnectEvent = AppStorage.Get<(event: string) => void>('remoteServiceExtensionConnectEvent'); 84 if (remoteServiceExtensionConnectEvent === undefined) { 85 Logger.info(TAG, `Timeout remote service callback is ${JSON.stringify(remoteServiceExtensionConnectEvent)}`); 86 return; 87 } 88 remoteServiceExtensionConnectEvent(MusicConnectEvent.EVENT_TIMEOUT); 89 }, CONNECT_REMOTE_TIMEOUT) 90 } catch (err) { 91 Logger.info(TAG, `ConnectServiceExtensionAbility has failed, want= ${JSON.stringify(want)}, err= ${JSON.stringify(err)}`) 92 } 93 } 94 95 stopServiceAbility(want): void { 96 this.context.stopServiceExtensionAbility(want).then(() => { 97 Logger.info(TAG, `Stop service has been succeeded, want= ${JSON.stringify(want)}`) 98 }).catch((err) => { 99 Logger.info(TAG, `Stop service has been failed, want= ${JSON.stringify(want)}, err= ${JSON.stringify(err)}`) 100 }) 101 } 102 103 onRemoteRequest(code: number, data: rpc.MessageParcel, reply: rpc.MessageParcel, options: rpc.MessageOption): boolean { 104 if (code === MusicSharedEventCode.START_DISTRIBUTED_MUSIC_SERVICE) { 105 let deviceId = data.readString() 106 let stringJson: string = data.readString() 107 let jsonData = JSON.parse(stringJson) 108 let params = { 109 uri: jsonData.uri, 110 seekTo: jsonData.seekTo, 111 isPlaying: jsonData.isPlaying, 112 flag: 'START_REMOTE_DISTRIBUTED_MUSIC_SERVICE' 113 } 114 let want = { 115 deviceId: deviceId, 116 bundleName: APPLICATION_BUNDLE_NAME, 117 abilityName: APPLICATION_SERVICE_NAME, 118 parameters: params 119 } 120 this.startServiceAbility(want) 121 } else if (code === MusicSharedEventCode.STOP_DISTRIBUTED_MUSIC_SERVICE) { 122 let deviceId = data.readString() 123 let want = { 124 deviceId: deviceId, 125 bundleName: APPLICATION_BUNDLE_NAME, 126 abilityName: APPLICATION_SERVICE_NAME 127 } 128 this.stopServiceAbility(want) 129 } else if (code === MusicSharedEventCode.PLAY_MUSIC_SERVICE) { 130 if (remoteProxy === null) { 131 Logger.info(TAG, 'Play local is null') 132 return false 133 } 134 let option = new rpc.MessageOption() 135 let data = new rpc.MessageParcel() 136 let reply = new rpc.MessageParcel() 137 remoteProxy.sendRequest(MusicSharedEventCode.PLAY_MUSIC_SERVICE_REMOTE, data, reply, option); 138 } else if (code === MusicSharedEventCode.PAUSE_MUSIC_SERVICE) { 139 if (remoteProxy === null) { 140 Logger.info(TAG, 'Pause local is null') 141 return false 142 } 143 let option = new rpc.MessageOption() 144 let data = new rpc.MessageParcel() 145 let reply = new rpc.MessageParcel() 146 remoteProxy.sendRequest(MusicSharedEventCode.PAUSE_MUSIC_SERVICE_REMOTE, data, reply, option); 147 } else if (code === MusicSharedEventCode.PLAY_MUSIC_SERVICE_REMOTE) { 148 let musicPlay = AppStorage.Get<() => void>('musicPlay'); 149 if (musicPlay === undefined) { 150 Logger.error(TAG, 'get play callback form app storage falied'); 151 return false; 152 } 153 musicPlay(); 154 } else if (code === MusicSharedEventCode.PAUSE_MUSIC_SERVICE_REMOTE) { 155 let musicPause = AppStorage.Get<() => void>('musicPause'); 156 if (musicPause === undefined) { 157 Logger.error(TAG, 'get pause callback form app storage falied'); 158 return false; 159 } 160 musicPause(); 161 } else if (code === MusicSharedEventCode.STOP_LOCAL_SERIVCE) { 162 this.context.terminateSelf().then(() => { 163 Logger.info(TAG, 'TerminateSelf service extension has been succeeded') 164 }).catch((err) => { 165 Logger.info(TAG, `TerminateSelf service extension has been failed err= ${JSON.stringify(err)}`) 166 }) 167 } else { 168 Logger.info(TAG, 'Invalid instruction') 169 return false 170 } 171 return true 172 } 173} 174 175export default class ServiceAbility extends ServiceExtensionAbility { 176 onCreate(want): void { 177 if (want.parameters.flag === 'START_REMOTE_DISTRIBUTED_MUSIC_SERVICE') { 178 let localwant = { 179 bundleName: APPLICATION_BUNDLE_NAME, 180 abilityName: APPLICATION_ABILITY_NAME, 181 parameters: want.parameters 182 } 183 this.context.startAbility(localwant).then(() => { 184 Logger.info(TAG, 'StartUIAbility has been succeeded') 185 }).catch((err) => { 186 Logger.info(TAG, `StartUIAbility has been failed, err= ${JSON.stringify(err)}`) 187 }) 188 } 189 } 190 191 onDestroy(): void { 192 Logger.info(TAG, 'ServiceAbility onDestroy') 193 } 194 195 onRequest(want, startId): void { 196 Logger.info(TAG, 'ServiceAbility onRequest') 197 } 198 199 onConnect(want): rpc.RemoteObject { 200 Logger.info(TAG, 'ServiceAbility onConnect') 201 return new DistributedMusicServiceExtension('ohos.samples.distributedMusicServiceExtension', this.context) 202 } 203 204 onDisconnect(want): void { 205 Logger.info(TAG, 'ServiceAbility onDisconnect') 206 } 207 208 onReconnect(want): void { 209 Logger.info(TAG, 'ServiceAbility onReconnect') 210 } 211 212 onConfigurationUpdate(newConfig): void { 213 Logger.info(TAG, 'ServiceAbility onConfigurationUpdate') 214 } 215 216 onDump(params: Array<string>): Array<string> { 217 Logger.info(TAG, 'ServiceAbility onDump') 218 return params 219 } 220}