1/* 2** 3** Copyright 2017, The Android Open Source Project 4** 5** Licensed under the Apache License, Version 2.0 (the "License"); 6** you may not use this file except in compliance with the License. 7** You may obtain a copy of the License at 8** 9** http://www.apache.org/licenses/LICENSE-2.0 10** 11** Unless required by applicable law or agreed to in writing, software 12** distributed under the License is distributed on an "AS IS" BASIS, 13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14** See the License for the specific language governing permissions and 15** limitations under the License. 16*/ 17 18#define LOG_TAG "IPlayer" 19//#define LOG_NDEBUG 0 20#include <utils/Log.h> 21 22#include <stdint.h> 23#include <sys/types.h> 24 25#include <binder/Parcel.h> 26 27#include <audiomanager/IPlayer.h> 28 29namespace android { 30 31enum { 32 START = IBinder::FIRST_CALL_TRANSACTION, 33 PAUSE = IBinder::FIRST_CALL_TRANSACTION + 1, 34 STOP = IBinder::FIRST_CALL_TRANSACTION + 2, 35 SET_VOLUME = IBinder::FIRST_CALL_TRANSACTION + 3, 36 SET_PAN = IBinder::FIRST_CALL_TRANSACTION + 4, 37 SET_START_DELAY_MS = IBinder::FIRST_CALL_TRANSACTION + 5, 38 APPLY_VOLUME_SHAPER = IBinder::FIRST_CALL_TRANSACTION + 6, 39}; 40 41class BpPlayer : public BpInterface<IPlayer> 42{ 43public: 44 explicit BpPlayer(const sp<IBinder>& impl) 45 : BpInterface<IPlayer>(impl) 46 { 47 } 48 49 virtual void start() 50 { 51 Parcel data, reply; 52 data.writeInterfaceToken(IPlayer::getInterfaceDescriptor()); 53 remote()->transact(START, data, &reply); 54 } 55 56 virtual void pause() 57 { 58 Parcel data, reply; 59 data.writeInterfaceToken(IPlayer::getInterfaceDescriptor()); 60 remote()->transact(PAUSE, data, &reply); 61 } 62 63 virtual void stop() 64 { 65 Parcel data, reply; 66 data.writeInterfaceToken(IPlayer::getInterfaceDescriptor()); 67 remote()->transact(STOP, data, &reply); 68 } 69 70 virtual void setVolume(float vol) 71 { 72 Parcel data, reply; 73 data.writeInterfaceToken(IPlayer::getInterfaceDescriptor()); 74 data.writeFloat(vol); 75 remote()->transact(SET_VOLUME, data, &reply); 76 } 77 78 virtual void setPan(float pan) 79 { 80 Parcel data, reply; 81 data.writeInterfaceToken(IPlayer::getInterfaceDescriptor()); 82 data.writeFloat(pan); 83 remote()->transact(SET_PAN, data, &reply); 84 } 85 86 virtual void setStartDelayMs(int32_t delayMs) { 87 Parcel data, reply; 88 data.writeInterfaceToken(IPlayer::getInterfaceDescriptor()); 89 data.writeInt32(delayMs); 90 remote()->transact(SET_START_DELAY_MS, data, &reply); 91 } 92 93 virtual void applyVolumeShaper( 94 const sp<VolumeShaper::Configuration>& configuration, 95 const sp<VolumeShaper::Operation>& operation) { 96 Parcel data, reply; 97 data.writeInterfaceToken(IPlayer::getInterfaceDescriptor()); 98 99 status_t status = configuration.get() == nullptr 100 ? data.writeInt32(0) 101 : data.writeInt32(1) 102 ?: configuration->writeToParcel(&data); 103 if (status != NO_ERROR) { 104 ALOGW("applyVolumeShaper failed configuration parceling: %d", status); 105 return; // ignore error 106 } 107 108 status = operation.get() == nullptr 109 ? status = data.writeInt32(0) 110 : data.writeInt32(1) 111 ?: operation->writeToParcel(&data); 112 if (status != NO_ERROR) { 113 ALOGW("applyVolumeShaper failed operation parceling: %d", status); 114 return; // ignore error 115 } 116 117 status = remote()->transact(APPLY_VOLUME_SHAPER, data, &reply); 118 119 ALOGW_IF(status != NO_ERROR, "applyVolumeShaper failed transact: %d", status); 120 return; // one way transaction, ignore error 121 } 122}; 123 124IMPLEMENT_META_INTERFACE(Player, "android.media.IPlayer"); 125 126// ---------------------------------------------------------------------- 127 128status_t BnPlayer::onTransact( 129 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 130{ 131 switch (code) { 132 case START: { 133 CHECK_INTERFACE(IPlayer, data, reply); 134 start(); 135 return NO_ERROR; 136 } break; 137 case PAUSE: { 138 CHECK_INTERFACE(IPlayer, data, reply); 139 pause(); 140 return NO_ERROR; 141 } 142 case STOP: { 143 CHECK_INTERFACE(IPlayer, data, reply); 144 stop(); 145 return NO_ERROR; 146 } break; 147 case SET_VOLUME: { 148 CHECK_INTERFACE(IPlayer, data, reply); 149 setVolume(data.readFloat()); 150 return NO_ERROR; 151 } break; 152 case SET_PAN: { 153 CHECK_INTERFACE(IPlayer, data, reply); 154 setPan(data.readFloat()); 155 return NO_ERROR; 156 } break; 157 case SET_START_DELAY_MS: { 158 CHECK_INTERFACE(IPlayer, data, reply); 159 setStartDelayMs(data.readInt32()); 160 return NO_ERROR; 161 } break; 162 case APPLY_VOLUME_SHAPER: { 163 CHECK_INTERFACE(IPlayer, data, reply); 164 sp<VolumeShaper::Configuration> configuration; 165 sp<VolumeShaper::Operation> operation; 166 167 int32_t present; 168 status_t status = data.readInt32(&present); 169 if (status == NO_ERROR && present != 0) { 170 configuration = new VolumeShaper::Configuration(); 171 status = configuration->readFromParcel(data); 172 } 173 status = status ?: data.readInt32(&present); 174 if (status == NO_ERROR && present != 0) { 175 operation = new VolumeShaper::Operation(); 176 status = operation->readFromParcel(data); 177 } 178 if (status == NO_ERROR) { 179 // one way transaction, no error returned 180 applyVolumeShaper(configuration, operation); 181 } 182 return NO_ERROR; 183 } break; 184 default: 185 return BBinder::onTransact(code, data, reply, flags); 186 } 187} 188 189} // namespace android 190