Loading media/libmediametrics/MediaAnalyticsItem.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -59,6 +59,7 @@ const int MediaAnalyticsItem::EnabledProperty_default = 1; MediaAnalyticsItem::MediaAnalyticsItem() : mPid(-1), mUid(-1), mPkgVersionCode(0), mSessionID(MediaAnalyticsItem::SessionIDNone), mTimestamp(0), mFinalized(0), Loading @@ -70,6 +71,7 @@ MediaAnalyticsItem::MediaAnalyticsItem() MediaAnalyticsItem::MediaAnalyticsItem(MediaAnalyticsItem::Key key) : mPid(-1), mUid(-1), mPkgVersionCode(0), mSessionID(MediaAnalyticsItem::SessionIDNone), mTimestamp(0), mFinalized(0), Loading services/mediaanalytics/MediaAnalyticsService.cpp +134 −63 Original line number Diff line number Diff line Loading @@ -257,14 +257,15 @@ MediaAnalyticsItem::SessionID_t MediaAnalyticsService::submit(MediaAnalyticsItem break; } // Overwrite package name and version if the caller was untrusted. if (!isTrusted) { item->setPkgName(getPkgName(item->getUid(), true)); item->setPkgVersionCode(0); setPkgInfo(item, item->getUid(), true, true); } else if (item->getPkgName().empty()) { // Only overwrite the package name if it was empty. Trust whatever // version code was provided by the trusted caller. item->setPkgName(getPkgName(uid, true)); // empty, so fill out both parts setPkgInfo(item, item->getUid(), true, true); } else { // trusted, provided a package, do nothing } ALOGV("given uid %d; sanitized uid: %d sanitized pkg: %s " Loading Loading @@ -800,31 +801,46 @@ void MediaAnalyticsService::summarize(MediaAnalyticsItem *item) { } // mapping uids to package names // how long we hold package info before we re-fetch it #define PKG_EXPIRATION_NS (30*60*1000000000ll) // 30 minutes, in nsecs // give me the package name, perhaps going to find it AString MediaAnalyticsService::getPkgName(uid_t uid, bool addIfMissing) { ssize_t i = mPkgMappings.indexOfKey(uid); if (i >= 0) { AString pkg = mPkgMappings.valueAt(i); ALOGV("returning pkg '%s' for uid %d", pkg.c_str(), uid); return pkg; void MediaAnalyticsService::setPkgInfo(MediaAnalyticsItem *item, uid_t uid, bool setName, bool setVersion) { ALOGV("asking for packagename to go with uid=%d", uid); if (!setName && !setVersion) { // setting nothing? strange return; } AString pkg; nsecs_t now = systemTime(SYSTEM_TIME_REALTIME); struct UidToPkgMap mapping; mapping.uid = (-1); if (addIfMissing == false) { return pkg; ssize_t i = mPkgMappings.indexOfKey(uid); if (i >= 0) { mapping = mPkgMappings.valueAt(i); ALOGV("Expiration? uid %d expiration %" PRId64 " now %" PRId64, uid, mapping.expiration, now); if (mapping.expiration < now) { // purge our current entry and re-query ALOGV("entry for uid %d expired, now= %" PRId64 "", uid, now); mPkgMappings.removeItemsAt(i, 1); // could cheat and use a goto back to the top of the routine. // a good compiler should recognize the local tail recursion... return setPkgInfo(item, uid, setName, setVersion); } } else { AString pkg; std::string installer = ""; int32_t versionCode = 0; struct passwd *pw = getpwuid(uid); if (pw) { pkg = pw->pw_name; } else { pkg = "-"; } // find the proper value // find the proper value -- should we cache this binder?? sp<IBinder> binder = NULL; sp<IServiceManager> sm = defaultServiceManager(); Loading @@ -839,13 +855,14 @@ AString MediaAnalyticsService::getPkgName(uid_t uid, bool addIfMissing) { if (binder != NULL) { sp<IPackageManagerNative> package_mgr = interface_cast<IPackageManagerNative>(binder); binder::Status status; std::vector<int> uids; std::vector<std::string> names; uids.push_back(uid); binder::Status status = package_mgr->getNamesForUids(uids, &names); status = package_mgr->getNamesForUids(uids, &names); if (!status.isOk()) { ALOGE("package_native::getNamesForUids failed: %s", status.exceptionMessage().c_str()); Loading @@ -854,31 +871,85 @@ AString MediaAnalyticsService::getPkgName(uid_t uid, bool addIfMissing) { pkg = names[0].c_str(); } } // strip any leading "shared:" strings that came back if (pkg.startsWith("shared:")) { pkg.erase(0, 7); } // determine how pkg was installed and the versionCode // if (pkg.empty()) { // no name for us to manage } else if (strchr(pkg.c_str(), '.') == NULL) { // not of form 'com.whatever...'; assume internal and ok } else if (strncmp(pkg.c_str(), "android.", 8) == 0) { // android.* packages are assumed fine } else { String16 pkgName16(pkg.c_str()); status = package_mgr->getInstallerForPackage(pkgName16, &installer); if (!status.isOk()) { ALOGE("package_native::getInstallerForPackage failed: %s", status.exceptionMessage().c_str()); } // skip if we didn't get an installer if (status.isOk()) { status = package_mgr->getVersionCodeForPackage(pkgName16, &versionCode); if (!status.isOk()) { ALOGE("package_native::getVersionCodeForPackage failed: %s", status.exceptionMessage().c_str()); } } // XXX determine whether package was side-loaded or from playstore. // for privacy, we only list apps loaded from playstore. // Sanitize the package name for ":" // as an example, we get "shared:android.uid.systemui" // replace : with something benign (I'm going to use !) if (!pkg.empty()) { int n = pkg.size(); char *p = (char *) pkg.c_str(); for (int i = 0 ; i < n; i++) { if (p[i] == ':') { p[i] = '!'; ALOGV("package '%s' installed by '%s' versioncode %d / %08x", pkg.c_str(), installer.c_str(), versionCode, versionCode); if (strncmp(installer.c_str(), "com.android.", 12) == 0) { // from play store, we keep info } else if (strncmp(installer.c_str(), "com.google.", 11) == 0) { // some google source, we keep info } else if (strcmp(installer.c_str(), "preload") == 0) { // preloads, we keep the info } else if (installer.c_str()[0] == '\0') { // sideload (no installer); do not report pkg = ""; versionCode = 0; } else { // unknown installer; do not report pkg = ""; versionCode = 0; } } } // add it to the map, to save a subsequent lookup if (!pkg.empty()) { Mutex::Autolock _l(mLock_mappings); ALOGV("Adding uid %d pkg '%s'", uid, pkg.c_str()); mPkgMappings.add(uid, pkg); ssize_t i = mPkgMappings.indexOfKey(uid); if (i < 0) { mapping.uid = uid; mapping.pkg = pkg; mapping.installer = installer.c_str(); mapping.versionCode = versionCode; mapping.expiration = now + PKG_EXPIRATION_NS; ALOGV("expiration for uid %d set to %" PRId64 "", uid, mapping.expiration); mPkgMappings.add(uid, mapping); } } } return pkg; if (mapping.uid != (uid_t)(-1)) { if (setName) { item->setPkgName(mapping.pkg); } if (setVersion) { item->setPkgVersionCode(mapping.versionCode); } } } } // namespace android services/mediaanalytics/MediaAnalyticsService.h +6 −2 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ class MediaAnalyticsService : public BnMediaAnalyticsService // partitioned a bit so we don't over serialize mutable Mutex mLock; mutable Mutex mLock_ids; mutable Mutex mLock_mappings; // limit how many records we'll retain // by count (in each queue (open, finalized)) Loading Loading @@ -135,10 +136,13 @@ class MediaAnalyticsService : public BnMediaAnalyticsService struct UidToPkgMap { uid_t uid; AString pkg; AString installer; int32_t versionCode; nsecs_t expiration; }; KeyedVector<uid_t,AString> mPkgMappings; AString getPkgName(uid_t uid, bool addIfMissing); KeyedVector<uid_t,struct UidToPkgMap> mPkgMappings; void setPkgInfo(MediaAnalyticsItem *item, uid_t uid, bool setName, bool setVersion); }; Loading Loading
media/libmediametrics/MediaAnalyticsItem.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -59,6 +59,7 @@ const int MediaAnalyticsItem::EnabledProperty_default = 1; MediaAnalyticsItem::MediaAnalyticsItem() : mPid(-1), mUid(-1), mPkgVersionCode(0), mSessionID(MediaAnalyticsItem::SessionIDNone), mTimestamp(0), mFinalized(0), Loading @@ -70,6 +71,7 @@ MediaAnalyticsItem::MediaAnalyticsItem() MediaAnalyticsItem::MediaAnalyticsItem(MediaAnalyticsItem::Key key) : mPid(-1), mUid(-1), mPkgVersionCode(0), mSessionID(MediaAnalyticsItem::SessionIDNone), mTimestamp(0), mFinalized(0), Loading
services/mediaanalytics/MediaAnalyticsService.cpp +134 −63 Original line number Diff line number Diff line Loading @@ -257,14 +257,15 @@ MediaAnalyticsItem::SessionID_t MediaAnalyticsService::submit(MediaAnalyticsItem break; } // Overwrite package name and version if the caller was untrusted. if (!isTrusted) { item->setPkgName(getPkgName(item->getUid(), true)); item->setPkgVersionCode(0); setPkgInfo(item, item->getUid(), true, true); } else if (item->getPkgName().empty()) { // Only overwrite the package name if it was empty. Trust whatever // version code was provided by the trusted caller. item->setPkgName(getPkgName(uid, true)); // empty, so fill out both parts setPkgInfo(item, item->getUid(), true, true); } else { // trusted, provided a package, do nothing } ALOGV("given uid %d; sanitized uid: %d sanitized pkg: %s " Loading Loading @@ -800,31 +801,46 @@ void MediaAnalyticsService::summarize(MediaAnalyticsItem *item) { } // mapping uids to package names // how long we hold package info before we re-fetch it #define PKG_EXPIRATION_NS (30*60*1000000000ll) // 30 minutes, in nsecs // give me the package name, perhaps going to find it AString MediaAnalyticsService::getPkgName(uid_t uid, bool addIfMissing) { ssize_t i = mPkgMappings.indexOfKey(uid); if (i >= 0) { AString pkg = mPkgMappings.valueAt(i); ALOGV("returning pkg '%s' for uid %d", pkg.c_str(), uid); return pkg; void MediaAnalyticsService::setPkgInfo(MediaAnalyticsItem *item, uid_t uid, bool setName, bool setVersion) { ALOGV("asking for packagename to go with uid=%d", uid); if (!setName && !setVersion) { // setting nothing? strange return; } AString pkg; nsecs_t now = systemTime(SYSTEM_TIME_REALTIME); struct UidToPkgMap mapping; mapping.uid = (-1); if (addIfMissing == false) { return pkg; ssize_t i = mPkgMappings.indexOfKey(uid); if (i >= 0) { mapping = mPkgMappings.valueAt(i); ALOGV("Expiration? uid %d expiration %" PRId64 " now %" PRId64, uid, mapping.expiration, now); if (mapping.expiration < now) { // purge our current entry and re-query ALOGV("entry for uid %d expired, now= %" PRId64 "", uid, now); mPkgMappings.removeItemsAt(i, 1); // could cheat and use a goto back to the top of the routine. // a good compiler should recognize the local tail recursion... return setPkgInfo(item, uid, setName, setVersion); } } else { AString pkg; std::string installer = ""; int32_t versionCode = 0; struct passwd *pw = getpwuid(uid); if (pw) { pkg = pw->pw_name; } else { pkg = "-"; } // find the proper value // find the proper value -- should we cache this binder?? sp<IBinder> binder = NULL; sp<IServiceManager> sm = defaultServiceManager(); Loading @@ -839,13 +855,14 @@ AString MediaAnalyticsService::getPkgName(uid_t uid, bool addIfMissing) { if (binder != NULL) { sp<IPackageManagerNative> package_mgr = interface_cast<IPackageManagerNative>(binder); binder::Status status; std::vector<int> uids; std::vector<std::string> names; uids.push_back(uid); binder::Status status = package_mgr->getNamesForUids(uids, &names); status = package_mgr->getNamesForUids(uids, &names); if (!status.isOk()) { ALOGE("package_native::getNamesForUids failed: %s", status.exceptionMessage().c_str()); Loading @@ -854,31 +871,85 @@ AString MediaAnalyticsService::getPkgName(uid_t uid, bool addIfMissing) { pkg = names[0].c_str(); } } // strip any leading "shared:" strings that came back if (pkg.startsWith("shared:")) { pkg.erase(0, 7); } // determine how pkg was installed and the versionCode // if (pkg.empty()) { // no name for us to manage } else if (strchr(pkg.c_str(), '.') == NULL) { // not of form 'com.whatever...'; assume internal and ok } else if (strncmp(pkg.c_str(), "android.", 8) == 0) { // android.* packages are assumed fine } else { String16 pkgName16(pkg.c_str()); status = package_mgr->getInstallerForPackage(pkgName16, &installer); if (!status.isOk()) { ALOGE("package_native::getInstallerForPackage failed: %s", status.exceptionMessage().c_str()); } // skip if we didn't get an installer if (status.isOk()) { status = package_mgr->getVersionCodeForPackage(pkgName16, &versionCode); if (!status.isOk()) { ALOGE("package_native::getVersionCodeForPackage failed: %s", status.exceptionMessage().c_str()); } } // XXX determine whether package was side-loaded or from playstore. // for privacy, we only list apps loaded from playstore. // Sanitize the package name for ":" // as an example, we get "shared:android.uid.systemui" // replace : with something benign (I'm going to use !) if (!pkg.empty()) { int n = pkg.size(); char *p = (char *) pkg.c_str(); for (int i = 0 ; i < n; i++) { if (p[i] == ':') { p[i] = '!'; ALOGV("package '%s' installed by '%s' versioncode %d / %08x", pkg.c_str(), installer.c_str(), versionCode, versionCode); if (strncmp(installer.c_str(), "com.android.", 12) == 0) { // from play store, we keep info } else if (strncmp(installer.c_str(), "com.google.", 11) == 0) { // some google source, we keep info } else if (strcmp(installer.c_str(), "preload") == 0) { // preloads, we keep the info } else if (installer.c_str()[0] == '\0') { // sideload (no installer); do not report pkg = ""; versionCode = 0; } else { // unknown installer; do not report pkg = ""; versionCode = 0; } } } // add it to the map, to save a subsequent lookup if (!pkg.empty()) { Mutex::Autolock _l(mLock_mappings); ALOGV("Adding uid %d pkg '%s'", uid, pkg.c_str()); mPkgMappings.add(uid, pkg); ssize_t i = mPkgMappings.indexOfKey(uid); if (i < 0) { mapping.uid = uid; mapping.pkg = pkg; mapping.installer = installer.c_str(); mapping.versionCode = versionCode; mapping.expiration = now + PKG_EXPIRATION_NS; ALOGV("expiration for uid %d set to %" PRId64 "", uid, mapping.expiration); mPkgMappings.add(uid, mapping); } } } return pkg; if (mapping.uid != (uid_t)(-1)) { if (setName) { item->setPkgName(mapping.pkg); } if (setVersion) { item->setPkgVersionCode(mapping.versionCode); } } } } // namespace android
services/mediaanalytics/MediaAnalyticsService.h +6 −2 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ class MediaAnalyticsService : public BnMediaAnalyticsService // partitioned a bit so we don't over serialize mutable Mutex mLock; mutable Mutex mLock_ids; mutable Mutex mLock_mappings; // limit how many records we'll retain // by count (in each queue (open, finalized)) Loading Loading @@ -135,10 +136,13 @@ class MediaAnalyticsService : public BnMediaAnalyticsService struct UidToPkgMap { uid_t uid; AString pkg; AString installer; int32_t versionCode; nsecs_t expiration; }; KeyedVector<uid_t,AString> mPkgMappings; AString getPkgName(uid_t uid, bool addIfMissing); KeyedVector<uid_t,struct UidToPkgMap> mPkgMappings; void setPkgInfo(MediaAnalyticsItem *item, uid_t uid, bool setName, bool setVersion); }; Loading