Merge "Log when binder thread pool is starved" into nyc-dev
am: 43dcac7

* commit '43dcac7500833c465c417805adc4693c60c3bb5e':
  Log when binder thread pool is starved

Change-Id: I420d31273aec69eab9d8e4faa10001ef48b17aa8
diff --git a/AppOpsManager.cpp b/AppOpsManager.cpp
index 9a061a0..f3b86ae 100644
--- a/AppOpsManager.cpp
+++ b/AppOpsManager.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <mutex>
 #include <binder/AppOpsManager.h>
 #include <binder/Binder.h>
 #include <binder/IServiceManager.h>
@@ -22,6 +23,19 @@
 
 namespace android {
 
+namespace {
+
+#if defined(__BRILLO__)
+// Because Brillo has no application model, security policy is managed
+// statically (at build time) with SELinux controls.
+// As a consequence, it also never runs the AppOpsManager service.
+const int APP_OPS_MANAGER_UNAVAILABLE_MODE = AppOpsManager::MODE_ALLOWED;
+#else
+const int APP_OPS_MANAGER_UNAVAILABLE_MODE = AppOpsManager::MODE_IGNORED;
+#endif  // defined(__BRILLO__)
+
+}  // namespace
+
 static String16 _appops("appops");
 static pthread_mutex_t gTokenMutex = PTHREAD_MUTEX_INITIALIZER;
 static sp<IBinder> gToken;
@@ -39,10 +53,15 @@
 {
 }
 
+#if defined(__BRILLO__)
+// There is no AppOpsService on Brillo
+sp<IAppOpsService> AppOpsManager::getService() { return NULL; }
+#else
 sp<IAppOpsService> AppOpsManager::getService()
 {
+
+    std::lock_guard<Mutex> scoped_lock(mLock);
     int64_t startTime = 0;
-    mLock.lock();
     sp<IAppOpsService> service = mService;
     while (service == NULL || !IInterface::asBinder(service)->isBinderAlive()) {
         sp<IBinder> binder = defaultServiceManager()->checkService(_appops);
@@ -53,7 +72,8 @@
                 ALOGI("Waiting for app ops service");
             } else if ((uptimeMillis()-startTime) > 10000) {
                 ALOGW("Waiting too long for app ops service, giving up");
-                return NULL;
+                service = NULL;
+                break;
             }
             sleep(1);
         } else {
@@ -61,25 +81,30 @@
             mService = service;
         }
     }
-    mLock.unlock();
     return service;
 }
+#endif  // defined(__BRILLO__)
 
 int32_t AppOpsManager::checkOp(int32_t op, int32_t uid, const String16& callingPackage)
 {
     sp<IAppOpsService> service = getService();
-    return service != NULL ? service->checkOperation(op, uid, callingPackage) : MODE_IGNORED;
+    return service != NULL
+            ? service->checkOperation(op, uid, callingPackage)
+            : APP_OPS_MANAGER_UNAVAILABLE_MODE;
 }
 
 int32_t AppOpsManager::noteOp(int32_t op, int32_t uid, const String16& callingPackage) {
     sp<IAppOpsService> service = getService();
-    return service != NULL ? service->noteOperation(op, uid, callingPackage) : MODE_IGNORED;
+    return service != NULL
+            ? service->noteOperation(op, uid, callingPackage)
+            : APP_OPS_MANAGER_UNAVAILABLE_MODE;
 }
 
 int32_t AppOpsManager::startOp(int32_t op, int32_t uid, const String16& callingPackage) {
     sp<IAppOpsService> service = getService();
-    return service != NULL ? service->startOperation(getToken(service), op, uid, callingPackage)
-            : MODE_IGNORED;
+    return service != NULL
+            ? service->startOperation(getToken(service), op, uid, callingPackage)
+            : APP_OPS_MANAGER_UNAVAILABLE_MODE;
 }
 
 void AppOpsManager::finishOp(int32_t op, int32_t uid, const String16& callingPackage) {
diff --git a/IPCThreadState.cpp b/IPCThreadState.cpp
index d90798f..9b5f0d7 100644
--- a/IPCThreadState.cpp
+++ b/IPCThreadState.cpp
@@ -330,6 +330,7 @@
             delete st;
             pthread_setspecific(gTLS, NULL);
         }
+        pthread_key_delete(gTLS);
         gHaveTLS = false;
     }
 }
diff --git a/IServiceManager.cpp b/IServiceManager.cpp
index 61f24d6..725ebdf 100644
--- a/IServiceManager.cpp
+++ b/IServiceManager.cpp
@@ -67,11 +67,6 @@
 
 bool checkPermission(const String16& permission, pid_t pid, uid_t uid)
 {
-#ifdef __BRILLO__
-    // Brillo doesn't currently run ActivityManager or support framework permissions.
-    return true;
-#endif
-
     sp<IPermissionController> pc;
     gDefaultServiceManagerLock.lock();
     pc = gPermissionController;
diff --git a/Parcel.cpp b/Parcel.cpp
index a0161b3..8898bcc 100644
--- a/Parcel.cpp
+++ b/Parcel.cpp
@@ -1112,7 +1112,7 @@
 }
 
 status_t Parcel::readStrongBinderVector(std::unique_ptr<std::vector<sp<IBinder>>>* val) const {
-    return readNullableTypedVector(val, &Parcel::readStrongBinder);
+    return readNullableTypedVector(val, &Parcel::readNullableStrongBinder);
 }
 
 status_t Parcel::readStrongBinderVector(std::vector<sp<IBinder>>* val) const {
@@ -1912,13 +1912,25 @@
 
 status_t Parcel::readStrongBinder(sp<IBinder>* val) const
 {
+    status_t status = readNullableStrongBinder(val);
+    if (status == OK && !val->get()) {
+        status = UNEXPECTED_NULL;
+    }
+    return status;
+}
+
+status_t Parcel::readNullableStrongBinder(sp<IBinder>* val) const
+{
     return unflatten_binder(ProcessState::self(), *this, val);
 }
 
 sp<IBinder> Parcel::readStrongBinder() const
 {
     sp<IBinder> val;
-    readStrongBinder(&val);
+    // Note that a lot of code in Android reads binders by hand with this
+    // method, and that code has historically been ok with getting nullptr
+    // back (while ignoring error codes).
+    readNullableStrongBinder(&val);
     return val;
 }
 
diff --git a/PersistableBundle.cpp b/PersistableBundle.cpp
index aef791c..a20359f 100644
--- a/PersistableBundle.cpp
+++ b/PersistableBundle.cpp
@@ -32,6 +32,9 @@
 using android::sp;
 using android::status_t;
 using android::UNEXPECTED_NULL;
+using std::map;
+using std::set;
+using std::vector;
 
 enum {
     // Keep in sync with BUNDLE_MAGIC in frameworks/base/core/java/android/os/BaseBundle.java.
@@ -55,12 +58,22 @@
 
 namespace {
 template <typename T>
-bool getValue(const android::String16& key, T* out, const std::map<android::String16, T>& map) {
+bool getValue(const android::String16& key, T* out, const map<android::String16, T>& map) {
     const auto& it = map.find(key);
     if (it == map.end()) return false;
     *out = it->second;
     return true;
 }
+
+template <typename T>
+set<android::String16> getKeys(const map<android::String16, T>& map) {
+    if (map.empty()) return set<android::String16>();
+    set<android::String16> keys;
+    for (const auto& key_value_pair : map) {
+        keys.emplace(key_value_pair.first);
+    }
+    return keys;
+}
 }  // namespace
 
 namespace android {
@@ -188,27 +201,27 @@
     mStringMap[key] = value;
 }
 
-void PersistableBundle::putBooleanVector(const String16& key, const std::vector<bool>& value) {
+void PersistableBundle::putBooleanVector(const String16& key, const vector<bool>& value) {
     erase(key);
     mBoolVectorMap[key] = value;
 }
 
-void PersistableBundle::putIntVector(const String16& key, const std::vector<int32_t>& value) {
+void PersistableBundle::putIntVector(const String16& key, const vector<int32_t>& value) {
     erase(key);
     mIntVectorMap[key] = value;
 }
 
-void PersistableBundle::putLongVector(const String16& key, const std::vector<int64_t>& value) {
+void PersistableBundle::putLongVector(const String16& key, const vector<int64_t>& value) {
     erase(key);
     mLongVectorMap[key] = value;
 }
 
-void PersistableBundle::putDoubleVector(const String16& key, const std::vector<double>& value) {
+void PersistableBundle::putDoubleVector(const String16& key, const vector<double>& value) {
     erase(key);
     mDoubleVectorMap[key] = value;
 }
 
-void PersistableBundle::putStringVector(const String16& key, const std::vector<String16>& value) {
+void PersistableBundle::putStringVector(const String16& key, const vector<String16>& value) {
     erase(key);
     mStringVectorMap[key] = value;
 }
@@ -238,23 +251,23 @@
     return getValue(key, out, mStringMap);
 }
 
-bool PersistableBundle::getBooleanVector(const String16& key, std::vector<bool>* out) const {
+bool PersistableBundle::getBooleanVector(const String16& key, vector<bool>* out) const {
     return getValue(key, out, mBoolVectorMap);
 }
 
-bool PersistableBundle::getIntVector(const String16& key, std::vector<int32_t>* out) const {
+bool PersistableBundle::getIntVector(const String16& key, vector<int32_t>* out) const {
     return getValue(key, out, mIntVectorMap);
 }
 
-bool PersistableBundle::getLongVector(const String16& key, std::vector<int64_t>* out) const {
+bool PersistableBundle::getLongVector(const String16& key, vector<int64_t>* out) const {
     return getValue(key, out, mLongVectorMap);
 }
 
-bool PersistableBundle::getDoubleVector(const String16& key, std::vector<double>* out) const {
+bool PersistableBundle::getDoubleVector(const String16& key, vector<double>* out) const {
     return getValue(key, out, mDoubleVectorMap);
 }
 
-bool PersistableBundle::getStringVector(const String16& key, std::vector<String16>* out) const {
+bool PersistableBundle::getStringVector(const String16& key, vector<String16>* out) const {
     return getValue(key, out, mStringVectorMap);
 }
 
@@ -262,6 +275,50 @@
     return getValue(key, out, mPersistableBundleMap);
 }
 
+set<String16> PersistableBundle::getBooleanKeys() const {
+    return getKeys(mBoolMap);
+}
+
+set<String16> PersistableBundle::getIntKeys() const {
+    return getKeys(mIntMap);
+}
+
+set<String16> PersistableBundle::getLongKeys() const {
+    return getKeys(mLongMap);
+}
+
+set<String16> PersistableBundle::getDoubleKeys() const {
+    return getKeys(mDoubleMap);
+}
+
+set<String16> PersistableBundle::getStringKeys() const {
+    return getKeys(mStringMap);
+}
+
+set<String16> PersistableBundle::getBooleanVectorKeys() const {
+    return getKeys(mBoolVectorMap);
+}
+
+set<String16> PersistableBundle::getIntVectorKeys() const {
+    return getKeys(mIntVectorMap);
+}
+
+set<String16> PersistableBundle::getLongVectorKeys() const {
+    return getKeys(mLongVectorMap);
+}
+
+set<String16> PersistableBundle::getDoubleVectorKeys() const {
+    return getKeys(mDoubleVectorMap);
+}
+
+set<String16> PersistableBundle::getStringVectorKeys() const {
+    return getKeys(mStringVectorMap);
+}
+
+set<String16> PersistableBundle::getPersistableBundleKeys() const {
+    return getKeys(mPersistableBundleMap);
+}
+
 status_t PersistableBundle::writeToParcelInner(Parcel* parcel) const {
     /*
      * To keep this implementation in sync with writeArrayMapInternal() in
diff --git a/ProcessState.cpp b/ProcessState.cpp
index f13f49f..e45b5f1 100644
--- a/ProcessState.cpp
+++ b/ProcessState.cpp
@@ -366,6 +366,13 @@
 
 ProcessState::~ProcessState()
 {
+    if (mDriverFD >= 0) {
+        if (mVMStart != MAP_FAILED) {
+            munmap(mVMStart, BINDER_VM_SIZE);
+        }
+        close(mDriverFD);
+    }
+    mDriverFD = -1;
 }
         
 }; // namespace android
diff --git a/Status.cpp b/Status.cpp
index d3520d6..5ae6db2 100644
--- a/Status.cpp
+++ b/Status.cpp
@@ -158,5 +158,10 @@
     return ret;
 }
 
+std::stringstream& operator<< (std::stringstream& stream, const Status& s) {
+    stream << s.toString8().string();
+    return stream;
+}
+
 }  // namespace binder
 }  // namespace android
diff --git a/include/hwbinder/Parcel.h b/include/hwbinder/Parcel.h
index 2685bcc..a836ce4 100644
--- a/include/hwbinder/Parcel.h
+++ b/include/hwbinder/Parcel.h
@@ -252,6 +252,7 @@
     const char16_t*     readString16Inplace(size_t* outLen) const;
     sp<IBinder>         readStrongBinder() const;
     status_t            readStrongBinder(sp<IBinder>* val) const;
+    status_t            readNullableStrongBinder(sp<IBinder>* val) const;
     wp<IBinder>         readWeakBinder() const;
 
     template<typename T>
@@ -268,6 +269,9 @@
     template<typename T>
     status_t            readStrongBinder(sp<T>* val) const;
 
+    template<typename T>
+    status_t            readNullableStrongBinder(sp<T>* val) const;
+
     status_t            readStrongBinderVector(std::unique_ptr<std::vector<sp<IBinder>>>* val) const;
     status_t            readStrongBinderVector(std::vector<sp<IBinder>>* val) const;
 
@@ -574,6 +578,20 @@
     return ret;
 }
 
+template<typename T>
+status_t Parcel::readNullableStrongBinder(sp<T>* val) const {
+    sp<IBinder> tmp;
+    status_t ret = readNullableStrongBinder(&tmp);
+
+    if (ret == OK) {
+        *val = interface_cast<T>(tmp);
+
+        if (val->get() == nullptr) {
+            return UNKNOWN_ERROR;
+        }
+    }
+}
+
 template<typename T, typename U>
 status_t Parcel::unsafeReadTypedVector(
         std::vector<T>* val,
diff --git a/include/hwbinder/PersistableBundle.h b/include/hwbinder/PersistableBundle.h
index fe5619f..322fef9 100644
--- a/include/hwbinder/PersistableBundle.h
+++ b/include/hwbinder/PersistableBundle.h
@@ -18,6 +18,7 @@
 #define ANDROID_PERSISTABLE_BUNDLE_H
 
 #include <map>
+#include <set>
 #include <vector>
 
 #include <binder/Parcelable.h>
@@ -79,6 +80,19 @@
     bool getStringVector(const String16& key, std::vector<String16>* out) const;
     bool getPersistableBundle(const String16& key, PersistableBundle* out) const;
 
+    /* Getters for all keys for each value type */
+    std::set<String16> getBooleanKeys() const;
+    std::set<String16> getIntKeys() const;
+    std::set<String16> getLongKeys() const;
+    std::set<String16> getDoubleKeys() const;
+    std::set<String16> getStringKeys() const;
+    std::set<String16> getBooleanVectorKeys() const;
+    std::set<String16> getIntVectorKeys() const;
+    std::set<String16> getLongVectorKeys() const;
+    std::set<String16> getDoubleVectorKeys() const;
+    std::set<String16> getStringVectorKeys() const;
+    std::set<String16> getPersistableBundleKeys() const;
+
     friend bool operator==(const PersistableBundle& lhs, const PersistableBundle& rhs) {
         return (lhs.mBoolMap == rhs.mBoolMap && lhs.mIntMap == rhs.mIntMap &&
                 lhs.mLongMap == rhs.mLongMap && lhs.mDoubleMap == rhs.mDoubleMap &&
diff --git a/include/hwbinder/Status.h b/include/hwbinder/Status.h
index ce947fa..7253af8 100644
--- a/include/hwbinder/Status.h
+++ b/include/hwbinder/Status.h
@@ -18,6 +18,7 @@
 #define ANDROID_BINDER_STATUS_H
 
 #include <cstdint>
+#include <sstream>
 
 #include <binder/Parcel.h>
 #include <utils/String8.h>
@@ -142,11 +143,7 @@
 };  // class Status
 
 // For gtest output logging
-template<typename T>
-T& operator<< (T& stream, const Status& s) {
-    stream << s.toString8().string();
-    return stream;
-}
+std::stringstream& operator<< (std::stringstream& stream, const Status& s);
 
 }  // namespace binder
 }  // namespace android