1 /*
2  * Copyright (C) 2017 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 // Proxy for media player implementations
18 
19 //#define LOG_NDEBUG 0
20 #define LOG_TAG "MediaAnalyticsService"
21 #include <utils/Log.h>
22 
23 #include <stdint.h>
24 #include <inttypes.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <sys/time.h>
28 #include <dirent.h>
29 #include <unistd.h>
30 
31 #include <string.h>
32 #include <pwd.h>
33 
34 #include <cutils/atomic.h>
35 #include <cutils/properties.h> // for property_get
36 
37 #include <utils/misc.h>
38 
39 #include <android/content/pm/IPackageManagerNative.h>
40 
41 #include <binder/IPCThreadState.h>
42 #include <binder/IServiceManager.h>
43 #include <binder/MemoryHeapBase.h>
44 #include <binder/MemoryBase.h>
45 #include <gui/Surface.h>
46 #include <utils/Errors.h>  // for status_t
47 #include <utils/List.h>
48 #include <utils/String8.h>
49 #include <utils/SystemClock.h>
50 #include <utils/Timers.h>
51 #include <utils/Vector.h>
52 
53 #include <media/AudioPolicyHelper.h>
54 #include <media/IMediaHTTPService.h>
55 #include <media/IRemoteDisplay.h>
56 #include <media/IRemoteDisplayClient.h>
57 #include <media/MediaPlayerInterface.h>
58 #include <media/mediarecorder.h>
59 #include <media/MediaMetadataRetrieverInterface.h>
60 #include <media/Metadata.h>
61 #include <media/AudioTrack.h>
62 #include <media/MemoryLeakTrackUtil.h>
63 #include <media/stagefright/MediaCodecList.h>
64 #include <media/stagefright/MediaErrors.h>
65 #include <media/stagefright/Utils.h>
66 #include <media/stagefright/foundation/ADebug.h>
67 #include <media/stagefright/foundation/ALooperRoster.h>
68 #include <mediautils/BatteryNotifier.h>
69 
70 //#include <memunreachable/memunreachable.h>
71 #include <system/audio.h>
72 
73 #include <private/android_filesystem_config.h>
74 
75 #include "MediaAnalyticsService.h"
76 
77 namespace android {
78 
79     using namespace android::base;
80     using namespace android::content::pm;
81 
82 // individual records kept in memory: age or count
83 // age: <= 36 hours (1.5 days)
84 // count: hard limit of # records
85 // (0 for either of these disables that threshold)
86 static const nsecs_t kMaxRecordAgeNs =  36 * 3600 * (1000*1000*1000ll);
87 static const int kMaxRecords    = 0;
88 
89 static const char *kServiceName = "media.metrics";
90 
instantiate()91 void MediaAnalyticsService::instantiate() {
92     defaultServiceManager()->addService(
93             String16(kServiceName), new MediaAnalyticsService());
94 }
95 
MediaAnalyticsService()96 MediaAnalyticsService::MediaAnalyticsService()
97         : mMaxRecords(kMaxRecords),
98           mMaxRecordAgeNs(kMaxRecordAgeNs),
99           mDumpProto(MediaAnalyticsItem::PROTO_V1),
100           mDumpProtoDefault(MediaAnalyticsItem::PROTO_V1) {
101 
102     ALOGD("MediaAnalyticsService created");
103 
104     mItemsSubmitted = 0;
105     mItemsFinalized = 0;
106     mItemsDiscarded = 0;
107     mItemsDiscardedExpire = 0;
108     mItemsDiscardedCount = 0;
109 
110     mLastSessionID = 0;
111     // recover any persistency we set up
112     // etc
113 }
114 
~MediaAnalyticsService()115 MediaAnalyticsService::~MediaAnalyticsService() {
116         ALOGD("MediaAnalyticsService destroyed");
117 
118     while (mItems.size() > 0) {
119         MediaAnalyticsItem * oitem = *(mItems.begin());
120         mItems.erase(mItems.begin());
121         delete oitem;
122         mItemsDiscarded++;
123         mItemsDiscardedCount++;
124     }
125 }
126 
127 
generateUniqueSessionID()128 MediaAnalyticsItem::SessionID_t MediaAnalyticsService::generateUniqueSessionID() {
129     // generate a new sessionid
130 
131     Mutex::Autolock _l(mLock_ids);
132     return (++mLastSessionID);
133 }
134 
135 // caller surrenders ownership of 'item'
submit(MediaAnalyticsItem * item,bool forcenew)136 MediaAnalyticsItem::SessionID_t MediaAnalyticsService::submit(MediaAnalyticsItem *item, bool forcenew)
137 {
138     UNUSED(forcenew);
139 
140     // fill in a sessionID if we do not yet have one
141     if (item->getSessionID() <= MediaAnalyticsItem::SessionIDNone) {
142         item->setSessionID(generateUniqueSessionID());
143     }
144 
145     // we control these, generally not trusting user input
146     nsecs_t now = systemTime(SYSTEM_TIME_REALTIME);
147     // round nsecs to seconds
148     now = ((now + 500000000) / 1000000000) * 1000000000;
149     item->setTimestamp(now);
150     int pid = IPCThreadState::self()->getCallingPid();
151     int uid = IPCThreadState::self()->getCallingUid();
152 
153     int uid_given = item->getUid();
154     int pid_given = item->getPid();
155 
156     // although we do make exceptions for some trusted client uids
157     bool isTrusted = false;
158 
159     ALOGV("caller has uid=%d, embedded uid=%d", uid, uid_given);
160 
161     switch (uid)  {
162         case AID_MEDIA:
163         case AID_MEDIA_CODEC:
164         case AID_MEDIA_EX:
165         case AID_MEDIA_DRM:
166             // trusted source, only override default values
167             isTrusted = true;
168             if (uid_given == (-1)) {
169                 item->setUid(uid);
170             }
171             if (pid_given == (-1)) {
172                 item->setPid(pid);
173             }
174             break;
175         default:
176             isTrusted = false;
177             item->setPid(pid);
178             item->setUid(uid);
179             break;
180     }
181 
182     // Overwrite package name and version if the caller was untrusted.
183     if (!isTrusted) {
184       setPkgInfo(item, item->getUid(), true, true);
185     } else if (item->getPkgName().empty()) {
186       // empty, so fill out both parts
187       setPkgInfo(item, item->getUid(), true, true);
188     } else {
189       // trusted, provided a package, do nothing
190     }
191 
192     ALOGV("given uid %d; sanitized uid: %d sanitized pkg: %s "
193           "sanitized pkg version: %"  PRId64,
194           uid_given, item->getUid(),
195           item->getPkgName().c_str(),
196           item->getPkgVersionCode());
197 
198     mItemsSubmitted++;
199 
200     // validate the record; we discard if we don't like it
201     if (contentValid(item, isTrusted) == false) {
202         delete item;
203         return MediaAnalyticsItem::SessionIDInvalid;
204     }
205 
206     // XXX: if we have a sessionid in the new record, look to make
207     // sure it doesn't appear in the finalized list.
208     // XXX: this is for security / DOS prevention.
209     // may also require that we persist the unique sessionIDs
210     // across boots [instead of within a single boot]
211 
212     if (item->count() == 0) {
213         // drop empty records
214         delete item;
215         item = NULL;
216         return MediaAnalyticsItem::SessionIDInvalid;
217     }
218 
219     // save the new record
220     MediaAnalyticsItem::SessionID_t id = item->getSessionID();
221     saveItem(item);
222     mItemsFinalized++;
223     return id;
224 }
225 
226 
dump(int fd,const Vector<String16> & args)227 status_t MediaAnalyticsService::dump(int fd, const Vector<String16>& args)
228 {
229     const size_t SIZE = 512;
230     char buffer[SIZE];
231     String8 result;
232 
233     if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
234         snprintf(buffer, SIZE, "Permission Denial: "
235                 "can't dump MediaAnalyticsService from pid=%d, uid=%d\n",
236                 IPCThreadState::self()->getCallingPid(),
237                 IPCThreadState::self()->getCallingUid());
238         result.append(buffer);
239         write(fd, result.string(), result.size());
240         return NO_ERROR;
241     }
242 
243     // crack any parameters
244     String16 protoOption("-proto");
245     int chosenProto = mDumpProtoDefault;
246     String16 clearOption("-clear");
247     bool clear = false;
248     String16 sinceOption("-since");
249     nsecs_t ts_since = 0;
250     String16 helpOption("-help");
251     String16 onlyOption("-only");
252     std::string only;
253     int n = args.size();
254 
255     for (int i = 0; i < n; i++) {
256         String8 myarg(args[i]);
257         if (args[i] == clearOption) {
258             clear = true;
259         } else if (args[i] == protoOption) {
260             i++;
261             if (i < n) {
262                 String8 value(args[i]);
263                 int proto = MediaAnalyticsItem::PROTO_V0;
264                 char *endp;
265                 const char *p = value.string();
266                 proto = strtol(p, &endp, 10);
267                 if (endp != p || *endp == '\0') {
268                     if (proto < MediaAnalyticsItem::PROTO_FIRST) {
269                         proto = MediaAnalyticsItem::PROTO_FIRST;
270                     } else if (proto > MediaAnalyticsItem::PROTO_LAST) {
271                         proto = MediaAnalyticsItem::PROTO_LAST;
272                     }
273                     chosenProto = proto;
274                 } else {
275                     result.append("unable to parse value for -proto\n\n");
276                 }
277             } else {
278                 result.append("missing value for -proto\n\n");
279             }
280         } else if (args[i] == sinceOption) {
281             i++;
282             if (i < n) {
283                 String8 value(args[i]);
284                 char *endp;
285                 const char *p = value.string();
286                 ts_since = strtoll(p, &endp, 10);
287                 if (endp == p || *endp != '\0') {
288                     ts_since = 0;
289                 }
290             } else {
291                 ts_since = 0;
292             }
293             // command line is milliseconds; internal units are nano-seconds
294             ts_since *= 1000*1000;
295         } else if (args[i] == onlyOption) {
296             i++;
297             if (i < n) {
298                 String8 value(args[i]);
299                 only = value.string();
300             }
301         } else if (args[i] == helpOption) {
302             result.append("Recognized parameters:\n");
303             result.append("-help        this help message\n");
304             result.append("-proto #     dump using protocol #");
305             result.append("-clear       clears out saved records\n");
306             result.append("-only X      process records for component X\n");
307             result.append("-since X     include records since X\n");
308             result.append("             (X is milliseconds since the UNIX epoch)\n");
309             write(fd, result.string(), result.size());
310             return NO_ERROR;
311         }
312     }
313 
314     Mutex::Autolock _l(mLock);
315     // mutex between insertion and dumping the contents
316 
317     mDumpProto = chosenProto;
318 
319     // we ALWAYS dump this piece
320     snprintf(buffer, SIZE, "Dump of the %s process:\n", kServiceName);
321     result.append(buffer);
322 
323     dumpHeaders(result, ts_since);
324 
325     dumpRecent(result, ts_since, only.c_str());
326 
327 
328     if (clear) {
329         // remove everything from the finalized queue
330         while (mItems.size() > 0) {
331             MediaAnalyticsItem * oitem = *(mItems.begin());
332             mItems.erase(mItems.begin());
333             delete oitem;
334             mItemsDiscarded++;
335         }
336 
337         // shall we clear the summary data too?
338 
339     }
340 
341     write(fd, result.string(), result.size());
342     return NO_ERROR;
343 }
344 
345 // dump headers
dumpHeaders(String8 & result,nsecs_t ts_since)346 void MediaAnalyticsService::dumpHeaders(String8 &result, nsecs_t ts_since)
347 {
348     const size_t SIZE = 512;
349     char buffer[SIZE];
350 
351     snprintf(buffer, SIZE, "Protocol Version: %d\n", mDumpProto);
352     result.append(buffer);
353 
354     int enabled = MediaAnalyticsItem::isEnabled();
355     if (enabled) {
356         snprintf(buffer, SIZE, "Metrics gathering: enabled\n");
357     } else {
358         snprintf(buffer, SIZE, "Metrics gathering: DISABLED via property\n");
359     }
360     result.append(buffer);
361 
362     snprintf(buffer, SIZE,
363         "Since Boot: Submissions: %8" PRId64
364             " Accepted: %8" PRId64 "\n",
365         mItemsSubmitted, mItemsFinalized);
366     result.append(buffer);
367     snprintf(buffer, SIZE,
368         "Records Discarded: %8" PRId64
369             " (by Count: %" PRId64 " by Expiration: %" PRId64 ")\n",
370          mItemsDiscarded, mItemsDiscardedCount, mItemsDiscardedExpire);
371     result.append(buffer);
372     if (ts_since != 0) {
373         snprintf(buffer, SIZE,
374             "Emitting Queue entries more recent than: %" PRId64 "\n",
375             (int64_t) ts_since);
376         result.append(buffer);
377     }
378 }
379 
380 // the recent, detailed queues
dumpRecent(String8 & result,nsecs_t ts_since,const char * only)381 void MediaAnalyticsService::dumpRecent(String8 &result, nsecs_t ts_since, const char * only)
382 {
383     const size_t SIZE = 512;
384     char buffer[SIZE];
385 
386     if (only != NULL && *only == '\0') {
387         only = NULL;
388     }
389 
390     // show the recently recorded records
391     snprintf(buffer, sizeof(buffer), "\nFinalized Metrics (oldest first):\n");
392     result.append(buffer);
393     result.append(this->dumpQueue(ts_since, only));
394 
395     // show who is connected and injecting records?
396     // talk about # records fed to the 'readers'
397     // talk about # records we discarded, perhaps "discarded w/o reading" too
398 }
399 
400 // caller has locked mLock...
dumpQueue()401 String8 MediaAnalyticsService::dumpQueue() {
402     return dumpQueue((nsecs_t) 0, NULL);
403 }
404 
dumpQueue(nsecs_t ts_since,const char * only)405 String8 MediaAnalyticsService::dumpQueue(nsecs_t ts_since, const char * only) {
406     String8 result;
407     int slot = 0;
408 
409     if (mItems.empty()) {
410             result.append("empty\n");
411     } else {
412         List<MediaAnalyticsItem *>::iterator it = mItems.begin();
413         for (; it != mItems.end(); it++) {
414             nsecs_t when = (*it)->getTimestamp();
415             if (when < ts_since) {
416                 continue;
417             }
418             if (only != NULL &&
419                 strcmp(only, (*it)->getKey().c_str()) != 0) {
420                 ALOGV("Omit '%s', it's not '%s'", (*it)->getKey().c_str(), only);
421                 continue;
422             }
423             std::string entry = (*it)->toString(mDumpProto);
424             result.appendFormat("%5d: %s\n", slot, entry.c_str());
425             slot++;
426         }
427     }
428 
429     return result;
430 }
431 
432 //
433 // Our Cheap in-core, non-persistent records management.
434 
435 // insert appropriately into queue
saveItem(MediaAnalyticsItem * item)436 void MediaAnalyticsService::saveItem(MediaAnalyticsItem * item)
437 {
438 
439     Mutex::Autolock _l(mLock);
440     // mutex between insertion and dumping the contents
441 
442     // we want to dump 'in FIFO order', so insert at the end
443     mItems.push_back(item);
444 
445     // keep removing old records the front until we're in-bounds (count)
446     if (mMaxRecords > 0) {
447         while (mItems.size() > (size_t) mMaxRecords) {
448             MediaAnalyticsItem * oitem = *(mItems.begin());
449             if (oitem == item) {
450                 break;
451             }
452             mItems.erase(mItems.begin());
453             delete oitem;
454             mItemsDiscarded++;
455             mItemsDiscardedCount++;
456         }
457     }
458 
459     // keep removing old records the front until we're in-bounds (count)
460     // NB: expired entries aren't removed until the next insertion, which could be a while
461     if (mMaxRecordAgeNs > 0) {
462         nsecs_t now = systemTime(SYSTEM_TIME_REALTIME);
463         while (mItems.size() > 0) {
464             MediaAnalyticsItem * oitem = *(mItems.begin());
465             nsecs_t when = oitem->getTimestamp();
466             if (oitem == item) {
467                 break;
468             }
469             // careful about timejumps too
470             if ((now > when) && (now-when) <= mMaxRecordAgeNs) {
471                 // this (and the rest) are recent enough to keep
472                 break;
473             }
474             mItems.erase(mItems.begin());
475             delete oitem;
476             mItemsDiscarded++;
477             mItemsDiscardedExpire++;
478         }
479     }
480 }
481 
482 static std::string allowedKeys[] =
483 {
484     "audiopolicy",
485     "audiorecord",
486     "audiotrack",
487     "codec",
488     "extractor",
489     "nuplayer",
490 };
491 
492 static const int nAllowedKeys = sizeof(allowedKeys) / sizeof(allowedKeys[0]);
493 
494 // are the contents good
contentValid(MediaAnalyticsItem * item,bool isTrusted)495 bool MediaAnalyticsService::contentValid(MediaAnalyticsItem *item, bool isTrusted) {
496 
497     // untrusted uids can only send us a limited set of keys
498     if (isTrusted == false) {
499         // restrict to a specific set of keys
500         std::string key = item->getKey();
501 
502         size_t i;
503         for(i = 0; i < nAllowedKeys; i++) {
504             if (key == allowedKeys[i]) {
505                 break;
506             }
507         }
508         if (i == nAllowedKeys) {
509             ALOGD("Ignoring (key): %s", item->toString().c_str());
510             return false;
511         }
512     }
513 
514     // internal consistency
515 
516     return true;
517 }
518 
519 // are we rate limited, normally false
rateLimited(MediaAnalyticsItem *)520 bool MediaAnalyticsService::rateLimited(MediaAnalyticsItem *) {
521 
522     return false;
523 }
524 
525 // how long we hold package info before we re-fetch it
526 #define PKG_EXPIRATION_NS (30*60*1000000000ll)   // 30 minutes, in nsecs
527 
528 // give me the package name, perhaps going to find it
529 // manages its own mutex operations internally
setPkgInfo(MediaAnalyticsItem * item,uid_t uid,bool setName,bool setVersion)530 void MediaAnalyticsService::setPkgInfo(MediaAnalyticsItem *item, uid_t uid, bool setName, bool setVersion)
531 {
532     ALOGV("asking for packagename to go with uid=%d", uid);
533 
534     if (!setName && !setVersion) {
535         // setting nothing? strange
536         return;
537     }
538 
539     nsecs_t now = systemTime(SYSTEM_TIME_REALTIME);
540     struct UidToPkgMap mapping;
541     mapping.uid = (uid_t)(-1);
542 
543     {
544         Mutex::Autolock _l(mLock_mappings);
545         int i = mPkgMappings.indexOfKey(uid);
546         if (i >= 0) {
547             mapping = mPkgMappings.valueAt(i);
548             ALOGV("Expiration? uid %d expiration %" PRId64 " now %" PRId64,
549                   uid, mapping.expiration, now);
550             if (mapping.expiration <= now) {
551                 // purge the stale entry and fall into re-fetching
552                 ALOGV("entry for uid %d expired, now= %" PRId64 "", uid, now);
553                 mPkgMappings.removeItemsAt(i);
554                 mapping.uid = (uid_t)(-1);
555             }
556         }
557     }
558 
559     // if we did not find it
560     if (mapping.uid == (uid_t)(-1)) {
561         std::string pkg;
562         std::string installer = "";
563         int64_t versionCode = 0;
564 
565         struct passwd *pw = getpwuid(uid);
566         if (pw) {
567             pkg = pw->pw_name;
568         }
569 
570         // find the proper value
571 
572         sp<IBinder> binder = NULL;
573         sp<IServiceManager> sm = defaultServiceManager();
574         if (sm == NULL) {
575             ALOGE("defaultServiceManager failed");
576         } else {
577             binder = sm->getService(String16("package_native"));
578             if (binder == NULL) {
579                 ALOGE("getService package_native failed");
580             }
581         }
582 
583         if (binder != NULL) {
584             sp<IPackageManagerNative> package_mgr = interface_cast<IPackageManagerNative>(binder);
585             binder::Status status;
586 
587             std::vector<int> uids;
588             std::vector<std::string> names;
589 
590             uids.push_back(uid);
591 
592             status = package_mgr->getNamesForUids(uids, &names);
593             if (!status.isOk()) {
594                 ALOGE("package_native::getNamesForUids failed: %s",
595                       status.exceptionMessage().c_str());
596             } else {
597                 if (!names[0].empty()) {
598                     pkg = names[0].c_str();
599                 }
600             }
601 
602             // strip any leading "shared:" strings that came back
603             if (pkg.compare(0, 7, "shared:") == 0) {
604                 pkg.erase(0, 7);
605             }
606 
607             // determine how pkg was installed and the versionCode
608             //
609             if (pkg.empty()) {
610                 // no name for us to manage
611             } else if (strchr(pkg.c_str(), '.') == NULL) {
612                 // not of form 'com.whatever...'; assume internal and ok
613             } else if (strncmp(pkg.c_str(), "android.", 8) == 0) {
614                 // android.* packages are assumed fine
615             } else {
616                 String16 pkgName16(pkg.c_str());
617                 status = package_mgr->getInstallerForPackage(pkgName16, &installer);
618                 if (!status.isOk()) {
619                     ALOGE("package_native::getInstallerForPackage failed: %s",
620                           status.exceptionMessage().c_str());
621                 }
622 
623                 // skip if we didn't get an installer
624                 if (status.isOk()) {
625                     status = package_mgr->getVersionCodeForPackage(pkgName16, &versionCode);
626                     if (!status.isOk()) {
627                         ALOGE("package_native::getVersionCodeForPackage failed: %s",
628                           status.exceptionMessage().c_str());
629                     }
630                 }
631 
632 
633                 ALOGV("package '%s' installed by '%s' versioncode %"  PRId64 " / %" PRIx64,
634                       pkg.c_str(), installer.c_str(), versionCode, versionCode);
635 
636                 if (strncmp(installer.c_str(), "com.android.", 12) == 0) {
637                         // from play store, we keep info
638                 } else if (strncmp(installer.c_str(), "com.google.", 11) == 0) {
639                         // some google source, we keep info
640                 } else if (strcmp(installer.c_str(), "preload") == 0) {
641                         // preloads, we keep the info
642                 } else if (installer.c_str()[0] == '\0') {
643                         // sideload (no installer); do not report
644                         pkg = "";
645                         versionCode = 0;
646                 } else {
647                         // unknown installer; do not report
648                         pkg = "";
649                         versionCode = 0;
650                 }
651             }
652         }
653 
654         // add it to the map, to save a subsequent lookup
655         if (!pkg.empty()) {
656             Mutex::Autolock _l(mLock_mappings);
657             ALOGV("Adding uid %d pkg '%s'", uid, pkg.c_str());
658             ssize_t i = mPkgMappings.indexOfKey(uid);
659             if (i < 0) {
660                 mapping.uid = uid;
661                 mapping.pkg = pkg;
662                 mapping.installer = installer.c_str();
663                 mapping.versionCode = versionCode;
664                 mapping.expiration = now + PKG_EXPIRATION_NS;
665                 ALOGV("expiration for uid %d set to %" PRId64 "", uid, mapping.expiration);
666 
667                 mPkgMappings.add(uid, mapping);
668             }
669         }
670     }
671 
672     if (mapping.uid != (uid_t)(-1)) {
673         if (setName) {
674             item->setPkgName(mapping.pkg);
675         }
676         if (setVersion) {
677             item->setPkgVersionCode(mapping.versionCode);
678         }
679     }
680 }
681 
682 } // namespace android
683