Merge "Add adbd tls APIs to adbd_auth library."
diff --git a/cmds/installd/CacheTracker.cpp b/cmds/installd/CacheTracker.cpp
index 8b868fb..a61f6bf 100644
--- a/cmds/installd/CacheTracker.cpp
+++ b/cmds/installd/CacheTracker.cpp
@@ -75,8 +75,7 @@
 
 bool CacheTracker::loadQuotaStats() {
     int cacheGid = multiuser_get_cache_gid(mUserId, mAppId);
-    int extCacheGid = multiuser_get_ext_cache_gid(mUserId, mAppId);
-    if (IsQuotaSupported(mUuid) && cacheGid != -1 && extCacheGid != -1) {
+    if (IsQuotaSupported(mUuid) && cacheGid != -1) {
         int64_t space;
         if ((space = GetOccupiedSpaceForGid(mUuid, cacheGid)) != -1) {
             cacheUsed += space;
@@ -84,7 +83,7 @@
             return false;
         }
 
-        if ((space = GetOccupiedSpaceForGid(mUuid, extCacheGid)) != -1) {
+        if ((space = get_occupied_app_cache_space_external(mUuid, mUserId, mAppId)) != -1) {
             cacheUsed += space;
         } else {
             return false;
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 0fde31a..b3e6792 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -53,6 +53,7 @@
 #include <log/log.h>               // TODO: Move everything to base/logging.
 #include <logwrap/logwrap.h>
 #include <private/android_filesystem_config.h>
+#include <private/android_projectid_config.h>
 #include <selinux/android.h>
 #include <system/thread_defs.h>
 #include <utils/Trace.h>
@@ -689,11 +690,13 @@
         if (delete_dir_contents_and_dir(path) != 0) {
             res = error("Failed to delete " + path);
         }
-        destroy_app_current_profiles(packageName, userId);
-        // TODO(calin): If the package is still installed by other users it's probably
-        // beneficial to keep the reference profile around.
-        // Verify if it's ok to do that.
-        destroy_app_reference_profile(packageName);
+        if ((flags & FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES) == 0) {
+            destroy_app_current_profiles(packageName, userId);
+            // TODO(calin): If the package is still installed by other users it's probably
+            // beneficial to keep the reference profile around.
+            // Verify if it's ok to do that.
+            destroy_app_reference_profile(packageName);
+        }
     }
     if (flags & FLAG_STORAGE_EXTERNAL) {
         std::lock_guard<std::recursive_mutex> lock(mMountsLock);
@@ -1475,8 +1478,8 @@
 static void collectQuotaStats(const std::string& uuid, int32_t userId,
         int32_t appId, struct stats* stats, struct stats* extStats) {
     int64_t space;
+    uid_t uid = multiuser_get_uid(userId, appId);
     if (stats != nullptr) {
-        uid_t uid = multiuser_get_uid(userId, appId);
         if ((space = GetOccupiedSpaceForUid(uuid, uid)) != -1) {
             stats->dataSize += space;
         }
@@ -1497,20 +1500,44 @@
     }
 
     if (extStats != nullptr) {
-        int extGid = multiuser_get_ext_gid(userId, appId);
-        if (extGid != -1) {
-            if ((space = GetOccupiedSpaceForGid(uuid, extGid)) != -1) {
-                extStats->dataSize += space;
+        static const bool supportsSdCardFs = supports_sdcardfs();
+        space = get_occupied_app_space_external(uuid, userId, appId);
+
+        if (space != -1) {
+            extStats->dataSize += space;
+            if (!supportsSdCardFs && stats != nullptr) {
+                // On devices without sdcardfs, if internal and external are on
+                // the same volume, a uid such as u0_a123 is used for
+                // application dirs on both internal and external storage;
+                // therefore, substract that amount from internal to make sure
+                // we don't count it double.
+                stats->dataSize -= space;
             }
         }
 
-        int extCacheGid = multiuser_get_ext_cache_gid(userId, appId);
-        if (extCacheGid != -1) {
-            if ((space = GetOccupiedSpaceForGid(uuid, extCacheGid)) != -1) {
-                extStats->dataSize += space;
-                extStats->cacheSize += space;
+        space = get_occupied_app_cache_space_external(uuid, userId, appId);
+        if (space != -1) {
+            extStats->dataSize += space; // cache counts for "data"
+            extStats->cacheSize += space;
+            if (!supportsSdCardFs && stats != nullptr) {
+                // On devices without sdcardfs, if internal and external are on
+                // the same volume, a uid such as u0_a123 is used for both
+                // internal and external storage; therefore, substract that
+                // amount from internal to make sure we don't count it double.
+                stats->dataSize -= space;
             }
         }
+
+        if (!supportsSdCardFs && stats != nullptr) {
+            // On devices without sdcardfs, the UID of OBBs on external storage
+            // matches the regular app UID (eg u0_a123); therefore, to avoid
+            // OBBs being include in stats->dataSize, compute the OBB size for
+            // this app, and substract it from the size reported on internal
+            // storage
+            long obbProjectId = uid - AID_APP_START + PROJECT_ID_EXT_OBB_START;
+            int64_t appObbSize = GetOccupiedSpaceForProjectId(uuid, obbProjectId);
+            stats->dataSize -= appObbSize;
+        }
     }
 }
 
@@ -1759,6 +1786,106 @@
     return ok();
 }
 
+struct external_sizes {
+    int64_t audioSize;
+    int64_t videoSize;
+    int64_t imageSize;
+    int64_t totalSize; // excludes OBBs (Android/obb), but includes app data + cache
+    int64_t obbSize;
+};
+
+#define PER_USER_RANGE 100000
+
+static long getProjectIdForUser(int userId, long projectId) {
+    return userId * PER_USER_RANGE + projectId;
+}
+
+static external_sizes getExternalSizesForUserWithQuota(const std::string& uuid, int32_t userId, const std::vector<int32_t>& appIds) {
+    struct external_sizes sizes = {};
+    int64_t space;
+
+    if (supports_sdcardfs()) {
+        uid_t uid = multiuser_get_uid(userId, AID_MEDIA_RW);
+        if ((space = GetOccupiedSpaceForUid(uuid, uid)) != -1) {
+            sizes.totalSize = space;
+        }
+
+        gid_t audioGid = multiuser_get_uid(userId, AID_MEDIA_AUDIO);
+        if ((space = GetOccupiedSpaceForGid(uuid, audioGid)) != -1) {
+            sizes.audioSize = space;
+        }
+
+        gid_t videoGid = multiuser_get_uid(userId, AID_MEDIA_VIDEO);
+        if ((space = GetOccupiedSpaceForGid(uuid, videoGid)) != -1) {
+            sizes.videoSize = space;
+        }
+
+        gid_t imageGid = multiuser_get_uid(userId, AID_MEDIA_IMAGE);
+        if ((space = GetOccupiedSpaceForGid(uuid, imageGid)) != -1) {
+            sizes.imageSize = space;
+        }
+
+        if ((space = GetOccupiedSpaceForGid(uuid, AID_MEDIA_OBB)) != -1) {
+            sizes.obbSize = space;
+        }
+    } else {
+        int64_t totalSize = 0;
+        long defaultProjectId = getProjectIdForUser(userId, PROJECT_ID_EXT_DEFAULT);
+        if ((space = GetOccupiedSpaceForProjectId(uuid, defaultProjectId)) != -1) {
+            // This is all files that are not audio/video/images, excluding
+            // OBBs and app-private data
+            totalSize += space;
+        }
+
+        long audioProjectId = getProjectIdForUser(userId, PROJECT_ID_EXT_MEDIA_AUDIO);
+        if ((space = GetOccupiedSpaceForProjectId(uuid, audioProjectId)) != -1) {
+            sizes.audioSize = space;
+            totalSize += space;
+        }
+
+        long videoProjectId = getProjectIdForUser(userId, PROJECT_ID_EXT_MEDIA_VIDEO);
+        if ((space = GetOccupiedSpaceForProjectId(uuid, videoProjectId)) != -1) {
+            sizes.videoSize = space;
+            totalSize += space;
+        }
+
+        long imageProjectId = getProjectIdForUser(userId, PROJECT_ID_EXT_MEDIA_IMAGE);
+        if ((space = GetOccupiedSpaceForProjectId(uuid, imageProjectId)) != -1) {
+            sizes.imageSize = space;
+            totalSize += space;
+        }
+
+        int64_t totalAppDataSize = 0;
+        int64_t totalAppCacheSize = 0;
+        int64_t totalAppObbSize = 0;
+        for (auto appId : appIds) {
+            if (appId >= AID_APP_START) {
+                // App data
+                uid_t uid = multiuser_get_uid(userId, appId);
+                long projectId = uid - AID_APP_START + PROJECT_ID_EXT_DATA_START;
+                totalAppDataSize += GetOccupiedSpaceForProjectId(uuid, projectId);
+
+                // App cache
+                long cacheProjectId = uid - AID_APP_START + PROJECT_ID_EXT_CACHE_START;
+                totalAppCacheSize += GetOccupiedSpaceForProjectId(uuid, cacheProjectId);
+
+                // App OBBs
+                long obbProjectId = uid - AID_APP_START + PROJECT_ID_EXT_OBB_START;
+                totalAppObbSize += GetOccupiedSpaceForProjectId(uuid, obbProjectId);
+            }
+        }
+        // Total size should include app data + cache
+        totalSize += totalAppDataSize;
+        totalSize += totalAppCacheSize;
+        sizes.totalSize = totalSize;
+
+        // Only OBB is separate
+        sizes.obbSize = totalAppObbSize;
+    }
+
+    return sizes;
+}
+
 binder::Status InstalldNativeService::getUserSize(const std::unique_ptr<std::string>& uuid,
         int32_t userId, int32_t flags, const std::vector<int32_t>& appIds,
         std::vector<int64_t>* _aidl_return) {
@@ -1787,14 +1914,6 @@
     }
 
     if (flags & FLAG_USE_QUOTA) {
-        int64_t space;
-
-        ATRACE_BEGIN("obb");
-        if ((space = GetOccupiedSpaceForGid(uuidString, AID_MEDIA_OBB)) != -1) {
-            extStats.codeSize += space;
-        }
-        ATRACE_END();
-
         ATRACE_BEGIN("code");
         calculate_tree_size(create_data_app_path(uuid_), &stats.codeSize, -1, -1, true);
         ATRACE_END();
@@ -1816,10 +1935,9 @@
         }
 
         ATRACE_BEGIN("external");
-        uid_t uid = multiuser_get_uid(userId, AID_MEDIA_RW);
-        if ((space = GetOccupiedSpaceForUid(uuidString, uid)) != -1) {
-            extStats.dataSize += space;
-        }
+        auto sizes = getExternalSizesForUserWithQuota(uuidString, userId, appIds);
+        extStats.dataSize += sizes.totalSize;
+        extStats.codeSize += sizes.obbSize;
         ATRACE_END();
 
         if (!uuid) {
@@ -1830,13 +1948,11 @@
                     -1, -1, true);
             ATRACE_END();
         }
-
         ATRACE_BEGIN("quota");
         int64_t dataSize = extStats.dataSize;
         for (auto appId : appIds) {
             if (appId >= AID_APP_START) {
                 collectQuotaStats(uuidString, userId, appId, &stats, &extStats);
-
 #if MEASURE_DEBUG
                 // Sleep to make sure we don't lose logs
                 usleep(1);
@@ -1932,29 +2048,13 @@
     }
 
     if (flags & FLAG_USE_QUOTA) {
-        int64_t space;
-
         ATRACE_BEGIN("quota");
-        uid_t uid = multiuser_get_uid(userId, AID_MEDIA_RW);
-        if ((space = GetOccupiedSpaceForUid(uuidString, uid)) != -1) {
-            totalSize = space;
-        }
-
-        gid_t audioGid = multiuser_get_uid(userId, AID_MEDIA_AUDIO);
-        if ((space = GetOccupiedSpaceForGid(uuidString, audioGid)) != -1) {
-            audioSize = space;
-        }
-        gid_t videoGid = multiuser_get_uid(userId, AID_MEDIA_VIDEO);
-        if ((space = GetOccupiedSpaceForGid(uuidString, videoGid)) != -1) {
-            videoSize = space;
-        }
-        gid_t imageGid = multiuser_get_uid(userId, AID_MEDIA_IMAGE);
-        if ((space = GetOccupiedSpaceForGid(uuidString, imageGid)) != -1) {
-            imageSize = space;
-        }
-        if ((space = GetOccupiedSpaceForGid(uuidString, AID_MEDIA_OBB)) != -1) {
-            obbSize = space;
-        }
+        auto sizes = getExternalSizesForUserWithQuota(uuidString, userId, appIds);
+        totalSize = sizes.totalSize;
+        audioSize = sizes.audioSize;
+        videoSize = sizes.videoSize;
+        imageSize = sizes.imageSize;
+        obbSize = sizes.obbSize;
         ATRACE_END();
 
         ATRACE_BEGIN("apps");
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 2f79552..f82afa8 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -26,6 +26,7 @@
 #include <sys/xattr.h>
 #include <sys/statvfs.h>
 
+#include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/strings.h>
 #include <android-base/stringprintf.h>
@@ -34,9 +35,11 @@
 #include <cutils/properties.h>
 #include <log/log.h>
 #include <private/android_filesystem_config.h>
+#include <private/android_projectid_config.h>
 
 #include "dexopt_return_codes.h"
 #include "globals.h"  // extern variables.
+#include "QuotaUtils.h"
 
 #ifndef LOG_TAG
 #define LOG_TAG "installd"
@@ -1060,6 +1063,51 @@
     return 0;
 }
 
+static const char* kProcFilesystems = "/proc/filesystems";
+bool supports_sdcardfs() {
+    std::string supported;
+    if (!android::base::ReadFileToString(kProcFilesystems, &supported)) {
+        PLOG(ERROR) << "Failed to read supported filesystems";
+        return false;
+    }
+    return supported.find("sdcardfs\n") != std::string::npos;
+}
+
+int64_t get_occupied_app_space_external(const std::string& uuid, int32_t userId, int32_t appId) {
+    static const bool supportsSdcardFs = supports_sdcardfs();
+
+    if (supportsSdcardFs) {
+        int extGid = multiuser_get_ext_gid(userId, appId);
+
+        if (extGid == -1) {
+            return -1;
+        }
+
+        return GetOccupiedSpaceForGid(uuid, extGid);
+    } else {
+        uid_t uid = multiuser_get_uid(userId, appId);
+        long projectId = uid - AID_APP_START + PROJECT_ID_EXT_DATA_START;
+        return GetOccupiedSpaceForProjectId(uuid, projectId);
+    }
+}
+int64_t get_occupied_app_cache_space_external(const std::string& uuid, int32_t userId, int32_t appId) {
+    static const bool supportsSdcardFs = supports_sdcardfs();
+
+    if (supportsSdcardFs) {
+        int extCacheGid = multiuser_get_ext_cache_gid(userId, appId);
+
+        if (extCacheGid == -1) {
+            return -1;
+        }
+
+        return GetOccupiedSpaceForGid(uuid, extCacheGid);
+    } else {
+        uid_t uid = multiuser_get_uid(userId, appId);
+        long projectId = uid - AID_APP_START + PROJECT_ID_EXT_CACHE_START;
+        return GetOccupiedSpaceForProjectId(uuid, projectId);
+    }
+}
+
 // Collect all non empty profiles from the given directory and puts then into profile_paths.
 // The profiles are identified based on PROFILE_EXT extension.
 // If a subdirectory or profile file cannot be opened the method logs a warning and moves on.
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index 6a42026..2503168 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -150,6 +150,10 @@
 int prepare_app_cache_dir(const std::string& parent, const char* name, mode_t target_mode,
         uid_t uid, gid_t gid);
 
+bool supports_sdcardfs();
+int64_t get_occupied_app_space_external(const std::string& uuid, int32_t userId, int32_t appId);
+int64_t get_occupied_app_cache_space_external(const std::string& uuid, int32_t userId, int32_t appId);
+
 // Collect all non empty profiles from the global profile directory and
 // put then into profile_paths. The profiles are identified based on PROFILE_EXT extension.
 // If a subdirectory or profile file cannot be opened the method logs a warning and moves on.
diff --git a/libs/binder/LazyServiceRegistrar.cpp b/libs/binder/LazyServiceRegistrar.cpp
index f064bd7..71d8130 100644
--- a/libs/binder/LazyServiceRegistrar.cpp
+++ b/libs/binder/LazyServiceRegistrar.cpp
@@ -64,8 +64,7 @@
 
 bool ClientCounterCallback::registerService(const sp<IBinder>& service, const std::string& name,
                                             bool allowIsolated, int dumpFlags) {
-    auto manager = interface_cast<AidlServiceManager>(
-                    ProcessState::self()->getContextObject(nullptr));
+    auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));
 
     bool reRegister = mRegisteredServices.count(name) > 0;
     std::string regStr = (reRegister) ? "Re-registering" : "Registering";
@@ -114,9 +113,7 @@
 void ClientCounterCallback::tryShutdown() {
     ALOGI("Trying to shut down the service. No clients in use for any service in process.");
 
-    // This makes the same assumption as IServiceManager.cpp. Could dedupe if used in more places.
-    auto manager = interface_cast<AidlServiceManager>(
-            ProcessState::self()->getContextObject(nullptr));
+    auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));
 
     auto unRegisterIt = mRegisteredServices.begin();
     for (; unRegisterIt != mRegisteredServices.end(); ++unRegisterIt) {
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 822247f..f1077ae 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -558,6 +558,13 @@
 bool Parcel::enforceInterface(const String16& interface,
                               IPCThreadState* threadState) const
 {
+    return enforceInterface(interface.string(), interface.size(), threadState);
+}
+
+bool Parcel::enforceInterface(const char16_t* interface,
+                              size_t len,
+                              IPCThreadState* threadState) const
+{
     // StrictModePolicy.
     int32_t strictPolicy = readInt32();
     if (threadState == nullptr) {
@@ -584,12 +591,15 @@
         return false;
     }
     // Interface descriptor.
-    const String16 str(readString16());
-    if (str == interface) {
+    size_t parcel_interface_len;
+    const char16_t* parcel_interface = readString16Inplace(&parcel_interface_len);
+    if (len == parcel_interface_len &&
+            (!len || !memcmp(parcel_interface, interface, len * sizeof (char16_t)))) {
         return true;
     } else {
         ALOGW("**** enforceInterface() expected '%s' but read '%s'",
-                String8(interface).string(), String8(str).string());
+              String8(interface, len).string(),
+              String8(parcel_interface, parcel_interface_len).string());
         return false;
     }
 }
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index c0f5e31..631e8c5 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -112,6 +112,10 @@
 {
     sp<IBinder> context = getStrongProxyForHandle(0);
 
+    if (context == nullptr) {
+       ALOGW("Not able to get context object on %s.", mDriverName.c_str());
+    }
+
     // The root object is special since we get it directly from the driver, it is never
     // written by Parcell::writeStrongBinder.
     internal::Stability::tryMarkCompilationUnit(context.get());
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index d4bb85b..4b1a758 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -96,6 +96,9 @@
     // passed in.
     bool                enforceInterface(const String16& interface,
                                          IPCThreadState* threadState = nullptr) const;
+    bool                enforceInterface(const char16_t* interface,
+                                         size_t len,
+                                         IPCThreadState* threadState = nullptr) const;
     bool                checkInterface(IBinder*) const;
 
     void                freeData();
diff --git a/libs/binder/ndk/parcel.cpp b/libs/binder/ndk/parcel.cpp
index 703ceae..c33c44f 100644
--- a/libs/binder/ndk/parcel.cpp
+++ b/libs/binder/ndk/parcel.cpp
@@ -247,15 +247,12 @@
         if (fd != -1) {
             return STATUS_UNKNOWN_ERROR;
         }
-        return parcel->get()->writeInt32(0);  // null
+        return PruneStatusT(parcel->get()->writeInt32(0));  // null
     }
+    status_t status = parcel->get()->writeInt32(1);  // not-null
+    if (status != STATUS_OK) return PruneStatusT(status);
 
-    ParcelFileDescriptor parcelFd = ParcelFileDescriptor(unique_fd(fd));
-    status_t status = parcel->get()->writeParcelable(parcelFd);
-
-    // ownership is retained by caller
-    (void)parcelFd.release().release();
-
+    status = parcel->get()->writeDupParcelFileDescriptor(fd);
     return PruneStatusT(status);
 }
 
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 5e0574a..8cb06e1 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -30,6 +30,7 @@
 
 #include <private/binder/binder_module.h>
 #include <sys/epoll.h>
+#include <sys/prctl.h>
 
 #define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
 
@@ -106,6 +107,7 @@
     if (pid == -1)
         return pid;
     if (pid == 0) {
+        prctl(PR_SET_PDEATHSIG, SIGHUP);
         close(pipefd[0]);
         execv(binderservername, childargv);
         status = -errno;
diff --git a/libs/cputimeinstate/cputimeinstate.cpp b/libs/cputimeinstate/cputimeinstate.cpp
index a03775b..58126dc 100644
--- a/libs/cputimeinstate/cputimeinstate.cpp
+++ b/libs/cputimeinstate/cputimeinstate.cpp
@@ -161,6 +161,17 @@
     return bpf_attach_tracepoint(prog_fd, eventType.c_str(), eventName.c_str()) >= 0;
 }
 
+static std::optional<uint32_t> getPolicyFreqIdx(uint32_t policy) {
+    auto path = StringPrintf("/sys/devices/system/cpu/cpufreq/policy%u/scaling_cur_freq",
+                             gPolicyCpus[policy][0]);
+    auto freqVec = readNumbersFromFile(path);
+    if (!freqVec.has_value() || freqVec->size() != 1) return {};
+    for (uint32_t idx = 0; idx < gPolicyFreqs[policy].size(); ++idx) {
+        if ((*freqVec)[0] == gPolicyFreqs[policy][idx]) return idx + 1;
+    }
+    return {};
+}
+
 // Start tracking and aggregating data to be reported by getUidCpuFreqTimes and getUidsCpuFreqTimes.
 // Returns true on success, false otherwise.
 // Tracking is active only once a live process has successfully called this function; if the calling
@@ -215,7 +226,9 @@
     unique_fd policyFreqIdxFd(bpf_obj_get_wronly(BPF_FS_PATH "map_time_in_state_policy_freq_idx_map"));
     if (policyFreqIdxFd < 0) return false;
     for (uint32_t i = 0; i < gNPolicies; ++i) {
-        if (writeToMapEntry(policyFreqIdxFd, &i, &zero, BPF_ANY)) return false;
+        auto freqIdx = getPolicyFreqIdx(i);
+        if (!freqIdx.has_value()) return false;
+        if (writeToMapEntry(policyFreqIdxFd, &i, &(*freqIdx), BPF_ANY)) return false;
     }
 
     gTracking = attachTracepointProgram("sched", "sched_switch") &&