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 for generateSessionId, err=%d", err); 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 ALOGW("bad response from service for submit, err=%d", err); 98 return MediaAnalyticsItem::SessionIDInvalid; 99 } 100 101 // get an answer out of 'reply' 102 int64_t sessionid = reply.readInt64(); 103 if (DEBUGGING_RETURNS) { 104 ALOGD("the caller gets sessionid=%" PRId64 "", sessionid); 105 } 106 return sessionid; 107 } 108 109 }; 110 111 IMPLEMENT_META_INTERFACE(MediaAnalyticsService, "android.media.IMediaAnalyticsService"); 112 113 // ---------------------------------------------------------------------- 114 115 status_t BnMediaAnalyticsService::onTransact( 116 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 117 { 118 119 120 // get calling pid/tid 121 IPCThreadState *ipc = IPCThreadState::self(); 122 int clientPid = ipc->getCallingPid(); 123 // permission checking 124 125 if(DEBUGGING_FLOW) { 126 ALOGD("running in service, code %d, pid %d; called from pid %d", 127 code, getpid(), clientPid); 128 } 129 130 switch (code) { 131 132 case GENERATE_UNIQUE_SESSIONID: { 133 CHECK_INTERFACE(IMediaAnalyticsService, data, reply); 134 135 MediaAnalyticsItem::SessionID_t sessionid = generateUniqueSessionID(); 136 reply->writeInt64(sessionid); 137 138 return NO_ERROR; 139 } break; 140 141 case SUBMIT_ITEM: { 142 CHECK_INTERFACE(IMediaAnalyticsService, data, reply); 143 144 bool forcenew; 145 MediaAnalyticsItem *item = new MediaAnalyticsItem; 146 147 data.readBool(&forcenew); 148 item->readFromParcel(data); 149 150 item->setPid(clientPid); 151 152 // submit() takes over ownership of 'item' 153 MediaAnalyticsItem::SessionID_t sessionid = submit(item, forcenew); 154 reply->writeInt64(sessionid); 155 156 return NO_ERROR; 157 } break; 158 159 default: 160 return BBinder::onTransact(code, data, reply, flags); 161 } 162 } 163 164 // ---------------------------------------------------------------------------- 165 166 } // namespace android 167