1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "MediaAnalytics" 18 19 #include <stdint.h> 20 #include <inttypes.h> 21 #include <sys/types.h> 22 23 #include <binder/Parcel.h> 24 #include <binder/IMemory.h> 25 #include <binder/IPCThreadState.h> 26 27 #include <utils/Errors.h> // for status_t 28 #include <utils/List.h> 29 #include <utils/Log.h> 30 #include <utils/String8.h> 31 32 #include <media/MediaAnalyticsItem.h> 33 #include <media/IMediaAnalyticsService.h> 34 35 #define DEBUGGING 0 36 #define DEBUGGING_FLOW 0 37 #define DEBUGGING_RETURNS 0 38 39 namespace android { 40 41 enum { 42 GENERATE_UNIQUE_SESSIONID = IBinder::FIRST_CALL_TRANSACTION, 43 SUBMIT_ITEM, 44 }; 45 46 class BpMediaAnalyticsService: public BpInterface<IMediaAnalyticsService> 47 { 48 public: 49 explicit BpMediaAnalyticsService(const sp<IBinder>& impl) 50 : BpInterface<IMediaAnalyticsService>(impl) 51 { 52 } 53 54 virtual MediaAnalyticsItem::SessionID_t generateUniqueSessionID() { 55 Parcel data, reply; 56 status_t err; 57 MediaAnalyticsItem::SessionID_t sessionid = 58 MediaAnalyticsItem::SessionIDInvalid; 59 60 data.writeInterfaceToken(IMediaAnalyticsService::getInterfaceDescriptor()); 61 err = remote()->transact(GENERATE_UNIQUE_SESSIONID, data, &reply); 62 if (err != NO_ERROR) { 63 ALOGW("bad response from service"); 64 return MediaAnalyticsItem::SessionIDInvalid; 65 } 66 sessionid = reply.readInt64(); 67 if (DEBUGGING_RETURNS) { 68 ALOGD("the caller gets a sessionid of %" PRId64 " back", sessionid); 69 } 70 return sessionid; 71 } 72 73 virtual MediaAnalyticsItem::SessionID_t submit(MediaAnalyticsItem *item, bool forcenew) 74 { 75 // have this record submit itself 76 // this will be a binder call with appropriate timing 77 // return value is the uuid that the system generated for it. 78 // the return value 0 and -1 are reserved. 79 // -1 to indicate that there was a problem recording... 80 81 Parcel data, reply; 82 status_t err; 83 84 if (item == NULL) { 85 return MediaAnalyticsItem::SessionIDInvalid; 86 } 87 88 data.writeInterfaceToken(IMediaAnalyticsService::getInterfaceDescriptor()); 89 if(DEBUGGING_FLOW) { 90 ALOGD("client offers record: %s", item->toString().c_str()); 91 } 92 data.writeBool(forcenew); 93 item->writeToParcel(&data); 94 95 err = remote()->transact(SUBMIT_ITEM, data, &reply); 96 if (err != NO_ERROR) { 97 return MediaAnalyticsItem::SessionIDInvalid; 98 } 99 100 // get an answer out of 'reply' 101 int64_t sessionid = reply.readInt64(); 102 if (DEBUGGING_RETURNS) { 103 ALOGD("the caller gets sessionid=%" PRId64 "", sessionid); 104 } 105 return sessionid; 106 } 107 108 }; 109 110 IMPLEMENT_META_INTERFACE(MediaAnalyticsService, "android.media.IMediaAnalyticsService"); 111 112 // ---------------------------------------------------------------------- 113 114 status_t BnMediaAnalyticsService::onTransact( 115 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 116 { 117 118 119 // get calling pid/tid 120 IPCThreadState *ipc = IPCThreadState::self(); 121 int clientPid = ipc->getCallingPid(); 122 // permission checking 123 124 if(DEBUGGING_FLOW) { 125 ALOGD("running in service, code %d, pid %d; called from pid %d", 126 code, getpid(), clientPid); 127 } 128 129 switch (code) { 130 131 case GENERATE_UNIQUE_SESSIONID: { 132 CHECK_INTERFACE(IMediaAnalyticsService, data, reply); 133 134 MediaAnalyticsItem::SessionID_t sessionid = generateUniqueSessionID(); 135 reply->writeInt64(sessionid); 136 137 return NO_ERROR; 138 } break; 139 140 case SUBMIT_ITEM: { 141 CHECK_INTERFACE(IMediaAnalyticsService, data, reply); 142 143 bool forcenew; 144 MediaAnalyticsItem *item = new MediaAnalyticsItem; 145 146 data.readBool(&forcenew); 147 item->readFromParcel(data); 148 149 item->setPid(clientPid); 150 151 // submit() takes over ownership of 'item' 152 MediaAnalyticsItem::SessionID_t sessionid = submit(item, forcenew); 153 reply->writeInt64(sessionid); 154 155 return NO_ERROR; 156 } break; 157 158 default: 159 return BBinder::onTransact(code, data, reply, flags); 160 } 161 } 162 163 // ---------------------------------------------------------------------------- 164 165 } // namespace android 166