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('remoteServiceExtensionConnectEvent'); 50 if (remoteServiceExtensionConnectEvent === undefined) { 51 Logger.info(TAG, `Connect remote service callback is ${JSON.stringify(remoteServiceExtensionConnectEvent)}`); 52 return; 53 } 54 AppStorage.setOrCreate('remoteServiceExtensionConnectEvent', !remoteServiceExtensionConnectEvent); 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('remoteServiceExtensionConnectEvent'); 61 if (remoteServiceExtensionConnectEvent === undefined) { 62 Logger.info(TAG, `Disconnect remote service callback is ${JSON.stringify(remoteServiceExtensionConnectEvent)}`); 63 return; 64 } 65 AppStorage.setOrCreate('remoteServiceExtensionConnectEvent', !remoteServiceExtensionConnectEvent); 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('remoteServiceExtensionConnectEvent'); 72 if (remoteServiceExtensionConnectEvent === undefined) { 73 Logger.info(TAG, `Failed remote service callback is ${JSON.stringify(remoteServiceExtensionConnectEvent)}`); 74 return; 75 } 76 AppStorage.setOrCreate('remoteServiceExtensionConnectEvent', !remoteServiceExtensionConnectEvent); 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('remoteServiceExtensionConnectEvent'); 84 if (remoteServiceExtensionConnectEvent === undefined) { 85 Logger.info(TAG, `Timeout remote service callback is ${JSON.stringify(remoteServiceExtensionConnectEvent)}`); 86 return; 87 } 88 AppStorage.setOrCreate('remoteServiceExtensionConnectEvent', !remoteServiceExtensionConnectEvent); 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 try { 108 let jsonData = JSON.parse(stringJson); 109 Logger.info(TAG, `onRemoteRequest jsonData: ${JSON.stringify(jsonData)}`); 110 let params = { 111 uri: jsonData.uri, 112 seekTo: jsonData.seekTo, 113 isPlaying: jsonData.isPlaying, 114 flag: 'START_REMOTE_DISTRIBUTED_MUSIC_SERVICE' 115 } 116 let want = { 117 deviceId: deviceId, 118 bundleName: APPLICATION_BUNDLE_NAME, 119 abilityName: APPLICATION_SERVICE_NAME, 120 parameters: params 121 } 122 this.startServiceAbility(want); 123 } catch (error) { 124 Logger.error(TAG, `JSON text error`); 125 } 126 } else if (code === MusicSharedEventCode.STOP_DISTRIBUTED_MUSIC_SERVICE) { 127 let deviceId = data.readString() 128 let want = { 129 deviceId: deviceId, 130 bundleName: APPLICATION_BUNDLE_NAME, 131 abilityName: APPLICATION_SERVICE_NAME 132 } 133 this.stopServiceAbility(want) 134 } else if (code === MusicSharedEventCode.PLAY_MUSIC_SERVICE) { 135 if (remoteProxy === null) { 136 Logger.info(TAG, 'Play local is null') 137 return false 138 } 139 let option = new rpc.MessageOption() 140 let data = new rpc.MessageParcel() 141 let reply = new rpc.MessageParcel() 142 remoteProxy.sendRequest(MusicSharedEventCode.PLAY_MUSIC_SERVICE_REMOTE, data, reply, option); 143 } else if (code === MusicSharedEventCode.PAUSE_MUSIC_SERVICE) { 144 if (remoteProxy === null) { 145 Logger.info(TAG, 'Pause local is null') 146 return false 147 } 148 let option = new rpc.MessageOption() 149 let data = new rpc.MessageParcel() 150 let reply = new rpc.MessageParcel() 151 remoteProxy.sendRequest(MusicSharedEventCode.PAUSE_MUSIC_SERVICE_REMOTE, data, reply, option); 152 } else if (code === MusicSharedEventCode.PLAY_MUSIC_SERVICE_REMOTE) { 153 let musicPlay = AppStorage.get('musicPlay'); 154 if (musicPlay === undefined) { 155 Logger.error(TAG, 'get play callback form app storage falied'); 156 return false; 157 } 158 AppStorage.setOrCreate('musicPlay', !musicPlay); 159 } else if (code === MusicSharedEventCode.PAUSE_MUSIC_SERVICE_REMOTE) { 160 let musicPause = AppStorage.get('musicPause'); 161 if (musicPause === undefined) { 162 Logger.error(TAG, 'get pause callback form app storage falied'); 163 return false; 164 } 165 AppStorage.setOrCreate('musicPause', !musicPause); 166 } else if (code === MusicSharedEventCode.STOP_LOCAL_SERIVCE) { 167 this.context.terminateSelf().then(() => { 168 Logger.info(TAG, 'TerminateSelf service extension has been succeeded') 169 }).catch((err) => { 170 Logger.info(TAG, `TerminateSelf service extension has been failed err= ${JSON.stringify(err)}`) 171 }) 172 } else { 173 Logger.info(TAG, 'Invalid instruction') 174 return false 175 } 176 return true 177 } 178} 179 180export default class ServiceAbility extends ServiceExtensionAbility { 181 onCreate(want): void { 182 if (want.parameters.flag === 'START_REMOTE_DISTRIBUTED_MUSIC_SERVICE') { 183 let localwant = { 184 bundleName: APPLICATION_BUNDLE_NAME, 185 abilityName: APPLICATION_ABILITY_NAME, 186 parameters: want.parameters 187 } 188 this.context.startAbility(localwant).then(() => { 189 Logger.info(TAG, 'StartUIAbility has been succeeded') 190 }).catch((err) => { 191 Logger.info(TAG, `StartUIAbility has been failed, err= ${JSON.stringify(err)}`) 192 }) 193 } 194 } 195 196 onDestroy(): void { 197 Logger.info(TAG, 'ServiceAbility onDestroy') 198 } 199 200 onRequest(want, startId): void { 201 Logger.info(TAG, 'ServiceAbility onRequest') 202 } 203 204 onConnect(want): rpc.RemoteObject { 205 Logger.info(TAG, 'ServiceAbility onConnect') 206 if (this.context === null && this.context === undefined) { 207 Logger.error(TAG, 'ServiceAbility context does not exist or is empty') 208 return 209 } 210 return new DistributedMusicServiceExtension('ohos.samples.distributedMusicServiceExtension', this.context) 211 } 212 213 onDisconnect(want): void { 214 Logger.info(TAG, 'ServiceAbility onDisconnect') 215 } 216 217 onReconnect(want): void { 218 Logger.info(TAG, 'ServiceAbility onReconnect') 219 } 220 221 onConfigurationUpdate(newConfig): void { 222 Logger.info(TAG, 'ServiceAbility onConfigurationUpdate') 223 } 224 225 onDump(params: Array<string>): Array<string> { 226 Logger.info(TAG, 'ServiceAbility onDump') 227 return params 228 } 229}