Merge "CameraService: Handle ActivityManager death for UidPolicy" into pi-dev
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index ad63899..fb9b0ba 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -1550,6 +1550,9 @@
 
     switch(eventId) {
         case ICameraService::EVENT_USER_SWITCHED: {
+            // Try to register for UID policy updates, in case we're recovering
+            // from a system server crash
+            mUidPolicy->registerSelf();
             doUserSwitch(/*newUserIds*/ args);
             break;
         }
@@ -2365,17 +2368,31 @@
 // ----------------------------------------------------------------------------
 
 void CameraService::UidPolicy::registerSelf() {
+    Mutex::Autolock _l(mUidLock);
+
     ActivityManager am;
+    if (mRegistered) return;
     am.registerUidObserver(this, ActivityManager::UID_OBSERVER_GONE
             | ActivityManager::UID_OBSERVER_IDLE
             | ActivityManager::UID_OBSERVER_ACTIVE,
             ActivityManager::PROCESS_STATE_UNKNOWN,
             String16("cameraserver"));
+    status_t res = am.linkToDeath(this);
+    if (res == OK) {
+        mRegistered = true;
+        ALOGV("UidPolicy: Registered with ActivityManager");
+    }
 }
 
 void CameraService::UidPolicy::unregisterSelf() {
+    Mutex::Autolock _l(mUidLock);
+
     ActivityManager am;
     am.unregisterUidObserver(this);
+    am.unlinkToDeath(this);
+    mRegistered = false;
+    mActiveUids.clear();
+    ALOGV("UidPolicy: Unregistered with ActivityManager");
 }
 
 void CameraService::UidPolicy::onUidGone(uid_t uid, bool disabled) {
@@ -2404,17 +2421,14 @@
 }
 
 bool CameraService::UidPolicy::isUidActive(uid_t uid) {
-    // Non-app UIDs are considered always active
-    if (uid < FIRST_APPLICATION_UID) {
-        return true;
-    }
     Mutex::Autolock _l(mUidLock);
     return isUidActiveLocked(uid);
 }
 
 bool CameraService::UidPolicy::isUidActiveLocked(uid_t uid) {
     // Non-app UIDs are considered always active
-    if (uid < FIRST_APPLICATION_UID) {
+    // If activity manager is unreachable, assume everything is active
+    if (uid < FIRST_APPLICATION_UID || !mRegistered) {
         return true;
     }
     auto it = mOverrideUids.find(uid);
@@ -2432,6 +2446,13 @@
     updateOverrideUid(uid, false, false);
 }
 
+void CameraService::UidPolicy::binderDied(const wp<IBinder>& /*who*/) {
+    Mutex::Autolock _l(mUidLock);
+    ALOGV("UidPolicy: ActivityManager has died");
+    mRegistered = false;
+    mActiveUids.clear();
+}
+
 void CameraService::UidPolicy::updateOverrideUid(uid_t uid, bool active, bool insert) {
     bool wasActive = false;
     bool isActive = false;
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 3812925..86a2b81 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -518,10 +518,10 @@
 
     // Observer for UID lifecycle enforcing that UIDs in idle
     // state cannot use the camera to protect user privacy.
-    class UidPolicy : public BnUidObserver {
+    class UidPolicy : public BnUidObserver, public virtual IBinder::DeathRecipient {
     public:
         explicit UidPolicy(sp<CameraService> service)
-                : mService(service) {}
+                : mRegistered(false), mService(service) {}
 
         void registerSelf();
         void unregisterSelf();
@@ -535,11 +535,14 @@
         void addOverrideUid(uid_t uid, bool active);
         void removeOverrideUid(uid_t uid);
 
+        // IBinder::DeathRecipient implementation
+        virtual void binderDied(const wp<IBinder> &who);
     private:
         bool isUidActiveLocked(uid_t uid);
         void updateOverrideUid(uid_t uid, bool active, bool insert);
 
         Mutex mUidLock;
+        bool mRegistered;
         wp<CameraService> mService;
         std::unordered_set<uid_t> mActiveUids;
         std::unordered_map<uid_t, bool> mOverrideUids;