AudioFlinger: fix unique ID generation after crash

The uniqued ID generator will generate the same audio session IDs
after a native audioserver restarts as it always resumes genrating from 1.
This can be a problem as the session ID of existing clients is
preserved on client side and reused when the client reconnects after a
native audioserver process crash.
This is particularly likely to happen with system sounds (touch sounds)
for which an audio track is created early in the init phase and stays
around forever.

To mitigate this risk, offset the allocation range by the
elapsed system time (monotonic) to push risk of overlap until after
first wrap around. Accounting for an average of one new ID per second
seems a good compromise between limiting the risk of overlap and leaving
room before the first wrap around.

Bug: 183582878
Test: make
Change-Id: I21b30c144cc3daab425757d7441af9bb62f793e5
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 6678287..7a89805 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -199,10 +199,21 @@
       mDeviceEffectManager(this),
       mSystemReady(false)
 {
+    // Move the audio session unique ID generator start base as time passes to limit risk of
+    // generating the same ID again after an audioserver restart.
+    // This is important because clients will reuse previously allocated audio session IDs
+    // when reconnecting after an audioserver restart and newly allocated IDs may conflict with
+    // active clients.
+    // Moving the base by 1 for each elapsed second is a good compromise between avoiding overlap
+    // between allocation ranges and not reaching wrap around too soon.
+    timespec ts{};
+    clock_gettime(CLOCK_MONOTONIC, &ts);
+    // zero ID has a special meaning, so start allocation at least at AUDIO_UNIQUE_ID_USE_MAX
+    uint32_t sessionBase = (uint32_t)std::max((long)1, ts.tv_sec);
     // unsigned instead of audio_unique_id_use_t, because ++ operator is unavailable for enum
     for (unsigned use = AUDIO_UNIQUE_ID_USE_UNSPECIFIED; use < AUDIO_UNIQUE_ID_USE_MAX; use++) {
-        // zero ID has a special meaning, so unavailable
-        mNextUniqueIds[use] = AUDIO_UNIQUE_ID_USE_MAX;
+        mNextUniqueIds[use] =
+                ((use == AUDIO_UNIQUE_ID_USE_SESSION) ? sessionBase : 1) * AUDIO_UNIQUE_ID_USE_MAX;
     }
 
 #if 1