Native Service and Android Service

  • Native Service:In every main() method of NativeService, which is called by init process through parseing init.rc, the globale object of ProcessState will be created by calling ProcessState::self(),and then startThreadPool and created main thread by calling IPCThreadPool.self()->joinThreadPool().
  • Android Service:All Android Service is created by SystemServer and running in the same process which is system server.

New Process with main()

  1. int main(int argc, char** argv)
  2. {
  3. sp<ProcessState> proc(ProcessState::self());
  4. sp<IServiceManager> sm = defaultServiceManager();
  5. LOGI("ServiceManager: %p", sm.get());
  6. AudioFlinger::instantiate();
  7. MediaPlayerService::instantiate();
  8. CameraService::instantiate();
  9. AudioPolicyService::instantiate();
  10. ProcessState::self()->startThreadPool();
  11. IPCThreadState::self()->joinThreadPool();
  12. }

Static: private/binder/Static.h

  • Static.h
    1. #include <utils/threads.h>
    2. #include <binder/IBinder.h>
    3. #include <binder/IMemory.h>
    4. #include <binder/ProcessState.h>
    5. #include <binder/IPermissionController.h>
    6. #include <binder/IServiceManager.h>
    7. namespace android {
    8. // For ProcessState.cpp
    9. extern Mutex gProcessMutex;
    10. extern sp<ProcessState> gProcess;
    11. // For ServiceManager.cpp
    12. extern Mutex gDefaultServiceManagerLock;
    13. extern sp<IServiceManager> gDefaultServiceManager;
    14. extern sp<IPermissionController> gPermissionController;
    15. }
  • Static.cpp
    1. #include <private/binder/Static.h>
    2. #include <binder/IPCThreadState.h>
    3. #include <utils/Log.h>
    4. namespace android {
    5. // ------------ ProcessState.cpp
    6. Mutex gProcessMutex;
    7. sp<ProcessState> gProcess;
    8. class LibUtilsIPCtStatics
    9. {
    10. public:
    11. LibUtilsIPCtStatics()
    12. {
    13. }
    14.  
    15. ~LibUtilsIPCtStatics()
    16. {
    17. IPCThreadState::shutdown();
    18. }
    19. };
    20. static LibUtilsIPCtStatics gIPCStatics;
    21. // ------------ ServiceManager.cpp
    22. Mutex gDefaultServiceManagerLock;
    23. sp<IServiceManager> gDefaultServiceManager;
    24. sp<IPermissionController> gPermissionController;
    25. }
  • When we create new process and call main()..........,the gloable vairables will be created
    1. Mutex gProcessMutex;
    2. sp<ProcessState> gProcess;
    3. Mutex gDefaultServiceManagerLock;
    4. sp<IServiceManager> gDefaultServiceManager;
    5. sp<IPermissionController> gPermissionController;

Threads

  • android.threads wrap something related to thread using linux's pthread.h
    1. /**
    2. * Copyright (C) 2007 The Android Open Source Project
    3. *
    4. * Licensed under the Apache License, Version 2.0 (the "License");
    5. * you may not use this file except in compliance with the License.
    6. * You may obtain a copy of the License at
    7. *
    8. * http://www.apache.org/licenses/LICENSE-2.0
    9. *
    10. * Unless required by applicable law or agreed to in writing, software
    11. * distributed under the License is distributed on an "AS IS" BASIS,
    12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13. * See the License for the specific language governing permissions and
    14. * limitations under the License.
    15. */
    16.  
    17. #ifndef _LIBS_UTILS_THREADS_H
    18. #define _LIBS_UTILS_THREADS_H
    19.  
    20. #include <stdint.h>
    21. #include <sys/types.h>
    22. #include <time.h>
    23. #include <system/graphics.h>
    24.  
    25. #if defined(HAVE_PTHREADS)
    26. # include <pthread.h>
    27. #endif
    28.  
    29. // ------------------------------------------------------------------
    30. // C API
    31.  
    32. #ifdef __cplusplus
    33. extern "C" {
    34. #endif
    35.  
    36. typedef void* android_thread_id_t;
    37.  
    38. typedef int (*android_thread_func_t)(void*);
    39.  
    40. enum {
    41. /**
    42. * ***********************************************
    43. * ** Keep in sync with android.os.Process.java **
    44. * ***********************************************
    45. *
    46. * This maps directly to the "nice" priorities we use in Android.
    47. * A thread priority should be chosen inverse-proportionally to
    48. * the amount of work the thread is expected to do. The more work
    49. * a thread will do, the less favorable priority it should get so that
    50. * it doesn't starve the system. Threads not behaving properly might
    51. * be "punished" by the kernel.
    52. * Use the levels below when appropriate. Intermediate values are
    53. * acceptable, preferably use the {MORE|LESS}_FAVORABLE constants below.
    54. */
    55. ANDROID_PRIORITY_LOWEST = ,
    56.  
    57. /** use for background tasks */
    58. ANDROID_PRIORITY_BACKGROUND = ,
    59.  
    60. /** most threads run at normal priority */
    61. ANDROID_PRIORITY_NORMAL = ,
    62.  
    63. /** threads currently running a UI that the user is interacting with */
    64. ANDROID_PRIORITY_FOREGROUND = -,
    65.  
    66. /** the main UI thread has a slightly more favorable priority */
    67. ANDROID_PRIORITY_DISPLAY = -,
    68.  
    69. /** ui service treads might want to run at a urgent display (uncommon) */
    70. ANDROID_PRIORITY_URGENT_DISPLAY = HAL_PRIORITY_URGENT_DISPLAY,
    71.  
    72. /** all normal audio threads */
    73. ANDROID_PRIORITY_AUDIO = -,
    74.  
    75. /** service audio threads (uncommon) */
    76. ANDROID_PRIORITY_URGENT_AUDIO = -,
    77.  
    78. /** should never be used in practice. regular process might not
    79. * be allowed to use this level */
    80. ANDROID_PRIORITY_HIGHEST = -,
    81.  
    82. ANDROID_PRIORITY_DEFAULT = ANDROID_PRIORITY_NORMAL,
    83. ANDROID_PRIORITY_MORE_FAVORABLE = -,
    84. ANDROID_PRIORITY_LESS_FAVORABLE = +,
    85. };
    86.  
    87. enum {
    88. ANDROID_TGROUP_DEFAULT = ,
    89. ANDROID_TGROUP_BG_NONINTERACT = ,
    90. ANDROID_TGROUP_FG_BOOST = ,
    91. ANDROID_TGROUP_MAX = ANDROID_TGROUP_FG_BOOST,
    92. };
    93.  
    94. // Create and run a new thread.
    95. extern int androidCreateThread(android_thread_func_t, void *);
    96.  
    97. // Create thread with lots of parameters
    98. extern int androidCreateThreadEtc(android_thread_func_t entryFunction,
    99. void *userData,
    100. const char* threadName,
    101. int32_t threadPriority,
    102. size_t threadStackSize,
    103. android_thread_id_t *threadId);
    104.  
    105. // Get some sort of unique identifier for the current thread.
    106. extern android_thread_id_t androidGetThreadId();
    107.  
    108. // Low-level thread creation -- never creates threads that can
    109. // interact with the Java VM.
    110. extern int androidCreateRawThreadEtc(android_thread_func_t entryFunction,
    111. void *userData,
    112. const char* threadName,
    113. int32_t threadPriority,
    114. size_t threadStackSize,
    115. android_thread_id_t *threadId);
    116.  
    117. // Used by the Java Runtime to control how threads are created, so that
    118. // they can be proper and lovely Java threads.
    119. typedef int (*android_create_thread_fn)(android_thread_func_t entryFunction,
    120. void *userData,
    121. const char* threadName,
    122. int32_t threadPriority,
    123. size_t threadStackSize,
    124. android_thread_id_t *threadId);
    125.  
    126. extern void androidSetCreateThreadFunc(android_create_thread_fn func);
    127.  
    128. // ------------------------------------------------------------------
    129. // Extra functions working with raw pids.
    130.  
    131. // Get pid for the current thread.
    132. extern pid_t androidGetTid();
    133.  
    134. // Change the scheduling group of a particular thread. The group
    135. // should be one of the ANDROID_TGROUP constants. Returns BAD_VALUE if
    136. // grp is out of range, else another non-zero value with errno set if
    137. // the operation failed. Thread ID zero means current thread.
    138. extern int androidSetThreadSchedulingGroup(pid_t tid, int grp);
    139.  
    140. // Change the priority AND scheduling group of a particular thread. The priority
    141. // should be one of the ANDROID_PRIORITY constants. Returns INVALID_OPERATION
    142. // if the priority set failed, else another value if just the group set failed;
    143. // in either case errno is set. Thread ID zero means current thread.
    144. extern int androidSetThreadPriority(pid_t tid, int prio);
    145.  
    146. // Get the current priority of a particular thread. Returns one of the
    147. // ANDROID_PRIORITY constants or a negative result in case of error.
    148. extern int androidGetThreadPriority(pid_t tid);
    149.  
    150. // Get the current scheduling group of a particular thread. Normally returns
    151. // one of the ANDROID_TGROUP constants other than ANDROID_TGROUP_DEFAULT.
    152. // Returns ANDROID_TGROUP_DEFAULT if no pthread support (e.g. on host) or if
    153. // scheduling groups are disabled. Returns INVALID_OPERATION if unexpected error.
    154. // Thread ID zero means current thread.
    155. extern int androidGetThreadSchedulingGroup(pid_t tid);
    156.  
    157. #ifdef __cplusplus
    158. }
    159. #endif
    160.  
    161. // ------------------------------------------------------------------
    162. // C++ API
    163.  
    164. #ifdef __cplusplus
    165.  
    166. #include <utils/Errors.h>
    167. #include <utils/RefBase.h>
    168. #include <utils/Timers.h>
    169.  
    170. namespace android {
    171.  
    172. typedef android_thread_id_t thread_id_t;
    173.  
    174. typedef android_thread_func_t thread_func_t;
    175.  
    176. enum {
    177. PRIORITY_LOWEST = ANDROID_PRIORITY_LOWEST,
    178. PRIORITY_BACKGROUND = ANDROID_PRIORITY_BACKGROUND,
    179. PRIORITY_NORMAL = ANDROID_PRIORITY_NORMAL,
    180. PRIORITY_FOREGROUND = ANDROID_PRIORITY_FOREGROUND,
    181. PRIORITY_DISPLAY = ANDROID_PRIORITY_DISPLAY,
    182. PRIORITY_URGENT_DISPLAY = ANDROID_PRIORITY_URGENT_DISPLAY,
    183. PRIORITY_AUDIO = ANDROID_PRIORITY_AUDIO,
    184. PRIORITY_URGENT_AUDIO = ANDROID_PRIORITY_URGENT_AUDIO,
    185. PRIORITY_HIGHEST = ANDROID_PRIORITY_HIGHEST,
    186. PRIORITY_DEFAULT = ANDROID_PRIORITY_DEFAULT,
    187. PRIORITY_MORE_FAVORABLE = ANDROID_PRIORITY_MORE_FAVORABLE,
    188. PRIORITY_LESS_FAVORABLE = ANDROID_PRIORITY_LESS_FAVORABLE,
    189. };
    190.  
    191. // Create and run a new thread.
    192. inline bool createThread(thread_func_t f, void *a) {
    193. return androidCreateThread(f, a) ? true : false;
    194. }
    195.  
    196. // Create thread with lots of parameters
    197. inline bool createThreadEtc(thread_func_t entryFunction,
    198. void *userData,
    199. const char* threadName = "android:unnamed_thread",
    200. int32_t threadPriority = PRIORITY_DEFAULT,
    201. size_t threadStackSize = ,
    202. thread_id_t *threadId = )
    203. {
    204. return androidCreateThreadEtc(entryFunction, userData, threadName,
    205. threadPriority, threadStackSize, threadId) ? true : false;
    206. }
    207.  
    208. // Get some sort of unique identifier for the current thread.
    209. inline thread_id_t getThreadId() {
    210. return androidGetThreadId();
    211. }
    212.  
    213. /******************************************************************************/
    214.  
    215. /**
    216. * Simple mutex class. The implementation is system-dependent.
    217. *
    218. * The mutex must be unlocked by the thread that locked it. They are not
    219. * recursive, i.e. the same thread can't lock it multiple times.
    220. */
    221. class Mutex {
    222. public:
    223. enum {
    224. PRIVATE = ,
    225. SHARED =
    226. };
    227.  
    228. Mutex();
    229. Mutex(const char* name);
    230. Mutex(int type, const char* name = NULL);
    231. ~Mutex();
    232.  
    233. // lock or unlock the mutex
    234. status_t lock();
    235. void unlock();
    236.  
    237. // lock if possible; returns 0 on success, error otherwise
    238. status_t tryLock();
    239.  
    240. // Manages the mutex automatically. It'll be locked when Autolock is
    241. // constructed and released when Autolock goes out of scope.
    242. class Autolock {
    243. public:
    244. inline Autolock(Mutex& mutex) : mLock(mutex) { mLock.lock(); }
    245. inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); }
    246. inline ~Autolock() { mLock.unlock(); }
    247. private:
    248. Mutex& mLock;
    249. };
    250.  
    251. private:
    252. friend class Condition;
    253.  
    254. // A mutex cannot be copied
    255. Mutex(const Mutex&);
    256. Mutex& operator = (const Mutex&);
    257.  
    258. #if defined(HAVE_PTHREADS)
    259. pthread_mutex_t mMutex;
    260. #else
    261. void _init();
    262. void* mState;
    263. #endif
    264. };
    265.  
    266. #if defined(HAVE_PTHREADS)
    267.  
    268. inline Mutex::Mutex() {
    269. pthread_mutex_init(&mMutex, NULL);
    270. }
    271. inline Mutex::Mutex(const char* name) {
    272. pthread_mutex_init(&mMutex, NULL);
    273. }
    274. inline Mutex::Mutex(int type, const char* name) {
    275. if (type == SHARED) {
    276. pthread_mutexattr_t attr;
    277. pthread_mutexattr_init(&attr);
    278. pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
    279. pthread_mutex_init(&mMutex, &attr);
    280. pthread_mutexattr_destroy(&attr);
    281. } else {
    282. pthread_mutex_init(&mMutex, NULL);
    283. }
    284. }
    285. inline Mutex::~Mutex() {
    286. pthread_mutex_destroy(&mMutex);
    287. }
    288. inline status_t Mutex::lock() {
    289. return -pthread_mutex_lock(&mMutex);
    290. }
    291. inline void Mutex::unlock() {
    292. pthread_mutex_unlock(&mMutex);
    293. }
    294. inline status_t Mutex::tryLock() {
    295. return -pthread_mutex_trylock(&mMutex);
    296. }
    297.  
    298. #endif // HAVE_PTHREADS
    299.  
    300. /**
    301. * Automatic mutex. Declare one of these at the top of a function.
    302. * When the function returns, it will go out of scope, and release the
    303. * mutex.
    304. */
    305.  
    306. typedef Mutex::Autolock AutoMutex;
    307.  
    308. /******************************************************************************/
    309.  
    310. #if defined(HAVE_PTHREADS)
    311.  
    312. /**
    313. * Simple mutex class. The implementation is system-dependent.
    314. *
    315. * The mutex must be unlocked by the thread that locked it. They are not
    316. * recursive, i.e. the same thread can't lock it multiple times.
    317. */
    318. class RWLock {
    319. public:
    320. enum {
    321. PRIVATE = ,
    322. SHARED =
    323. };
    324.  
    325. RWLock();
    326. RWLock(const char* name);
    327. RWLock(int type, const char* name = NULL);
    328. ~RWLock();
    329.  
    330. status_t readLock();
    331. status_t tryReadLock();
    332. status_t writeLock();
    333. status_t tryWriteLock();
    334. void unlock();
    335.  
    336. class AutoRLock {
    337. public:
    338. inline AutoRLock(RWLock& rwlock) : mLock(rwlock) { mLock.readLock(); }
    339. inline ~AutoRLock() { mLock.unlock(); }
    340. private:
    341. RWLock& mLock;
    342. };
    343.  
    344. class AutoWLock {
    345. public:
    346. inline AutoWLock(RWLock& rwlock) : mLock(rwlock) { mLock.writeLock(); }
    347. inline ~AutoWLock() { mLock.unlock(); }
    348. private:
    349. RWLock& mLock;
    350. };
    351.  
    352. private:
    353. // A RWLock cannot be copied
    354. RWLock(const RWLock&);
    355. RWLock& operator = (const RWLock&);
    356.  
    357. pthread_rwlock_t mRWLock;
    358. };
    359.  
    360. inline RWLock::RWLock() {
    361. pthread_rwlock_init(&mRWLock, NULL);
    362. }
    363. inline RWLock::RWLock(const char* name) {
    364. pthread_rwlock_init(&mRWLock, NULL);
    365. }
    366. inline RWLock::RWLock(int type, const char* name) {
    367. if (type == SHARED) {
    368. pthread_rwlockattr_t attr;
    369. pthread_rwlockattr_init(&attr);
    370. pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
    371. pthread_rwlock_init(&mRWLock, &attr);
    372. pthread_rwlockattr_destroy(&attr);
    373. } else {
    374. pthread_rwlock_init(&mRWLock, NULL);
    375. }
    376. }
    377. inline RWLock::~RWLock() {
    378. pthread_rwlock_destroy(&mRWLock);
    379. }
    380. inline status_t RWLock::readLock() {
    381. return -pthread_rwlock_rdlock(&mRWLock);
    382. }
    383. inline status_t RWLock::tryReadLock() {
    384. return -pthread_rwlock_tryrdlock(&mRWLock);
    385. }
    386. inline status_t RWLock::writeLock() {
    387. return -pthread_rwlock_wrlock(&mRWLock);
    388. }
    389. inline status_t RWLock::tryWriteLock() {
    390. return -pthread_rwlock_trywrlock(&mRWLock);
    391. }
    392. inline void RWLock::unlock() {
    393. pthread_rwlock_unlock(&mRWLock);
    394. }
    395.  
    396. #endif // HAVE_PTHREADS
    397.  
    398. /******************************************************************************/
    399.  
    400. /**
    401. * Condition variable class. The implementation is system-dependent.
    402. *
    403. * Condition variables are paired up with mutexes. Lock the mutex,
    404. * call wait(), then either re-wait() if things aren't quite what you want,
    405. * or unlock the mutex and continue. All threads calling wait() must
    406. * use the same mutex for a given Condition.
    407. */
    408. class Condition {
    409. public:
    410. enum {
    411. PRIVATE = ,
    412. SHARED =
    413. };
    414.  
    415. Condition();
    416. Condition(int type);
    417. ~Condition();
    418. // Wait on the condition variable. Lock the mutex before calling.
    419. status_t wait(Mutex& mutex);
    420. // same with relative timeout
    421. status_t waitRelative(Mutex& mutex, nsecs_t reltime);
    422. // Signal the condition variable, allowing one thread to continue.
    423. void signal();
    424. // Signal the condition variable, allowing all threads to continue.
    425. void broadcast();
    426.  
    427. private:
    428. #if defined(HAVE_PTHREADS)
    429. pthread_cond_t mCond;
    430. #else
    431. void* mState;
    432. #endif
    433. };
    434.  
    435. #if defined(HAVE_PTHREADS)
    436.  
    437. inline Condition::Condition() {
    438. pthread_cond_init(&mCond, NULL);
    439. }
    440. inline Condition::Condition(int type) {
    441. if (type == SHARED) {
    442. pthread_condattr_t attr;
    443. pthread_condattr_init(&attr);
    444. pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
    445. pthread_cond_init(&mCond, &attr);
    446. pthread_condattr_destroy(&attr);
    447. } else {
    448. pthread_cond_init(&mCond, NULL);
    449. }
    450. }
    451. inline Condition::~Condition() {
    452. pthread_cond_destroy(&mCond);
    453. }
    454. inline status_t Condition::wait(Mutex& mutex) {
    455. return -pthread_cond_wait(&mCond, &mutex.mMutex);
    456. }
    457. inline status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime) {
    458. #if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE)
    459. struct timespec ts;
    460. ts.tv_sec = reltime/;
    461. ts.tv_nsec = reltime%;
    462. return -pthread_cond_timedwait_relative_np(&mCond, &mutex.mMutex, &ts);
    463. #else // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
    464. struct timespec ts;
    465. #if defined(HAVE_POSIX_CLOCKS)
    466. clock_gettime(CLOCK_REALTIME, &ts);
    467. #else // HAVE_POSIX_CLOCKS
    468. // we don't support the clocks here.
    469. struct timeval t;
    470. gettimeofday(&t, NULL);
    471. ts.tv_sec = t.tv_sec;
    472. ts.tv_nsec= t.tv_usec*;
    473. #endif // HAVE_POSIX_CLOCKS
    474. ts.tv_sec += reltime/;
    475. ts.tv_nsec+= reltime%;
    476. if (ts.tv_nsec >= ) {
    477. ts.tv_nsec -= ;
    478. ts.tv_sec += ;
    479. }
    480. return -pthread_cond_timedwait(&mCond, &mutex.mMutex, &ts);
    481. #endif // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
    482. }
    483. inline void Condition::signal() {
    484. pthread_cond_signal(&mCond);
    485. }
    486. inline void Condition::broadcast() {
    487. pthread_cond_broadcast(&mCond);
    488. }
    489.  
    490. #endif // HAVE_PTHREADS
    491.  
    492. /******************************************************************************/
    493.  
    494. /**
    495. * This is our spiffy thread object!
    496. */
    497.  
    498. class Thread : virtual public RefBase
    499. {
    500. public:
    501. // Create a Thread object, but doesn't create or start the associated
    502. // thread. See the run() method.
    503. Thread(bool canCallJava = true);
    504. virtual ~Thread();
    505.  
    506. // Start the thread in threadLoop() which needs to be implemented.
    507. virtual status_t run( const char* name = ,
    508. int32_t priority = PRIORITY_DEFAULT,
    509. size_t stack = );
    510.  
    511. // Ask this object's thread to exit. This function is asynchronous, when the
    512. // function returns the thread might still be running. Of course, this
    513. // function can be called from a different thread.
    514. virtual void requestExit();
    515.  
    516. // Good place to do one-time initializations
    517. virtual status_t readyToRun();
    518.  
    519. // Call requestExit() and wait until this object's thread exits.
    520. // BE VERY CAREFUL of deadlocks. In particular, it would be silly to call
    521. // this function from this object's thread. Will return WOULD_BLOCK in
    522. // that case.
    523. status_t requestExitAndWait();
    524.  
    525. // Wait until this object's thread exits. Returns immediately if not yet running.
    526. // Do not call from this object's thread; will return WOULD_BLOCK in that case.
    527. status_t join();
    528.  
    529. protected:
    530. // exitPending() returns true if requestExit() has been called.
    531. bool exitPending() const;
    532.  
    533. private:
    534. // Derived class must implement threadLoop(). The thread starts its life
    535. // here. There are two ways of using the Thread object:
    536. // 1) loop: if threadLoop() returns true, it will be called again if
    537. // requestExit() wasn't called.
    538. // 2) once: if threadLoop() returns false, the thread will exit upon return.
    539. virtual bool threadLoop() = ;
    540.  
    541. private:
    542. Thread& operator=(const Thread&);
    543. static int _threadLoop(void* user);
    544. const bool mCanCallJava;
    545. // always hold mLock when reading or writing
    546. thread_id_t mThread;
    547. mutable Mutex mLock;
    548. Condition mThreadExitedCondition;
    549. status_t mStatus;
    550. // note that all accesses of mExitPending and mRunning need to hold mLock
    551. volatile bool mExitPending;
    552. volatile bool mRunning;
    553. sp<Thread> mHoldSelf;
    554. #if HAVE_ANDROID_OS
    555. int mTid;
    556. #endif
    557. };
    558.  
    559. }; // namespace android
    560.  
    561. #endif // __cplusplus
    562.  
    563. #endif // _LIBS_UTILS_THREADS_H

    threads.h

    1. /**
    2. * Copyright (C) 2007 The Android Open Source Project
    3. *
    4. * Licensed under the Apache License, Version 2.0 (the "License");
    5. * you may not use this file except in compliance with the License.
    6. * You may obtain a copy of the License at
    7. *
    8. * http://www.apache.org/licenses/LICENSE-2.0
    9. *
    10. * Unless required by applicable law or agreed to in writing, software
    11. * distributed under the License is distributed on an "AS IS" BASIS,
    12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13. * See the License for the specific language governing permissions and
    14. * limitations under the License.
    15. */
    16.  
    17. // #define LOG_NDEBUG 0
    18. #define LOG_TAG "libutils.threads"
    19.  
    20. #include <utils/threads.h>
    21. #include <utils/Log.h>
    22.  
    23. #include <cutils/sched_policy.h>
    24. #include <cutils/properties.h>
    25.  
    26. #include <stdio.h>
    27. #include <stdlib.h>
    28. #include <memory.h>
    29. #include <errno.h>
    30. #include <assert.h>
    31. #include <unistd.h>
    32.  
    33. #if defined(HAVE_PTHREADS)
    34. # include <pthread.h>
    35. # include <sched.h>
    36. # include <sys/resource.h>
    37. #elif defined(HAVE_WIN32_THREADS)
    38. # include <windows.h>
    39. # include <stdint.h>
    40. # include <process.h>
    41. # define HAVE_CREATETHREAD // Cygwin, vs. HAVE__BEGINTHREADEX for MinGW
    42. #endif
    43.  
    44. #if defined(HAVE_PRCTL)
    45. #include <sys/prctl.h>
    46. #endif
    47.  
    48. /**
    49. * ===========================================================================
    50. * Thread wrappers
    51. * ===========================================================================
    52. */
    53.  
    54. using namespace android;
    55.  
    56. // ----------------------------------------------------------------------------
    57. #if defined(HAVE_PTHREADS)
    58. // ----------------------------------------------------------------------------
    59.  
    60. /**
    61. * Create and run a new thread.
    62. *
    63. * We create it "detached", so it cleans up after itself.
    64. */
    65.  
    66. typedef void* (*android_pthread_entry)(void*);
    67.  
    68. static pthread_once_t gDoSchedulingGroupOnce = PTHREAD_ONCE_INIT;
    69. static bool gDoSchedulingGroup = true;
    70.  
    71. static void checkDoSchedulingGroup(void) {
    72. char buf[PROPERTY_VALUE_MAX];
    73. int len = property_get("debug.sys.noschedgroups", buf, "");
    74. if (len > ) {
    75. int temp;
    76. if (sscanf(buf, "%d", &temp) == ) {
    77. gDoSchedulingGroup = temp == ;
    78. }
    79. }
    80. }
    81.  
    82. struct thread_data_t {
    83. thread_func_t entryFunction;
    84. void* userData;
    85. int priority;
    86. char * threadName;
    87.  
    88. // we use this trampoline when we need to set the priority with
    89. // nice/setpriority.
    90. static int trampoline(const thread_data_t* t) {
    91. thread_func_t f = t->entryFunction;
    92. void* u = t->userData;
    93. int prio = t->priority;
    94. char * name = t->threadName;
    95. delete t;
    96. setpriority(PRIO_PROCESS, , prio);
    97. pthread_once(&gDoSchedulingGroupOnce, checkDoSchedulingGroup);
    98. if (gDoSchedulingGroup) {
    99. if (prio >= ANDROID_PRIORITY_BACKGROUND) {
    100. set_sched_policy(androidGetTid(), SP_BACKGROUND);
    101. } else {
    102. set_sched_policy(androidGetTid(), SP_FOREGROUND);
    103. }
    104. }
    105.  
    106. if (name) {
    107. #if defined(HAVE_PRCTL)
    108. // Mac OS doesn't have this, and we build libutil for the host too
    109. int hasAt = ;
    110. int hasDot = ;
    111. char *s = name;
    112. while (*s) {
    113. if (*s == '.') hasDot = ;
    114. else if (*s == '@') hasAt = ;
    115. s++;
    116. }
    117. int len = s - name;
    118. if (len < || hasAt || !hasDot) {
    119. s = name;
    120. } else {
    121. s = name + len - ;
    122. }
    123. prctl(PR_SET_NAME, (unsigned long) s, , , );
    124. #endif
    125. free(name);
    126. }
    127. return f(u);
    128. }
    129. };
    130.  
    131. int androidCreateRawThreadEtc(android_thread_func_t entryFunction,
    132. void *userData,
    133. const char* threadName,
    134. int32_t threadPriority,
    135. size_t threadStackSize,
    136. android_thread_id_t *threadId)
    137. {
    138. pthread_attr_t attr;
    139. pthread_attr_init(&attr);
    140. pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    141.  
    142. #ifdef HAVE_ANDROID_OS /** valgrind is rejecting RT-priority create reqs */
    143. if (threadPriority != PRIORITY_DEFAULT || threadName != NULL) {
    144. // We could avoid the trampoline if there was a way to get to the
    145. // android_thread_id_t (pid) from pthread_t
    146. thread_data_t* t = new thread_data_t;
    147. t->priority = threadPriority;
    148. t->threadName = threadName ? strdup(threadName) : NULL;
    149. t->entryFunction = entryFunction;
    150. t->userData = userData;
    151. entryFunction = (android_thread_func_t)&thread_data_t::trampoline;
    152. userData = t;
    153. }
    154. #endif
    155.  
    156. if (threadStackSize) {
    157. pthread_attr_setstacksize(&attr, threadStackSize);
    158. }
    159.  
    160. errno = ;
    161. pthread_t thread;
    162. int result = pthread_create(&thread, &attr,
    163. (android_pthread_entry)entryFunction, userData);
    164. pthread_attr_destroy(&attr);
    165. if (result != ) {
    166. LOGE("androidCreateRawThreadEtc failed (entry=%p, res=%d, errno=%d)\n"
    167. "(android threadPriority=%d)",
    168. entryFunction, result, errno, threadPriority);
    169. return ;
    170. }
    171.  
    172. // Note that *threadID is directly available to the parent only, as it is
    173. // assigned after the child starts. Use memory barrier / lock if the child
    174. // or other threads also need access.
    175. if (threadId != NULL) {
    176. *threadId = (android_thread_id_t)thread; // XXX: this is not portable
    177. }
    178. return ;
    179. }
    180.  
    181. android_thread_id_t androidGetThreadId()
    182. {
    183. return (android_thread_id_t)pthread_self();
    184. }
    185.  
    186. // ----------------------------------------------------------------------------
    187. #elif defined(HAVE_WIN32_THREADS)
    188. // ----------------------------------------------------------------------------
    189.  
    190. /**
    191. * Trampoline to make us __stdcall-compliant.
    192. *
    193. * We're expected to delete "vDetails" when we're done.
    194. */
    195. struct threadDetails {
    196. int (*func)(void*);
    197. void* arg;
    198. };
    199. static __stdcall unsigned int threadIntermediary(void* vDetails)
    200. {
    201. struct threadDetails* pDetails = (struct threadDetails*) vDetails;
    202. int result;
    203.  
    204. result = (*(pDetails->func))(pDetails->arg);
    205.  
    206. delete pDetails;
    207.  
    208. LOG(LOG_VERBOSE, "thread", "thread exiting\n");
    209. return (unsigned int) result;
    210. }
    211.  
    212. /**
    213. * Create and run a new thread.
    214. */
    215. static bool doCreateThread(android_thread_func_t fn, void* arg, android_thread_id_t *id)
    216. {
    217. HANDLE hThread;
    218. struct threadDetails* pDetails = new threadDetails; // must be on heap
    219. unsigned int thrdaddr;
    220.  
    221. pDetails->func = fn;
    222. pDetails->arg = arg;
    223.  
    224. #if defined(HAVE__BEGINTHREADEX)
    225. hThread = (HANDLE) _beginthreadex(NULL, , threadIntermediary, pDetails, ,
    226. &thrdaddr);
    227. if (hThread == )
    228. #elif defined(HAVE_CREATETHREAD)
    229. hThread = CreateThread(NULL, ,
    230. (LPTHREAD_START_ROUTINE) threadIntermediary,
    231. (void*) pDetails, , (DWORD*) &thrdaddr);
    232. if (hThread == NULL)
    233. #endif
    234. {
    235. LOG(LOG_WARN, "thread", "WARNING: thread create failed\n");
    236. return false;
    237. }
    238.  
    239. #if defined(HAVE_CREATETHREAD)
    240. /** close the management handle */
    241. CloseHandle(hThread);
    242. #endif
    243.  
    244. if (id != NULL) {
    245. *id = (android_thread_id_t)thrdaddr;
    246. }
    247.  
    248. return true;
    249. }
    250.  
    251. int androidCreateRawThreadEtc(android_thread_func_t fn,
    252. void *userData,
    253. const char* threadName,
    254. int32_t threadPriority,
    255. size_t threadStackSize,
    256. android_thread_id_t *threadId)
    257. {
    258. return doCreateThread( fn, userData, threadId);
    259. }
    260.  
    261. android_thread_id_t androidGetThreadId()
    262. {
    263. return (android_thread_id_t)GetCurrentThreadId();
    264. }
    265.  
    266. // ----------------------------------------------------------------------------
    267. #else
    268. #error "Threads not supported"
    269. #endif
    270.  
    271. // ----------------------------------------------------------------------------
    272.  
    273. int androidCreateThread(android_thread_func_t fn, void* arg)
    274. {
    275. return createThreadEtc(fn, arg);
    276. }
    277.  
    278. int androidCreateThreadGetID(android_thread_func_t fn, void *arg, android_thread_id_t *id)
    279. {
    280. return createThreadEtc(fn, arg, "android:unnamed_thread",
    281. PRIORITY_DEFAULT, , id);
    282. }
    283.  
    284. static android_create_thread_fn gCreateThreadFn = androidCreateRawThreadEtc;
    285.  
    286. int androidCreateThreadEtc(android_thread_func_t entryFunction,
    287. void *userData,
    288. const char* threadName,
    289. int32_t threadPriority,
    290. size_t threadStackSize,
    291. android_thread_id_t *threadId)
    292. {
    293. return gCreateThreadFn(entryFunction, userData, threadName,
    294. threadPriority, threadStackSize, threadId);
    295. }
    296.  
    297. void androidSetCreateThreadFunc(android_create_thread_fn func)
    298. {
    299. gCreateThreadFn = func;
    300. }
    301.  
    302. pid_t androidGetTid()
    303. {
    304. #ifdef HAVE_GETTID
    305. return gettid();
    306. #else
    307. return getpid();
    308. #endif
    309. }
    310.  
    311. int androidSetThreadSchedulingGroup(pid_t tid, int grp)
    312. {
    313. if (grp > ANDROID_TGROUP_MAX || grp < ) {
    314. return BAD_VALUE;
    315. }
    316.  
    317. #if defined(HAVE_PTHREADS)
    318. pthread_once(&gDoSchedulingGroupOnce, checkDoSchedulingGroup);
    319. if (gDoSchedulingGroup) {
    320. // set_sched_policy does not support tid == 0
    321. if (tid == ) {
    322. tid = androidGetTid();
    323. }
    324. if (set_sched_policy(tid, (grp == ANDROID_TGROUP_BG_NONINTERACT) ?
    325. SP_BACKGROUND : SP_FOREGROUND)) {
    326. return PERMISSION_DENIED;
    327. }
    328. }
    329. #endif
    330.  
    331. return NO_ERROR;
    332. }
    333.  
    334. int androidSetThreadPriority(pid_t tid, int pri)
    335. {
    336. int rc = ;
    337.  
    338. #if defined(HAVE_PTHREADS)
    339. int lasterr = ;
    340.  
    341. pthread_once(&gDoSchedulingGroupOnce, checkDoSchedulingGroup);
    342. if (gDoSchedulingGroup) {
    343. // set_sched_policy does not support tid == 0
    344. int policy_tid;
    345. if (tid == ) {
    346. policy_tid = androidGetTid();
    347. } else {
    348. policy_tid = tid;
    349. }
    350. if (pri >= ANDROID_PRIORITY_BACKGROUND) {
    351. rc = set_sched_policy(policy_tid, SP_BACKGROUND);
    352. } else if (getpriority(PRIO_PROCESS, tid) >= ANDROID_PRIORITY_BACKGROUND) {
    353. rc = set_sched_policy(policy_tid, SP_FOREGROUND);
    354. }
    355. }
    356.  
    357. if (rc) {
    358. lasterr = errno;
    359. }
    360.  
    361. if (setpriority(PRIO_PROCESS, tid, pri) < ) {
    362. rc = INVALID_OPERATION;
    363. } else {
    364. errno = lasterr;
    365. }
    366. #endif
    367.  
    368. return rc;
    369. }
    370.  
    371. int androidGetThreadPriority(pid_t tid) {
    372. #if defined(HAVE_PTHREADS)
    373. return getpriority(PRIO_PROCESS, tid);
    374. #else
    375. return ANDROID_PRIORITY_NORMAL;
    376. #endif
    377. }
    378.  
    379. int androidGetThreadSchedulingGroup(pid_t tid)
    380. {
    381. int ret = ANDROID_TGROUP_DEFAULT;
    382.  
    383. #if defined(HAVE_PTHREADS)
    384. // convention is to not call get/set_sched_policy methods if disabled by property
    385. pthread_once(&gDoSchedulingGroupOnce, checkDoSchedulingGroup);
    386. if (gDoSchedulingGroup) {
    387. SchedPolicy policy;
    388. // get_sched_policy does not support tid == 0
    389. if (tid == ) {
    390. tid = androidGetTid();
    391. }
    392. if (get_sched_policy(tid, &policy) < ) {
    393. ret = INVALID_OPERATION;
    394. } else {
    395. switch (policy) {
    396. case SP_BACKGROUND:
    397. ret = ANDROID_TGROUP_BG_NONINTERACT;
    398. break;
    399. case SP_FOREGROUND:
    400. ret = ANDROID_TGROUP_FG_BOOST;
    401. break;
    402. default:
    403. // should not happen, as enum SchedPolicy does not have any other values
    404. ret = INVALID_OPERATION;
    405. break;
    406. }
    407. }
    408. }
    409. #endif
    410.  
    411. return ret;
    412. }
    413.  
    414. namespace android {
    415.  
    416. /**
    417. * ===========================================================================
    418. * Mutex class
    419. * ===========================================================================
    420. */
    421.  
    422. #if defined(HAVE_PTHREADS)
    423. // implemented as inlines in threads.h
    424. #elif defined(HAVE_WIN32_THREADS)
    425.  
    426. Mutex::Mutex()
    427. {
    428. HANDLE hMutex;
    429.  
    430. assert(sizeof(hMutex) == sizeof(mState));
    431.  
    432. hMutex = CreateMutex(NULL, FALSE, NULL);
    433. mState = (void*) hMutex;
    434. }
    435.  
    436. Mutex::Mutex(const char* name)
    437. {
    438. // XXX: name not used for now
    439. HANDLE hMutex;
    440.  
    441. assert(sizeof(hMutex) == sizeof(mState));
    442.  
    443. hMutex = CreateMutex(NULL, FALSE, NULL);
    444. mState = (void*) hMutex;
    445. }
    446.  
    447. Mutex::Mutex(int type, const char* name)
    448. {
    449. // XXX: type and name not used for now
    450. HANDLE hMutex;
    451.  
    452. assert(sizeof(hMutex) == sizeof(mState));
    453.  
    454. hMutex = CreateMutex(NULL, FALSE, NULL);
    455. mState = (void*) hMutex;
    456. }
    457.  
    458. Mutex::~Mutex()
    459. {
    460. CloseHandle((HANDLE) mState);
    461. }
    462.  
    463. status_t Mutex::lock()
    464. {
    465. DWORD dwWaitResult;
    466. dwWaitResult = WaitForSingleObject((HANDLE) mState, INFINITE);
    467. return dwWaitResult != WAIT_OBJECT_0 ? - : NO_ERROR;
    468. }
    469.  
    470. void Mutex::unlock()
    471. {
    472. if (!ReleaseMutex((HANDLE) mState))
    473. LOG(LOG_WARN, "thread", "WARNING: bad result from unlocking mutex\n");
    474. }
    475.  
    476. status_t Mutex::tryLock()
    477. {
    478. DWORD dwWaitResult;
    479.  
    480. dwWaitResult = WaitForSingleObject((HANDLE) mState, );
    481. if (dwWaitResult != WAIT_OBJECT_0 && dwWaitResult != WAIT_TIMEOUT)
    482. LOG(LOG_WARN, "thread", "WARNING: bad result from try-locking mutex\n");
    483. return (dwWaitResult == WAIT_OBJECT_0) ? : -;
    484. }
    485.  
    486. #else
    487. #error "Somebody forgot to implement threads for this platform."
    488. #endif
    489.  
    490. /**
    491. * ===========================================================================
    492. * Condition class
    493. * ===========================================================================
    494. */
    495.  
    496. #if defined(HAVE_PTHREADS)
    497. // implemented as inlines in threads.h
    498. #elif defined(HAVE_WIN32_THREADS)
    499.  
    500. /**
    501. * Windows doesn't have a condition variable solution. It's possible
    502. * to create one, but it's easy to get it wrong. For a discussion, and
    503. * the origin of this implementation, see:
    504. *
    505. * http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
    506. *
    507. * The implementation shown on the page does NOT follow POSIX semantics.
    508. * As an optimization they require acquiring the external mutex before
    509. * calling signal() and broadcast(), whereas POSIX only requires grabbing
    510. * it before calling wait(). The implementation here has been un-optimized
    511. * to have the correct behavior.
    512. */
    513. typedef struct WinCondition {
    514. // Number of waiting threads.
    515. int waitersCount;
    516.  
    517. // Serialize access to waitersCount.
    518. CRITICAL_SECTION waitersCountLock;
    519.  
    520. // Semaphore used to queue up threads waiting for the condition to
    521. // become signaled.
    522. HANDLE sema;
    523.  
    524. // An auto-reset event used by the broadcast/signal thread to wait
    525. // for all the waiting thread(s) to wake up and be released from
    526. // the semaphore.
    527. HANDLE waitersDone;
    528.  
    529. // This mutex wouldn't be necessary if we required that the caller
    530. // lock the external mutex before calling signal() and broadcast().
    531. // I'm trying to mimic pthread semantics though.
    532. HANDLE internalMutex;
    533.  
    534. // Keeps track of whether we were broadcasting or signaling. This
    535. // allows us to optimize the code if we're just signaling.
    536. bool wasBroadcast;
    537.  
    538. status_t wait(WinCondition* condState, HANDLE hMutex, nsecs_t* abstime)
    539. {
    540. // Increment the wait count, avoiding race conditions.
    541. EnterCriticalSection(&condState->waitersCountLock);
    542. condState->waitersCount++;
    543. //printf("+++ wait: incr waitersCount to %d (tid=%ld)\n",
    544. // condState->waitersCount, getThreadId());
    545. LeaveCriticalSection(&condState->waitersCountLock);
    546.  
    547. DWORD timeout = INFINITE;
    548. if (abstime) {
    549. nsecs_t reltime = *abstime - systemTime();
    550. if (reltime < )
    551. reltime = ;
    552. timeout = reltime/;
    553. }
    554.  
    555. // Atomically release the external mutex and wait on the semaphore.
    556. DWORD res =
    557. SignalObjectAndWait(hMutex, condState->sema, timeout, FALSE);
    558.  
    559. //printf("+++ wait: awake (tid=%ld)\n", getThreadId());
    560.  
    561. // Reacquire lock to avoid race conditions.
    562. EnterCriticalSection(&condState->waitersCountLock);
    563.  
    564. // No longer waiting.
    565. condState->waitersCount--;
    566.  
    567. // Check to see if we're the last waiter after a broadcast.
    568. bool lastWaiter = (condState->wasBroadcast && condState->waitersCount == );
    569.  
    570. //printf("+++ wait: lastWaiter=%d (wasBc=%d wc=%d)\n",
    571. // lastWaiter, condState->wasBroadcast, condState->waitersCount);
    572.  
    573. LeaveCriticalSection(&condState->waitersCountLock);
    574.  
    575. // If we're the last waiter thread during this particular broadcast
    576. // then signal broadcast() that we're all awake. It'll drop the
    577. // internal mutex.
    578. if (lastWaiter) {
    579. // Atomically signal the "waitersDone" event and wait until we
    580. // can acquire the internal mutex. We want to do this in one step
    581. // because it ensures that everybody is in the mutex FIFO before
    582. // any thread has a chance to run. Without it, another thread
    583. // could wake up, do work, and hop back in ahead of us.
    584. SignalObjectAndWait(condState->waitersDone, condState->internalMutex,
    585. INFINITE, FALSE);
    586. } else {
    587. // Grab the internal mutex.
    588. WaitForSingleObject(condState->internalMutex, INFINITE);
    589. }
    590.  
    591. // Release the internal and grab the external.
    592. ReleaseMutex(condState->internalMutex);
    593. WaitForSingleObject(hMutex, INFINITE);
    594.  
    595. return res == WAIT_OBJECT_0 ? NO_ERROR : -;
    596. }
    597. } WinCondition;
    598.  
    599. /**
    600. * Constructor. Set up the WinCondition stuff.
    601. */
    602. Condition::Condition()
    603. {
    604. WinCondition* condState = new WinCondition;
    605.  
    606. condState->waitersCount = ;
    607. condState->wasBroadcast = false;
    608. // semaphore: no security, initial value of 0
    609. condState->sema = CreateSemaphore(NULL, , 0x7fffffff, NULL);
    610. InitializeCriticalSection(&condState->waitersCountLock);
    611. // auto-reset event, not signaled initially
    612. condState->waitersDone = CreateEvent(NULL, FALSE, FALSE, NULL);
    613. // used so we don't have to lock external mutex on signal/broadcast
    614. condState->internalMutex = CreateMutex(NULL, FALSE, NULL);
    615.  
    616. mState = condState;
    617. }
    618.  
    619. /**
    620. * Destructor. Free Windows resources as well as our allocated storage.
    621. */
    622. Condition::~Condition()
    623. {
    624. WinCondition* condState = (WinCondition*) mState;
    625. if (condState != NULL) {
    626. CloseHandle(condState->sema);
    627. CloseHandle(condState->waitersDone);
    628. delete condState;
    629. }
    630. }
    631.  
    632. status_t Condition::wait(Mutex& mutex)
    633. {
    634. WinCondition* condState = (WinCondition*) mState;
    635. HANDLE hMutex = (HANDLE) mutex.mState;
    636.  
    637. return ((WinCondition*)mState)->wait(condState, hMutex, NULL);
    638. }
    639.  
    640. status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime)
    641. {
    642. WinCondition* condState = (WinCondition*) mState;
    643. HANDLE hMutex = (HANDLE) mutex.mState;
    644. nsecs_t absTime = systemTime()+reltime;
    645.  
    646. return ((WinCondition*)mState)->wait(condState, hMutex, &absTime);
    647. }
    648.  
    649. /**
    650. * Signal the condition variable, allowing one thread to continue.
    651. */
    652. void Condition::signal()
    653. {
    654. WinCondition* condState = (WinCondition*) mState;
    655.  
    656. // Lock the internal mutex. This ensures that we don't clash with
    657. // broadcast().
    658. WaitForSingleObject(condState->internalMutex, INFINITE);
    659.  
    660. EnterCriticalSection(&condState->waitersCountLock);
    661. bool haveWaiters = (condState->waitersCount > );
    662. LeaveCriticalSection(&condState->waitersCountLock);
    663.  
    664. // If no waiters, then this is a no-op. Otherwise, knock the semaphore
    665. // down a notch.
    666. if (haveWaiters)
    667. ReleaseSemaphore(condState->sema, , );
    668.  
    669. // Release internal mutex.
    670. ReleaseMutex(condState->internalMutex);
    671. }
    672.  
    673. /**
    674. * Signal the condition variable, allowing all threads to continue.
    675. *
    676. * First we have to wake up all threads waiting on the semaphore, then
    677. * we wait until all of the threads have actually been woken before
    678. * releasing the internal mutex. This ensures that all threads are woken.
    679. */
    680. void Condition::broadcast()
    681. {
    682. WinCondition* condState = (WinCondition*) mState;
    683.  
    684. // Lock the internal mutex. This keeps the guys we're waking up
    685. // from getting too far.
    686. WaitForSingleObject(condState->internalMutex, INFINITE);
    687.  
    688. EnterCriticalSection(&condState->waitersCountLock);
    689. bool haveWaiters = false;
    690.  
    691. if (condState->waitersCount > ) {
    692. haveWaiters = true;
    693. condState->wasBroadcast = true;
    694. }
    695.  
    696. if (haveWaiters) {
    697. // Wake up all the waiters.
    698. ReleaseSemaphore(condState->sema, condState->waitersCount, );
    699.  
    700. LeaveCriticalSection(&condState->waitersCountLock);
    701.  
    702. // Wait for all awakened threads to acquire the counting semaphore.
    703. // The last guy who was waiting sets this.
    704. WaitForSingleObject(condState->waitersDone, INFINITE);
    705.  
    706. // Reset wasBroadcast. (No crit section needed because nobody
    707. // else can wake up to poke at it.)
    708. condState->wasBroadcast = ;
    709. } else {
    710. // nothing to do
    711. LeaveCriticalSection(&condState->waitersCountLock);
    712. }
    713.  
    714. // Release internal mutex.
    715. ReleaseMutex(condState->internalMutex);
    716. }
    717.  
    718. #else
    719. #error "condition variables not supported on this platform"
    720. #endif
    721.  
    722. // ----------------------------------------------------------------------------
    723.  
    724. /**
    725. * This is our thread object!
    726. */
    727.  
    728. Thread::Thread(bool canCallJava)
    729. : mCanCallJava(canCallJava),
    730. mThread(thread_id_t(-)),
    731. mLock("Thread::mLock"),
    732. mStatus(NO_ERROR),
    733. mExitPending(false), mRunning(false)
    734. #ifdef HAVE_ANDROID_OS
    735. , mTid(-)
    736. #endif
    737. {
    738. }
    739.  
    740. Thread::~Thread()
    741. {
    742. }
    743.  
    744. status_t Thread::readyToRun()
    745. {
    746. return NO_ERROR;
    747. }
    748.  
    749. status_t Thread::run(const char* name, int32_t priority, size_t stack)
    750. {
    751. Mutex::Autolock _l(mLock);
    752.  
    753. if (mRunning) {
    754. // thread already started
    755. return INVALID_OPERATION;
    756. }
    757.  
    758. // reset status and exitPending to their default value, so we can
    759. // try again after an error happened (either below, or in readyToRun())
    760. mStatus = NO_ERROR;
    761. mExitPending = false;
    762. mThread = thread_id_t(-);
    763.  
    764. // hold a strong reference on ourself
    765. mHoldSelf = this;
    766.  
    767. mRunning = true;
    768.  
    769. bool res;
    770. if (mCanCallJava) {
    771. res = createThreadEtc(_threadLoop,
    772. this, name, priority, stack, &mThread);
    773. } else {
    774. res = androidCreateRawThreadEtc(_threadLoop,
    775. this, name, priority, stack, &mThread);
    776. }
    777.  
    778. if (res == false) {
    779. mStatus = UNKNOWN_ERROR; // something happened!
    780. mRunning = false;
    781. mThread = thread_id_t(-);
    782. mHoldSelf.clear(); // "this" may have gone away after this.
    783.  
    784. return UNKNOWN_ERROR;
    785. }
    786.  
    787. // Do not refer to mStatus here: The thread is already running (may, in fact
    788. // already have exited with a valid mStatus result). The NO_ERROR indication
    789. // here merely indicates successfully starting the thread and does not
    790. // imply successful termination/execution.
    791. return NO_ERROR;
    792.  
    793. // Exiting scope of mLock is a memory barrier and allows new thread to run
    794. }
    795.  
    796. int Thread::_threadLoop(void* user)
    797. {
    798. Thread* const self = static_cast<Thread*>(user);
    799.  
    800. sp<Thread> strong(self->mHoldSelf);
    801. wp<Thread> weak(strong);
    802. self->mHoldSelf.clear();
    803.  
    804. #ifdef HAVE_ANDROID_OS
    805. // this is very useful for debugging with gdb
    806. self->mTid = gettid();
    807. #endif
    808.  
    809. bool first = true;
    810.  
    811. do {
    812. bool result;
    813. if (first) {
    814. first = false;
    815. self->mStatus = self->readyToRun();
    816. result = (self->mStatus == NO_ERROR);
    817.  
    818. if (result && !self->exitPending()) {
    819. // Binder threads (and maybe others) rely on threadLoop
    820. // running at least once after a successful ::readyToRun()
    821. // (unless, of course, the thread has already been asked to exit
    822. // at that point).
    823. // This is because threads are essentially used like this:
    824. // (new ThreadSubclass())->run();
    825. // The caller therefore does not retain a strong reference to
    826. // the thread and the thread would simply disappear after the
    827. // successful ::readyToRun() call instead of entering the
    828. // threadLoop at least once.
    829. result = self->threadLoop();
    830. }
    831. } else {
    832. result = self->threadLoop();
    833. }
    834.  
    835. // establish a scope for mLock
    836. {
    837. Mutex::Autolock _l(self->mLock);
    838. if (result == false || self->mExitPending) {
    839. self->mExitPending = true;
    840. self->mRunning = false;
    841. // clear thread ID so that requestExitAndWait() does not exit if
    842. // called by a new thread using the same thread ID as this one.
    843. self->mThread = thread_id_t(-);
    844. // note that interested observers blocked in requestExitAndWait are
    845. // awoken by broadcast, but blocked on mLock until break exits scope
    846. self->mThreadExitedCondition.broadcast();
    847. break;
    848. }
    849. }
    850.  
    851. // Release our strong reference, to let a chance to the thread
    852. // to die a peaceful death.
    853. strong.clear();
    854. // And immediately, re-acquire a strong reference for the next loop
    855. strong = weak.promote();
    856. } while(strong != );
    857.  
    858. return ;
    859. }
    860.  
    861. void Thread::requestExit()
    862. {
    863. Mutex::Autolock _l(mLock);
    864. mExitPending = true;
    865. }
    866.  
    867. status_t Thread::requestExitAndWait()
    868. {
    869. Mutex::Autolock _l(mLock);
    870. if (mThread == getThreadId()) {
    871. LOGW(
    872. "Thread (this=%p): don't call waitForExit() from this "
    873. "Thread object's thread. It's a guaranteed deadlock!",
    874. this);
    875.  
    876. return WOULD_BLOCK;
    877. }
    878.  
    879. mExitPending = true;
    880.  
    881. while (mRunning == true) {
    882. mThreadExitedCondition.wait(mLock);
    883. }
    884. // This next line is probably not needed any more, but is being left for
    885. // historical reference. Note that each interested party will clear flag.
    886. mExitPending = false;
    887.  
    888. return mStatus;
    889. }
    890.  
    891. status_t Thread::join()
    892. {
    893. Mutex::Autolock _l(mLock);
    894. if (mThread == getThreadId()) {
    895. LOGW(
    896. "Thread (this=%p): don't call join() from this "
    897. "Thread object's thread. It's a guaranteed deadlock!",
    898. this);
    899.  
    900. return WOULD_BLOCK;
    901. }
    902.  
    903. while (mRunning == true) {
    904. mThreadExitedCondition.wait(mLock);
    905. }
    906.  
    907. return mStatus;
    908. }
    909.  
    910. bool Thread::exitPending() const
    911. {
    912. Mutex::Autolock _l(mLock);
    913. return mExitPending;
    914. }
    915.  
    916. }; // namespace android

    Threads.cpp

  • The definition of Mutex in thread
  •  class Mutex {
    public:
    enum {
    PRIVATE = ,
    SHARED =
    };
    Mutex();
    Mutex(const char* name);
    Mutex(int type, const char* name = NULL);
    ~Mutex();
    status_t lock();
    void unlock();
    status_t tryLock();
    class Autolock {
    public:
    inline Autolock(Mutex& mutex) : mLock(mutex) { mLock.lock(); }
    inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); }
    inline ~Autolock() { mLock.unlock(); }
    private:
    Mutex& mLock;
    };
    private:
    friend class Condition;
    // A mutex cannot be copied
    Mutex(const Mutex&);
    Mutex& operator = (const Mutex&);
    #if defined(HAVE_PTHREADS)
    pthread_mutex_t mMutex;
    #else
    void _init();
    void* mState;
    #endif
    };
    #if defined(HAVE_PTHREADS)
    inline Mutex::Mutex() {
    pthread_mutex_init(&mMutex, NULL);
    }
    inline Mutex::Mutex(const char* name) {
    pthread_mutex_init(&mMutex, NULL);
    }
    inline Mutex::Mutex(int type, const char* name) {
    if (type == SHARED) {
    pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
    pthread_mutex_init(&mMutex, &attr);
    pthread_mutexattr_destroy(&attr);
    } else {
    pthread_mutex_init(&mMutex, NULL);
    }
    }
    inline Mutex::~Mutex() {
    pthread_mutex_destroy(&mMutex);
    }
    inline status_t Mutex::lock() {
    return -pthread_mutex_lock(&mMutex);
    }
    inline void Mutex::unlock() {
    pthread_mutex_unlock(&mMutex);
    }
    inline status_t Mutex::tryLock() {
    return -pthread_mutex_trylock(&mMutex);
    }
    #endif // HAVE_PTHREADS
    typedef Mutex::Autolock AutoMutex;

    Mutex

  • The interface of thread
  •  lass Thread : virtual public RefBase
    {
    public:
    Thread(bool canCallJava = true);
    virtual ~Thread();
    virtual status_t run(const char* name = ,
    int32_t priority = PRIORITY_DEFAULT,
    size_t stack = );
    virtual void requestExit();ns
    virtual status_t readyToRun();
    status_t requestExitAndWait();
    status_t join();
    protected:
    bool exitPending() const;
    private:
    virtual bool threadLoop() = ;
    private:
    Thread& operator=(const Thread&);
    static int _threadLoop(void* user);
    const bool mCanCallJava;
    thread_id_t mThread;
    mutable Mutex mLock;
    Condition mThreadExitedCondition;
    status_t mStatus;
    volatile bool mExitPending;
    volatile bool mRunning;
    sp<Thread> mHoldSelf;
    #if HAVE_ANDROID_OS
    int mTid;
    #endif
    };

    Thread

  • Create a thread on linux as global function
  •  1 inline bool createThread(thread_func_t f, void *a) {
    2 return androidCreateThread(f, a) ? true : false;
    3 }
    4 int androidCreateThread(android_thread_func_t fn, void* arg)
    5 {
    6 return createThreadEtc(fn, arg);
    7 }
    8
    9 // Create thread with lots of parameters
    10 inline bool createThreadEtc(thread_func_t entryFunction,
    11 void *userData,
    12 const char* threadName = "android:unnamed_thread",
    13 int32_t threadPriority = PRIORITY_DEFAULT,
    14 size_t threadStackSize = 0,
    15 thread_id_t *threadId = 0)
    16 {
    17 return androidCreateThreadEtc(entryFunction, userData, threadName,
    18 threadPriority, threadStackSize, threadId) ? true : false;
    19 }
    20 static android_create_thread_fn gCreateThreadFn = androidCreateRawThreadEtc;
    21 int androidCreateRawThreadEtc(android_thread_func_t entryFunction,
    22 void *userData,
    23 const char* threadName,
    24 int32_t threadPriority,
    25 size_t threadStackSize,
    26 android_thread_id_t *threadId)
    27 {
    28 pthread_attr_t attr;
    29 pthread_attr_init(&attr);
    30 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    31 #ifdef HAVE_ANDROID_OS /** valgrind is rejecting RT-priority create reqs */
    32 if (threadPriority != PRIORITY_DEFAULT || threadName != NULL) {
    33 // We could avoid the trampoline if there was a way to get to the
    34 // android_thread_id_t (pid) from pthread_t
    35 thread_data_t* t = new thread_data_t;
    36 t->priority = threadPriority;
    37 t->threadName = threadName ? strdup(threadName) : NULL;
    38 t->entryFunction = entryFunction;
    39 t->userData = userData;
    40 entryFunction = (android_thread_func_t)&thread_data_t::trampoline;
    41 userData = t;
    42 }
    43 #endif
    44 if (threadStackSize) {
    45 pthread_attr_setstacksize(&attr, threadStackSize);
    46 }
    47 errno = 0;
    48 pthread_t thread;
    49 int result = pthread_create(&thread, &attr,android_pthread_entry)entryFunction, userData);
    50 pthread_attr_destroy(&attr);
    51 if (result != 0) {
    52 LOGE("androidCreateRawThreadEtc failed (entry=%p, res=%d, errno=%d)\n"
    53 "(android threadPriority=%d)",
    54 entryFunction, result, errno, threadPriority);
    55 return 0;
    56 }
    57 // Note that *threadID is directly available to the parent only, as it is
    58 // assigned after the child starts. Use memory barrier / lock if the child
    59 // or other threads also need access.
    60 if (threadId != NULL) {
    61 *threadId = (android_thread_id_t)thread; // XXX: this is not portable
    62 }
    63 return 1;
    64 }  
  • Create a new thread on win32 as global function
  •  int androidCreateRawThreadEtc(android_thread_func_t fn,
    void *userData,
    const char* threadName,
    int32_t threadPriority,
    size_t threadStackSize,
    android_thread_id_t *threadId)
    {
    return doCreateThread( fn, userData, threadId);
    }
    static bool doCreateThread(android_thread_func_t fn, void* arg, android_thread_id_t *id)
    {
    HANDLE hThread;
    struct threadDetails* pDetails = new threadDetails; // must be on heap
    unsigned int thrdaddr;
    pDetails->func = fn;
    pDetails->arg = arg;
    #if defined(HAVE__BEGINTHREADEX)
    hThread = (HANDLE) _beginthreadex(NULL, , threadIntermediary, pDetails, ,&thrdaddr);
    if (hThread == )
    #elif defined(HAVE_CREATETHREAD)
    hThread = CreateThread(NULL, ,LPTHREAD_START_ROUTINE) threadIntermediary,
    (void*) pDetails, , (DWORD*) &thrdaddr);
    if (hThread == NULL)
    #endif
    {
    LOG(LOG_WARN, "thread", "WARNING: thread create failed\n");
    return false;
    }
    #if defined(HAVE_CREATETHREAD)
    /** close the management handle */
    CloseHandle(hThread);
    #endif
    if (id != NULL) {
    *id = (android_thread_id_t)thrdaddr;
    }
    return true;
    }
  • Create a thead in thread object
  •  status_t Thread::run(const char* name, int32_t priority, size_t stack)
    {
    Mutex::Autolock _l(mLock);
    if (mRunning) {
    // thread already started
    return INVALID_OPERATION;
    })
    mStatus = NO_ERROR;
    mExitPending = false;
    mThread = thread_id_t(-);
    mHoldSelf = this;
    mRunning = true;
    bool res;
    if (mCanCallJava) {
    res = createThreadEtc(_threadLoop,
    this, name, priority, stack, &mThread);
    } else {
    res = androidCreateRawThreadEtc(_threadLoop,
    this, name, priority, stack, &mThread);
    }
    if (res == false) {
    mStatus = UNKNOWN_ERROR; // something happened!
    mRunning = false;
    mThread = thread_id_t(-);
    mHoldSelf.clear(); // "this" may have gone away after this. return UNKNOWN_ERROR;
    }
    return NO_ERROR;
    }
    int Thread::_threadLoop(void* user)
    {
    Thread* const self = static_cast<Thread*>(user);
    sp<Thread> strong(self->mHoldSelf);
    wp<Thread> weak(strong);
    self->mHoldSelf.clear();
    #ifdef HAVE_ANDROID_OS
    // this is very useful for debugging with gdb
    self->mTid = gettid();
    #endif
    bool first = true; do {
    bool result;
    if (first) {
    first = false;
    self->mStatus = self->readyToRun();
    result = (self->mStatus == NO_ERROR); if (result && !self->exitPending()) {
    result = self->threadLoop();
    }
    } else {
    result = self->threadLoop();
    }
    // establish a scope for mLock
    {
    Mutex::Autolock _l(self->mLock);
    if (result == false || self->mExitPending) {
    self->mExitPending = true;
    self->mRunning = false;
    // clear thread ID so that requestExitAndWait() does not exit if
    // called by a new thread using the same thread ID as this one.
    self->mThread = thread_id_t(-);
    // note that interested observers blocked in requestExitAndWait are
    // awoken by broadcast, but blocked on mLock until break exits scope
    self->mThreadExitedCondition.broadcast();
    break;
    }
    }
    strong.clear();
    strong = weak.promote();
    } while(strong != );
    return ;
    }

 ProcessState

  • ProcessState.h
  •  /**
    * Copyright (C) 2005 The Android Open Source Project
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
    * You may obtain a copy of the License at
    *
    * http://www.apache.org/licenses/LICENSE-2.0
    *
    * Unless required by applicable law or agreed to in writing, software
    * distributed under the License is distributed on an "AS IS" BASIS,
    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    * See the License for the specific language governing permissions and
    * limitations under the License.
    */ #ifndef ANDROID_PROCESS_STATE_H
    #define ANDROID_PROCESS_STATE_H #include <binder/IBinder.h>
    #include <utils/KeyedVector.h>
    #include <utils/String8.h>
    #include <utils/String16.h> #include <utils/threads.h> // ---------------------------------------------------------------------------
    namespace android { // Global variables
    extern int mArgC;
    extern const char* const* mArgV;
    extern int mArgLen; class IPCThreadState; class ProcessState : public virtual RefBase
    {
    public:
    static sp<ProcessState> self();
    void setContextObject(const sp<IBinder>& object);
    sp<IBinder> getContextObject(const sp<IBinder>& caller);
    void setContextObject(const sp<IBinder>& object,
    const String16& name);
    sp<IBinder> getContextObject(const String16& name,
    const sp<IBinder>& caller); void startThreadPool();
    typedef bool (*context_check_func)(const String16& name,
    const sp<IBinder>& caller,
    void* userData); bool isContextManager(void) const;
    bool becomeContextManager(
    context_check_func checkFunc,
    void* userData); sp<IBinder> getStrongProxyForHandle(int32_t handle);
    wp<IBinder> getWeakProxyForHandle(int32_t handle);
    void expungeHandle(int32_t handle, IBinder* binder); void setArgs(int argc, const char* const argv[]);
    int getArgC() const;
    const char* const* getArgV() const; void setArgV0(const char* txt); void spawnPooledThread(bool isMain); private:
    friend class IPCThreadState; ProcessState();
    ~ProcessState(); ProcessState(const ProcessState& o);
    ProcessState& operator=(const ProcessState& o); struct handle_entry {
    IBinder* binder;
    RefBase::weakref_type* refs;
    }; handle_entry* lookupHandleLocked(int32_t handle); int mDriverFD;
    void* mVMStart; mutable Mutex mLock; // protects everything below. Vector<handle_entry>mHandleToObject; bool mManagesContexts;
    context_check_func mBinderContextCheckFunc;
    void* mBinderContextUserData; KeyedVector<String16, sp<IBinder> >
    mContexts; String8 mRootDir;
    bool mThreadPoolStarted;
    volatile int32_t mThreadPoolSeq;
    }; }; // namespace android // --------------------------------------------------------------------------- #endif // ANDROID_PROCESS_STATE_H

    ProcessState.h

  • ProcessState.cpp
  •  /**
    * Copyright (C) 2005 The Android Open Source Project
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
    * You may obtain a copy of the License at
    *
    * http://www.apache.org/licenses/LICENSE-2.0
    *
    * Unless required by applicable law or agreed to in writing, software
    * distributed under the License is distributed on an "AS IS" BASIS,
    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    * See the License for the specific language governing permissions and
    * limitations under the License.
    */ #define LOG_TAG "ProcessState" #include <cutils/process_name.h> #include <binder/ProcessState.h> #include <utils/Atomic.h>
    #include <binder/BpBinder.h>
    #include <binder/IPCThreadState.h>
    #include <utils/Log.h>
    #include <utils/String8.h>
    #include <binder/IServiceManager.h>
    #include <utils/String8.h>
    #include <utils/threads.h> #include <private/binder/binder_module.h>
    #include <private/binder/Static.h> #include <errno.h>
    #include <fcntl.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/ioctl.h>
    #include <sys/mman.h>
    #include <sys/stat.h> #define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2)) // --------------------------------------------------------------------------- namespace android { // Global variables
    int mArgC;
    const char* const* mArgV;
    int mArgLen; class PoolThread : public Thread
    {
    public:
    PoolThread(bool isMain)
    : mIsMain(isMain)
    {
    } protected:
    virtual bool threadLoop()
    {
    IPCThreadState::self()->joinThreadPool(mIsMain);
    return false;
    }
    const bool mIsMain;
    }; sp<ProcessState> ProcessState::self()
    {
    if (gProcess != NULL) return gProcess; AutoMutex _l(gProcessMutex);
    if (gProcess == NULL) gProcess = new ProcessState;
    return gProcess;
    } void ProcessState::setContextObject(const sp<IBinder>& object)
    {
    setContextObject(object, String16("default"));
    } sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)
    {
    return getStrongProxyForHandle();
    } void ProcessState::setContextObject(const sp<IBinder>& object, const String16& name)
    {
    AutoMutex _l(mLock);
    mContexts.add(name, object);
    } sp<IBinder> ProcessState::getContextObject(const String16& name, const sp<IBinder>& caller)
    {
    mLock.lock();
    sp<IBinder> object(
    mContexts.indexOfKey(name) >= ? mContexts.valueFor(name) : NULL);
    mLock.unlock(); //printf("Getting context object %s for %p\n", String8(name).string(), caller.get()); if (object != NULL) return object; // Don't attempt to retrieve contexts if we manage them
    if (mManagesContexts) {
    LOGE("getContextObject(%s) failed, but we manage the contexts!\n",
    String8(name).string());
    return NULL;
    } IPCThreadState* ipc = IPCThreadState::self();
    {
    Parcel data, reply;
    // no interface token on this magic transaction
    data.writeString16(name);
    data.writeStrongBinder(caller);
    status_t result = ipc->transact( /**magic*/, , data, &reply, );
    if (result == NO_ERROR) {
    object = reply.readStrongBinder();
    }
    } ipc->flushCommands(); if (object != NULL) setContextObject(object, name);
    return object;
    } void ProcessState::startThreadPool()
    {
    AutoMutex _l(mLock);
    if (!mThreadPoolStarted) {
    mThreadPoolStarted = true;
    spawnPooledThread(true);
    }
    } bool ProcessState::isContextManager(void) const
    {
    return mManagesContexts;
    } bool ProcessState::becomeContextManager(context_check_func checkFunc, void* userData)
    {
    if (!mManagesContexts) {
    AutoMutex _l(mLock);
    mBinderContextCheckFunc = checkFunc;
    mBinderContextUserData = userData; int dummy = ;
    status_t result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy);
    if (result == ) {
    mManagesContexts = true;
    } else if (result == -) {
    mBinderContextCheckFunc = NULL;
    mBinderContextUserData = NULL;
    LOGE("Binder ioctl to become context manager failed: %s\n", strerror(errno));
    }
    }
    return mManagesContexts;
    } ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle)
    {
    const size_t N=mHandleToObject.size();
    if (N <= (size_t)handle) {
    handle_entry e;
    e.binder = NULL;
    e.refs = NULL;
    status_t err = mHandleToObject.insertAt(e, N, handle+-N);
    if (err < NO_ERROR) return NULL;
    }
    return &mHandleToObject.editItemAt(handle);
    } sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
    {
    sp<IBinder> result; AutoMutex _l(mLock); handle_entry* e = lookupHandleLocked(handle); if (e != NULL) {
    // We need to create a new BpBinder if there isn't currently one, OR we
    // are unable to acquire a weak reference on this current one. See comment
    // in getWeakProxyForHandle() for more info about this.
    IBinder* b = e->binder;
    if (b == NULL || !e->refs->attemptIncWeak(this)) {
    b = new BpBinder(handle);
    e->binder = b;
    if (b) e->refs = b->getWeakRefs();
    result = b;
    } else {
    // This little bit of nastyness is to allow us to add a primary
    // reference to the remote proxy when this team doesn't have one
    // but another team is sending the handle to us.
    result.force_set(b);
    e->refs->decWeak(this);
    }
    } return result;
    } wp<IBinder> ProcessState::getWeakProxyForHandle(int32_t handle)
    {
    wp<IBinder> result; AutoMutex _l(mLock); handle_entry* e = lookupHandleLocked(handle); if (e != NULL) {
    // We need to create a new BpBinder if there isn't currently one, OR we
    // are unable to acquire a weak reference on this current one. The
    // attemptIncWeak() is safe because we know the BpBinder destructor will always
    // call expungeHandle(), which acquires the same lock we are holding now.
    // We need to do this because there is a race condition between someone
    // releasing a reference on this BpBinder, and a new reference on its handle
    // arriving from the driver.
    IBinder* b = e->binder;
    if (b == NULL || !e->refs->attemptIncWeak(this)) {
    b = new BpBinder(handle);
    result = b;
    e->binder = b;
    if (b) e->refs = b->getWeakRefs();
    } else {
    result = b;
    e->refs->decWeak(this);
    }
    } return result;
    } void ProcessState::expungeHandle(int32_t handle, IBinder* binder)
    {
    AutoMutex _l(mLock); handle_entry* e = lookupHandleLocked(handle); // This handle may have already been replaced with a new BpBinder
    // (if someone failed the AttemptIncWeak() above); we don't want
    // to overwrite it.
    if (e && e->binder == binder) e->binder = NULL;
    } void ProcessState::setArgs(int argc, const char* const argv[])
    {
    mArgC = argc;
    mArgV = (const char **)argv; mArgLen = ;
    for (int i=; i<argc; i++) {
    mArgLen += strlen(argv[i]) + ;
    }
    mArgLen--;
    } int ProcessState::getArgC() const
    {
    return mArgC;
    } const char* const* ProcessState::getArgV() const
    {
    return mArgV;
    } void ProcessState::setArgV0(const char* txt)
    {
    if (mArgV != NULL) {
    strncpy((char*)mArgV[], txt, mArgLen);
    set_process_name(txt);
    }
    } void ProcessState::spawnPooledThread(bool isMain)
    {
    if (mThreadPoolStarted) {
    int32_t s = android_atomic_add(, &mThreadPoolSeq);
    char buf[];
    sprintf(buf, "Binder Thread #%d", s);
    LOGV("Spawning new pooled thread, name=%s\n", buf);
    sp<Thread> t = new PoolThread(isMain);
    t->run(buf);
    }
    } static int open_driver()
    {
    int fd = open("/dev/binder", O_RDWR);
    if (fd >= ) {
    fcntl(fd, F_SETFD, FD_CLOEXEC);
    int vers;
    status_t result = ioctl(fd, BINDER_VERSION, &vers);
    if (result == -) {
    LOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
    close(fd);
    fd = -;
    }
    if (result != || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
    LOGE("Binder driver protocol does not match user space protocol!");
    close(fd);
    fd = -;
    }
    size_t maxThreads = ;
    result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
    if (result == -) {
    LOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
    }
    } else {
    LOGW("Opening '/dev/binder' failed: %s\n", strerror(errno));
    }
    return fd;
    } ProcessState::ProcessState()
    : mDriverFD(open_driver())
    , mVMStart(MAP_FAILED)
    , mManagesContexts(false)
    , mBinderContextCheckFunc(NULL)
    , mBinderContextUserData(NULL)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq()
    {
    if (mDriverFD >= ) {
    // XXX Ideally, there should be a specific define for whether we
    // have mmap (or whether we could possibly have the kernel module
    // availabla).
    #if !defined(HAVE_WIN32_IPC)
    // mmap the binder, providing a chunk of virtual address space to receive transactions.
    mVMStart = mmap(, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, );
    if (mVMStart == MAP_FAILED) {
    // *sigh*
    LOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
    close(mDriverFD);
    mDriverFD = -;
    }
    #else
    mDriverFD = -;
    #endif
    } LOG_ALWAYS_FATAL_IF(mDriverFD < , "Binder driver could not be opened. Terminating.");
    } ProcessState::~ProcessState()
    {
    } }; // namespace android

    ProcessState.cpp

  • Create a new object of ProcessState and assign to global sp<ProcessState> gProcess;
  •  sp<ProcessState> ProcessState::self()
    {
    if (gProcess != NULL)
    return gProcess;
    AutoMutex _l(gProcessMutex);
    if (gProcess == NULL)
    gProcess = new ProcessState;
    return gProcess;
    }
  • Open the binder to get handler of binder
  •  static int open_driver()//every process where the service run or client run will have its own default binder's handle
    {
    int fd = open("/dev/binder", O_RDWR);
    if (fd >= ) {
    fcntl(fd, F_SETFD, FD_CLOEXEC);
    int vers;
    status_t result = ioctl(fd, BINDER_VERSION, &vers);
    if (result == -) {
    LOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
    close(fd);
    fd = -;
    }
    if (result != || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
    LOGE("Binder driver protocol does not match user space protocol!");
    close(fd);
    fd = -;
    }
    size_t maxThreads = ;
    result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
    if (result == -) {
    LOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
    }
    } else {
    LOGW("Opening '/dev/binder' failed: %s\n", strerror(errno));
    }
    return fd;
    }
  •  ProcessState::ProcessState()
    : mDriverFD(open_driver())
    , mVMStart(MAP_FAILED)
    , mManagesContexts(false)
    , mBinderContextCheckFunc(NULL)
    , mBinderContextUserData(NULL)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq()
    {
    if (mDriverFD >= ) {
    // XXX Ideally, there should be a specific define for whether we
    // have mmap (or whether we could possibly have the kernel module
    // availabla).
    #if !defined(HAVE_WIN32_IPC)
    // mmap the binder, providing a chunk of virtual address space to receive transactions.
    mVMStart = mmap(, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, );
    if (mVMStart == MAP_FAILED) {
    // *sigh*
    LOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
    close(mDriverFD);
    mDriverFD = -;
    }
    #else
    mDriverFD = -;
    #endif
    }
    }

    PrecessState's Constructor

  • PoolThread of ProcessState
  •  class PoolThread : public Thread
    {
    public:
    PoolThread(bool isMain)
    : mIsMain(isMain)
    {
    }
    protected:
    virtual bool threadLoop()//override threadLoop of Thread
    {
    IPCThreadState::self()->joinThreadPool(mIsMain);
    return false;
    }
    const bool mIsMain;
    };
  • Start thread pool
  •  void ProcessState::startThreadPool()
    {
    AutoMutex _l(mLock);
    if (!mThreadPoolStarted) {
    mThreadPoolStarted = true;
    spawnPooledThread(true);
    }
    }
    void ProcessState::spawnPooledThread(bool isMain)
    {
    if (mThreadPoolStarted) {
    int32_t s = android_atomic_add(, &mThreadPoolSeq);
    char buf[];
    sprintf(buf, "Binder Thread #%d", s);
    LOGV("Spawning new pooled thread, name=%s\n", buf);
    sp<Thread> t = new PoolThread(isMain);
    t->run(buf);//thread run by calling threadLoop
      }  }

IPCThreadState

  • IPCThreadState.h
  •  /**
    * Copyright (C) 2005 The Android Open Source Project
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
    * You may obtain a copy of the License at
    *
    * http://www.apache.org/licenses/LICENSE-2.0
    *
    * Unless required by applicable law or agreed to in writing, software
    * distributed under the License is distributed on an "AS IS" BASIS,
    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    * See the License for the specific language governing permissions and
    * limitations under the License.
    */ #ifndef ANDROID_IPC_THREAD_STATE_H
    #define ANDROID_IPC_THREAD_STATE_H #include <utils/Errors.h>
    #include <binder/Parcel.h>
    #include <binder/ProcessState.h>
    #include <utils/Vector.h> #ifdef HAVE_WIN32_PROC
    typedef int uid_t;
    #endif // ---------------------------------------------------------------------------
    namespace android { class IPCThreadState
    {
    public:
    static IPCThreadState* self();
    static IPCThreadState* selfOrNull(); // self(), but won't instantiate
    sp<ProcessState> process();
    status_t clearLastError();
    int getCallingPid();
    int getCallingUid();
    void setStrictModePolicy(int32_t policy);
    int32_t getStrictModePolicy() const;
    void setLastTransactionBinderFlags(int32_t flags);
    int32_t getLastTransactionBinderFlags() const;
    int64_t clearCallingIdentity();
    void restoreCallingIdentity(int64_t token);
    void flushCommands();
    void joinThreadPool(bool isMain = true);
    void stopProcess(bool immediate = true);
    status_t transact(int32_t handle,
    uint32_t code, const Parcel& data,
    Parcel* reply, uint32_t flags);
    void incStrongHandle(int32_t handle);
    void decStrongHandle(int32_t handle);
    void incWeakHandle(int32_t handle);
    void decWeakHandle(int32_t handle);
    status_t attemptIncStrongHandle(int32_t handle);
    static void expungeHandle(int32_t handle, IBinder* binder);
    status_t requestDeathNotification(int32_t handle,
    BpBinder* proxy);
    status_t clearDeathNotification(int32_t handle,
    BpBinder* proxy);
    static void shutdown();
    static void disableBackgroundScheduling(bool disable);
    private:
    IPCThreadState();
    ~IPCThreadState();
    status_t sendReply(const Parcel& reply, uint32_t flags);
    status_t waitForResponse(Parcel *reply,
    status_t *acquireResult=NULL);
    status_t talkWithDriver(bool doReceive=true);
    status_t writeTransactionData(int32_t cmd,
    uint32_t binderFlags,
    int32_t handle,
    uint32_t code,
    const Parcel& data,
    status_t* statusBuffer);
    status_t executeCommand(int32_t command);
    void clearCaller();
    static void threadDestructor(void *st);
    static void freeBuffer(Parcel* parcel,
    const uint8_t* data, size_t dataSize,
    const size_t* objects, size_t objectsSize,
    void* cookie);
    const sp<ProcessState> mProcess;
    const pid_t mMyThreadId;
    Vector<BBinder*> mPendingStrongDerefs;
    Vector<RefBase::weakref_type*> mPendingWeakDerefs; Parcel mIn;
    Parcel mOut;
    status_t mLastError;
    pid_t mCallingPid;
    uid_t mCallingUid;
    int32_t mStrictModePolicy;
    int32_t mLastTransactionBinderFlags;
    };
    };
    #endif // ANDROID_IPC_THREAD_STATE_H

    IPCThreadState.h

  • IPCThreadState.cpp
  •  /**
    * Copyright (C) 2005 The Android Open Source Project
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
    * You may obtain a copy of the License at
    *
    * http://www.apache.org/licenses/LICENSE-2.0
    *
    * Unless required by applicable law or agreed to in writing, software
    * distributed under the License is distributed on an "AS IS" BASIS,
    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    * See the License for the specific language governing permissions and
    * limitations under the License.
    */ #define LOG_TAG "IPCThreadState" #include <binder/IPCThreadState.h> #include <binder/Binder.h>
    #include <binder/BpBinder.h>
    #include <cutils/sched_policy.h>
    #include <utils/Debug.h>
    #include <utils/Log.h>
    #include <utils/TextOutput.h>
    #include <utils/threads.h> #include <private/binder/binder_module.h>
    #include <private/binder/Static.h> #include <sys/ioctl.h>
    #include <signal.h>
    #include <errno.h>
    #include <stdio.h>
    #include <unistd.h> #ifdef HAVE_PTHREADS
    #include <pthread.h>
    #include <sched.h>
    #include <sys/resource.h>
    #endif
    #ifdef HAVE_WIN32_THREADS
    #include <windows.h>
    #endif #if LOG_NDEBUG #define IF_LOG_TRANSACTIONS() if (false)
    #define IF_LOG_COMMANDS() if (false)
    #define LOG_REMOTEREFS(...)
    #define IF_LOG_REMOTEREFS() if (false)
    #define LOG_THREADPOOL(...)
    #define LOG_ONEWAY(...) #else #define IF_LOG_TRANSACTIONS() IF_LOG(LOG_VERBOSE, "transact")
    #define IF_LOG_COMMANDS() IF_LOG(LOG_VERBOSE, "ipc")
    #define LOG_REMOTEREFS(...) LOG(LOG_DEBUG, "remoterefs", __VA_ARGS__)
    #define IF_LOG_REMOTEREFS() IF_LOG(LOG_DEBUG, "remoterefs")
    #define LOG_THREADPOOL(...) LOG(LOG_DEBUG, "threadpool", __VA_ARGS__)
    #define LOG_ONEWAY(...) LOG(LOG_DEBUG, "ipc", __VA_ARGS__) #endif // --------------------------------------------------------------------------- namespace android { static const char* getReturnString(size_t idx);
    static const char* getCommandString(size_t idx);
    static const void* printReturnCommand(TextOutput& out, const void* _cmd);
    static const void* printCommand(TextOutput& out, const void* _cmd); // This will result in a missing symbol failure if the IF_LOG_COMMANDS()
    // conditionals don't get stripped... but that is probably what we want.
    #if !LOG_NDEBUG
    static const char *kReturnStrings[] = {
    "BR_ERROR",
    "BR_OK",
    "BR_TRANSACTION",
    "BR_REPLY",
    "BR_ACQUIRE_RESULT",
    "BR_DEAD_REPLY",
    "BR_TRANSACTION_COMPLETE",
    "BR_INCREFS",
    "BR_ACQUIRE",
    "BR_RELEASE",
    "BR_DECREFS",
    "BR_ATTEMPT_ACQUIRE",
    "BR_NOOP",
    "BR_SPAWN_LOOPER",
    "BR_FINISHED",
    "BR_DEAD_BINDER",
    "BR_CLEAR_DEATH_NOTIFICATION_DONE",
    "BR_FAILED_REPLY"
    }; static const char *kCommandStrings[] = {
    "BC_TRANSACTION",
    "BC_REPLY",
    "BC_ACQUIRE_RESULT",
    "BC_FREE_BUFFER",
    "BC_INCREFS",
    "BC_ACQUIRE",
    "BC_RELEASE",
    "BC_DECREFS",
    "BC_INCREFS_DONE",
    "BC_ACQUIRE_DONE",
    "BC_ATTEMPT_ACQUIRE",
    "BC_REGISTER_LOOPER",
    "BC_ENTER_LOOPER",
    "BC_EXIT_LOOPER",
    "BC_REQUEST_DEATH_NOTIFICATION",
    "BC_CLEAR_DEATH_NOTIFICATION",
    "BC_DEAD_BINDER_DONE"
    }; static const char* getReturnString(size_t idx)
    {
    if (idx < sizeof(kReturnStrings) / sizeof(kReturnStrings[]))
    return kReturnStrings[idx];
    else
    return "unknown";
    } static const char* getCommandString(size_t idx)
    {
    if (idx < sizeof(kCommandStrings) / sizeof(kCommandStrings[]))
    return kCommandStrings[idx];
    else
    return "unknown";
    } static const void* printBinderTransactionData(TextOutput& out, const void* data)
    {
    const binder_transaction_data* btd =
    (const binder_transaction_data*)data;
    if (btd->target.handle < ) {
    /** want to print descriptors in decimal; guess based on value */
    out << "target.desc=" << btd->target.handle;
    } else {
    out << "target.ptr=" << btd->target.ptr;
    }
    out << " (cookie " << btd->cookie << ")" << endl
    << "code=" << TypeCode(btd->code) << ", flags=" << (void*)btd->flags << endl
    << "data=" << btd->data.ptr.buffer << " (" << (void*)btd->data_size
    << " bytes)" << endl
    << "offsets=" << btd->data.ptr.offsets << " (" << (void*)btd->offsets_size
    << " bytes)";
    return btd+;
    } static const void* printReturnCommand(TextOutput& out, const void* _cmd)
    {
    static const size_t N = sizeof(kReturnStrings)/sizeof(kReturnStrings[]);
    const int32_t* cmd = (const int32_t*)_cmd;
    int32_t code = *cmd++;
    size_t cmdIndex = code & 0xff;
    if (code == (int32_t) BR_ERROR) {
    out << "BR_ERROR: " << (void*)(*cmd++) << endl;
    return cmd;
    } else if (cmdIndex >= N) {
    out << "Unknown reply: " << code << endl;
    return cmd;
    }
    out << kReturnStrings[cmdIndex]; switch (code) {
    case BR_TRANSACTION:
    case BR_REPLY: {
    out << ": " << indent;
    cmd = (const int32_t *)printBinderTransactionData(out, cmd);
    out << dedent;
    } break; case BR_ACQUIRE_RESULT: {
    const int32_t res = *cmd++;
    out << ": " << res << (res ? " (SUCCESS)" : " (FAILURE)");
    } break; case BR_INCREFS:
    case BR_ACQUIRE:
    case BR_RELEASE:
    case BR_DECREFS: {
    const int32_t b = *cmd++;
    const int32_t c = *cmd++;
    out << ": target=" << (void*)b << " (cookie " << (void*)c << ")";
    } break; case BR_ATTEMPT_ACQUIRE: {
    const int32_t p = *cmd++;
    const int32_t b = *cmd++;
    const int32_t c = *cmd++;
    out << ": target=" << (void*)b << " (cookie " << (void*)c
    << "), pri=" << p;
    } break; case BR_DEAD_BINDER:
    case BR_CLEAR_DEATH_NOTIFICATION_DONE: {
    const int32_t c = *cmd++;
    out << ": death cookie " << (void*)c;
    } break; default:
    // no details to show for: BR_OK, BR_DEAD_REPLY,
    // BR_TRANSACTION_COMPLETE, BR_FINISHED
    break;
    } out << endl;
    return cmd;
    } static const void* printCommand(TextOutput& out, const void* _cmd)
    {
    static const size_t N = sizeof(kCommandStrings)/sizeof(kCommandStrings[]);
    const int32_t* cmd = (const int32_t*)_cmd;
    int32_t code = *cmd++;
    size_t cmdIndex = code & 0xff; if (cmdIndex >= N) {
    out << "Unknown command: " << code << endl;
    return cmd;
    }
    out << kCommandStrings[cmdIndex]; switch (code) {
    case BC_TRANSACTION:
    case BC_REPLY: {
    out << ": " << indent;
    cmd = (const int32_t *)printBinderTransactionData(out, cmd);
    out << dedent;
    } break; case BC_ACQUIRE_RESULT: {
    const int32_t res = *cmd++;
    out << ": " << res << (res ? " (SUCCESS)" : " (FAILURE)");
    } break; case BC_FREE_BUFFER: {
    const int32_t buf = *cmd++;
    out << ": buffer=" << (void*)buf;
    } break; case BC_INCREFS:
    case BC_ACQUIRE:
    case BC_RELEASE:
    case BC_DECREFS: {
    const int32_t d = *cmd++;
    out << ": desc=" << d;
    } break; case BC_INCREFS_DONE:
    case BC_ACQUIRE_DONE: {
    const int32_t b = *cmd++;
    const int32_t c = *cmd++;
    out << ": target=" << (void*)b << " (cookie " << (void*)c << ")";
    } break; case BC_ATTEMPT_ACQUIRE: {
    const int32_t p = *cmd++;
    const int32_t d = *cmd++;
    out << ": desc=" << d << ", pri=" << p;
    } break; case BC_REQUEST_DEATH_NOTIFICATION:
    case BC_CLEAR_DEATH_NOTIFICATION: {
    const int32_t h = *cmd++;
    const int32_t c = *cmd++;
    out << ": handle=" << h << " (death cookie " << (void*)c << ")";
    } break; case BC_DEAD_BINDER_DONE: {
    const int32_t c = *cmd++;
    out << ": death cookie " << (void*)c;
    } break; default:
    // no details to show for: BC_REGISTER_LOOPER, BC_ENTER_LOOPER,
    // BC_EXIT_LOOPER
    break;
    } out << endl;
    return cmd;
    }
    #endif static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER;
    static bool gHaveTLS = false;
    static pthread_key_t gTLS = ;
    static bool gShutdown = false;
    static bool gDisableBackgroundScheduling = false; IPCThreadState* IPCThreadState::self()
    {
    if (gHaveTLS) {
    restart:
    const pthread_key_t k = gTLS;
    IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
    if (st) return st;
    return new IPCThreadState;
    }
    if (gShutdown) return NULL;
    pthread_mutex_lock(&gTLSMutex);
    if (!gHaveTLS) {
    if (pthread_key_create(&gTLS, threadDestructor) != ) {
    pthread_mutex_unlock(&gTLSMutex);
    return NULL;
    }
    gHaveTLS = true;
    }
    pthread_mutex_unlock(&gTLSMutex);
    goto restart;
    } IPCThreadState* IPCThreadState::selfOrNull()
    {
    if (gHaveTLS) {
    const pthread_key_t k = gTLS;
    IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
    return st;
    }
    return NULL;
    } void IPCThreadState::shutdown()
    {
    gShutdown = true; if (gHaveTLS) {
    // XXX Need to wait for all thread pool threads to exit!
    IPCThreadState* st = (IPCThreadState*)pthread_getspecific(gTLS);
    if (st) {
    delete st;
    pthread_setspecific(gTLS, NULL);
    }
    gHaveTLS = false;
    }
    } void IPCThreadState::disableBackgroundScheduling(bool disable)
    {
    gDisableBackgroundScheduling = disable;
    } sp<ProcessState> IPCThreadState::process()
    {
    return mProcess;
    } status_t IPCThreadState::clearLastError()
    {
    const status_t err = mLastError;
    mLastError = NO_ERROR;
    return err;
    } int IPCThreadState::getCallingPid()
    {
    return mCallingPid;
    } int IPCThreadState::getCallingUid()
    {
    return mCallingUid;
    } int64_t IPCThreadState::clearCallingIdentity()
    {
    int64_t token = ((int64_t)mCallingUid<<) | mCallingPid;
    clearCaller();
    return token;
    } void IPCThreadState::setStrictModePolicy(int32_t policy)
    {
    mStrictModePolicy = policy;
    } int32_t IPCThreadState::getStrictModePolicy() const
    {
    return mStrictModePolicy;
    } void IPCThreadState::setLastTransactionBinderFlags(int32_t flags)
    {
    mLastTransactionBinderFlags = flags;
    } int32_t IPCThreadState::getLastTransactionBinderFlags() const
    {
    return mLastTransactionBinderFlags;
    } void IPCThreadState::restoreCallingIdentity(int64_t token)
    {
    mCallingUid = (int)(token>>);
    mCallingPid = (int)token;
    } void IPCThreadState::clearCaller()
    {
    mCallingPid = getpid();
    mCallingUid = getuid();
    } void IPCThreadState::flushCommands()
    {
    if (mProcess->mDriverFD <= )
    return;
    talkWithDriver(false);
    } void IPCThreadState::joinThreadPool(bool isMain)
    {
    LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid());
    mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
    // This thread may have been spawned by a thread that was in the background
    // scheduling group, so first we will make sure it is in the default/foreground
    // one to avoid performing an initial transaction in the background.
    androidSetThreadSchedulingGroup(mMyThreadId, ANDROID_TGROUP_DEFAULT);
    status_t result;
    do {
    int32_t cmd;
    // When we've cleared the incoming command queue, process any pending derefs
    if (mIn.dataPosition() >= mIn.dataSize()) {
    size_t numPending = mPendingWeakDerefs.size();
    if (numPending > ) {
    for (size_t i = ; i < numPending; i++) {
    RefBase::weakref_type* refs = mPendingWeakDerefs[i];
    refs->decWeak(mProcess.get());
    }
    mPendingWeakDerefs.clear();
    }
    numPending = mPendingStrongDerefs.size();
    if (numPending > ) {
    for (size_t i = ; i < numPending; i++) {
    BBinder* obj = mPendingStrongDerefs[i];
    obj->decStrong(mProcess.get());
    }
    mPendingStrongDerefs.clear();
    }
    }
    // now get the next command to be processed, waiting if necessary
    result = talkWithDriver();
    if (result >= NO_ERROR) {
    size_t IN = mIn.dataAvail();
    if (IN < sizeof(int32_t)) continue;
    cmd = mIn.readInt32();
    IF_LOG_COMMANDS() {
    alog << "Processing top-level Command: "
    << getReturnString(cmd) << endl;
    }
    result = executeCommand(cmd);
    }
    // After executing the command, ensure that the thread is returned to the
    // default cgroup before rejoining the pool. The driver takes care of
    // restoring the priority, but doesn't do anything with cgroups so we
    // need to take care of that here in userspace. Note that we do make
    // sure to go in the foreground after executing a transaction, but
    // there are other callbacks into user code that could have changed
    // our group so we want to make absolutely sure it is put back.
    androidSetThreadSchedulingGroup(mMyThreadId, ANDROID_TGROUP_DEFAULT);
    // Let this thread exit the thread pool if it is no longer
    // needed and it is not the main process thread.
    if(result == TIMED_OUT && !isMain) {
    break;
    }
    } while (result != -ECONNREFUSED && result != -EBADF); LOG_THREADPOOL("**** THREAD %p (PID %d) IS LEAVING THE THREAD POOL err=%p\n",
    (void*)pthread_self(), getpid(), (void*)result);
    mOut.writeInt32(BC_EXIT_LOOPER);
    talkWithDriver(false);
    } void IPCThreadState::stopProcess(bool immediate)
    {
    //LOGI("**** STOPPING PROCESS");
    flushCommands();
    int fd = mProcess->mDriverFD;
    mProcess->mDriverFD = -;
    close(fd);
    //kill(getpid(), SIGKILL);
    } status_t IPCThreadState::transact(int32_t handle,
    uint32_t code, const Parcel& data,
    Parcel* reply, uint32_t flags)
    {
    status_t err = data.errorCheck(); flags |= TF_ACCEPT_FDS; IF_LOG_TRANSACTIONS() {
    TextOutput::Bundle _b(alog);
    alog << "BC_TRANSACTION thr " << (void*)pthread_self() << " / hand "
    << handle << " / code " << TypeCode(code) << ": "
    << indent << data << dedent << endl;
    } if (err == NO_ERROR) {
    LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),
    (flags & TF_ONE_WAY) == ? "READ REPLY" : "ONE WAY");
    err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
    } if (err != NO_ERROR) {
    if (reply) reply->setError(err);
    return (mLastError = err);
    } if ((flags & TF_ONE_WAY) == ) {
    #if 0
    if (code == ) { // relayout
    LOGI(">>>>>> CALLING transaction 4");
    } else {
    LOGI(">>>>>> CALLING transaction %d", code);
    }
    #endif
    if (reply) {
    err = waitForResponse(reply);
    } else {
    Parcel fakeReply;
    err = waitForResponse(&fakeReply);
    }
    #if 0
    if (code == ) { // relayout
    LOGI("<<<<<< RETURNING transaction 4");
    } else {
    LOGI("<<<<<< RETURNING transaction %d", code);
    }
    #endif IF_LOG_TRANSACTIONS() {
    TextOutput::Bundle _b(alog);
    alog << "BR_REPLY thr " << (void*)pthread_self() << " / hand "
    << handle << ": ";
    if (reply) alog << indent << *reply << dedent << endl;
    else alog << "(none requested)" << endl;
    }
    } else {
    err = waitForResponse(NULL, NULL);
    } return err;
    } void IPCThreadState::incStrongHandle(int32_t handle)
    {
    LOG_REMOTEREFS("IPCThreadState::incStrongHandle(%d)\n", handle);
    mOut.writeInt32(BC_ACQUIRE);
    mOut.writeInt32(handle);
    } void IPCThreadState::decStrongHandle(int32_t handle)
    {
    LOG_REMOTEREFS("IPCThreadState::decStrongHandle(%d)\n", handle);
    mOut.writeInt32(BC_RELEASE);
    mOut.writeInt32(handle);
    } void IPCThreadState::incWeakHandle(int32_t handle)
    {
    LOG_REMOTEREFS("IPCThreadState::incWeakHandle(%d)\n", handle);
    mOut.writeInt32(BC_INCREFS);
    mOut.writeInt32(handle);
    } void IPCThreadState::decWeakHandle(int32_t handle)
    {
    LOG_REMOTEREFS("IPCThreadState::decWeakHandle(%d)\n", handle);
    mOut.writeInt32(BC_DECREFS);
    mOut.writeInt32(handle);
    } status_t IPCThreadState::attemptIncStrongHandle(int32_t handle)
    {
    LOG_REMOTEREFS("IPCThreadState::attemptIncStrongHandle(%d)\n", handle);
    mOut.writeInt32(BC_ATTEMPT_ACQUIRE);
    mOut.writeInt32(); // xxx was thread priority
    mOut.writeInt32(handle);
    status_t result = UNKNOWN_ERROR; waitForResponse(NULL, &result); #if LOG_REFCOUNTS
    printf("IPCThreadState::attemptIncStrongHandle(%ld) = %s\n",
    handle, result == NO_ERROR ? "SUCCESS" : "FAILURE");
    #endif return result;
    } void IPCThreadState::expungeHandle(int32_t handle, IBinder* binder)
    {
    #if LOG_REFCOUNTS
    printf("IPCThreadState::expungeHandle(%ld)\n", handle);
    #endif
    self()->mProcess->expungeHandle(handle, binder);
    } status_t IPCThreadState::requestDeathNotification(int32_t handle, BpBinder* proxy)
    {
    mOut.writeInt32(BC_REQUEST_DEATH_NOTIFICATION);
    mOut.writeInt32((int32_t)handle);
    mOut.writeInt32((int32_t)proxy);
    return NO_ERROR;
    } status_t IPCThreadState::clearDeathNotification(int32_t handle, BpBinder* proxy)
    {
    mOut.writeInt32(BC_CLEAR_DEATH_NOTIFICATION);
    mOut.writeInt32((int32_t)handle);
    mOut.writeInt32((int32_t)proxy);
    return NO_ERROR;
    } IPCThreadState::IPCThreadState()
    : mProcess(ProcessState::self()),
    mMyThreadId(androidGetTid()),
    mStrictModePolicy(),
    mLastTransactionBinderFlags()
    {
    pthread_setspecific(gTLS, this);
    clearCaller();
    mIn.setDataCapacity();
    mOut.setDataCapacity();
    } IPCThreadState::~IPCThreadState()
    {
    } status_t IPCThreadState::sendReply(const Parcel& reply, uint32_t flags)
    {
    status_t err;
    status_t statusBuffer;
    err = writeTransactionData(BC_REPLY, flags, -, , reply, &statusBuffer);
    if (err < NO_ERROR) return err; return waitForResponse(NULL, NULL);
    } status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
    {
    int32_t cmd;
    int32_t err; while () {
    if ((err=talkWithDriver()) < NO_ERROR) break;
    err = mIn.errorCheck();
    if (err < NO_ERROR) break;
    if (mIn.dataAvail() == ) continue; cmd = mIn.readInt32(); IF_LOG_COMMANDS() {
    alog << "Processing waitForResponse Command: "
    << getReturnString(cmd) << endl;
    } switch (cmd) {
    case BR_TRANSACTION_COMPLETE:
    if (!reply && !acquireResult) goto finish;
    break; case BR_DEAD_REPLY:
    err = DEAD_OBJECT;
    goto finish; case BR_FAILED_REPLY:
    err = FAILED_TRANSACTION;
    goto finish; case BR_ACQUIRE_RESULT:
    {
    LOG_ASSERT(acquireResult != NULL, "Unexpected brACQUIRE_RESULT");
    const int32_t result = mIn.readInt32();
    if (!acquireResult) continue;
    *acquireResult = result ? NO_ERROR : INVALID_OPERATION;
    }
    goto finish; case BR_REPLY:
    {
    binder_transaction_data tr;
    err = mIn.read(&tr, sizeof(tr));
    LOG_ASSERT(err == NO_ERROR, "Not enough command data for brREPLY");
    if (err != NO_ERROR) goto finish; if (reply) {
    if ((tr.flags & TF_STATUS_CODE) == ) {
    reply->ipcSetDataReference(
    reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
    tr.data_size,
    reinterpret_cast<const size_t*>(tr.data.ptr.offsets),
    tr.offsets_size/sizeof(size_t),
    freeBuffer, this);
    } else {
    err = *static_cast<const status_t*>(tr.data.ptr.buffer);
    freeBuffer(NULL,
    reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
    tr.data_size,
    reinterpret_cast<const size_t*>(tr.data.ptr.offsets),
    tr.offsets_size/sizeof(size_t), this);
    }
    } else {
    freeBuffer(NULL,
    reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
    tr.data_size,
    reinterpret_cast<const size_t*>(tr.data.ptr.offsets),
    tr.offsets_size/sizeof(size_t), this);
    continue;
    }
    }
    goto finish; default:
    err = executeCommand(cmd);
    if (err != NO_ERROR) goto finish;
    break;
    }
    } finish:
    if (err != NO_ERROR) {
    if (acquireResult) *acquireResult = err;
    if (reply) reply->setError(err);
    mLastError = err;
    } return err;
    } status_t IPCThreadState::talkWithDriver(bool doReceive)
    {
    LOG_ASSERT(mProcess->mDriverFD >= , "Binder driver is not opened"); binder_write_read bwr; // Is the read buffer empty?
    const bool needRead = mIn.dataPosition() >= mIn.dataSize(); // We don't want to write anything if we are still reading
    // from data left in the input buffer and the caller
    // has requested to read the next data.
    const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : ; bwr.write_size = outAvail;
    bwr.write_buffer = (long unsigned int)mOut.data(); // This is what we'll read.
    if (doReceive && needRead) {
    bwr.read_size = mIn.dataCapacity();
    bwr.read_buffer = (long unsigned int)mIn.data();
    } else {
    bwr.read_size = ;
    } IF_LOG_COMMANDS() {
    TextOutput::Bundle _b(alog);
    if (outAvail != ) {
    alog << "Sending commands to driver: " << indent;
    const void* cmds = (const void*)bwr.write_buffer;
    const void* end = ((const uint8_t*)cmds)+bwr.write_size;
    alog << HexDump(cmds, bwr.write_size) << endl;
    while (cmds < end) cmds = printCommand(alog, cmds);
    alog << dedent;
    }
    alog << "Size of receive buffer: " << bwr.read_size
    << ", needRead: " << needRead << ", doReceive: " << doReceive << endl;
    } // Return immediately if there is nothing to do.
    if ((bwr.write_size == ) && (bwr.read_size == )) return NO_ERROR; bwr.write_consumed = ;
    bwr.read_consumed = ;
    status_t err;
    do {
    IF_LOG_COMMANDS() {
    alog << "About to read/write, write size = " << mOut.dataSize() << endl;
    }
    #if defined(HAVE_ANDROID_OS)
    if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= )
    err = NO_ERROR;
    else
    err = -errno;
    #else
    err = INVALID_OPERATION;
    #endif
    IF_LOG_COMMANDS() {
    alog << "Finished read/write, write size = " << mOut.dataSize() << endl;
    }
    } while (err == -EINTR); IF_LOG_COMMANDS() {
    alog << "Our err: " << (void*)err << ", write consumed: "
    << bwr.write_consumed << " (of " << mOut.dataSize()
    << "), read consumed: " << bwr.read_consumed << endl;
    } if (err >= NO_ERROR) {
    if (bwr.write_consumed > ) {
    if (bwr.write_consumed < (ssize_t)mOut.dataSize())
    mOut.remove(, bwr.write_consumed);
    else
    mOut.setDataSize();
    }
    if (bwr.read_consumed > ) {
    mIn.setDataSize(bwr.read_consumed);
    mIn.setDataPosition();
    }
    IF_LOG_COMMANDS() {
    TextOutput::Bundle _b(alog);
    alog << "Remaining data size: " << mOut.dataSize() << endl;
    alog << "Received commands from driver: " << indent;
    const void* cmds = mIn.data();
    const void* end = mIn.data() + mIn.dataSize();
    alog << HexDump(cmds, mIn.dataSize()) << endl;
    while (cmds < end) cmds = printReturnCommand(alog, cmds);
    alog << dedent;
    }
    return NO_ERROR;
    } return err;
    } status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
    int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
    {
    binder_transaction_data tr; tr.target.handle = handle;
    tr.code = code;
    tr.flags = binderFlags;
    tr.cookie = ;
    tr.sender_pid = ;
    tr.sender_euid = ; const status_t err = data.errorCheck();
    if (err == NO_ERROR) {
    tr.data_size = data.ipcDataSize();
    tr.data.ptr.buffer = data.ipcData();
    tr.offsets_size = data.ipcObjectsCount()*sizeof(size_t);
    tr.data.ptr.offsets = data.ipcObjects();
    } else if (statusBuffer) {
    tr.flags |= TF_STATUS_CODE;
    *statusBuffer = err;
    tr.data_size = sizeof(status_t);
    tr.data.ptr.buffer = statusBuffer;
    tr.offsets_size = ;
    tr.data.ptr.offsets = NULL;
    } else {
    return (mLastError = err);
    } mOut.writeInt32(cmd);
    mOut.write(&tr, sizeof(tr)); return NO_ERROR;
    } sp<BBinder> the_context_object; void setTheContextObject(sp<BBinder> obj)
    {
    the_context_object = obj;
    } status_t IPCThreadState::executeCommand(int32_t cmd)
    {
    BBinder* obj;
    RefBase::weakref_type* refs;
    status_t result = NO_ERROR; switch (cmd) {
    case BR_ERROR:
    result = mIn.readInt32();
    break; case BR_OK:
    break; case BR_ACQUIRE:
    refs = (RefBase::weakref_type*)mIn.readInt32();
    obj = (BBinder*)mIn.readInt32();
    LOG_ASSERT(refs->refBase() == obj,
    "BR_ACQUIRE: object %p does not match cookie %p (expected %p)",
    refs, obj, refs->refBase());
    obj->incStrong(mProcess.get());
    IF_LOG_REMOTEREFS() {
    LOG_REMOTEREFS("BR_ACQUIRE from driver on %p", obj);
    obj->printRefs();
    }
    mOut.writeInt32(BC_ACQUIRE_DONE);
    mOut.writeInt32((int32_t)refs);
    mOut.writeInt32((int32_t)obj);
    break; case BR_RELEASE:
    refs = (RefBase::weakref_type*)mIn.readInt32();
    obj = (BBinder*)mIn.readInt32();
    LOG_ASSERT(refs->refBase() == obj,
    "BR_RELEASE: object %p does not match cookie %p (expected %p)",
    refs, obj, refs->refBase());
    IF_LOG_REMOTEREFS() {
    LOG_REMOTEREFS("BR_RELEASE from driver on %p", obj);
    obj->printRefs();
    }
    mPendingStrongDerefs.push(obj);
    break; case BR_INCREFS:
    refs = (RefBase::weakref_type*)mIn.readInt32();
    obj = (BBinder*)mIn.readInt32();
    refs->incWeak(mProcess.get());
    mOut.writeInt32(BC_INCREFS_DONE);
    mOut.writeInt32((int32_t)refs);
    mOut.writeInt32((int32_t)obj);
    break; case BR_DECREFS:
    refs = (RefBase::weakref_type*)mIn.readInt32();
    obj = (BBinder*)mIn.readInt32();
    // NOTE: This assertion is not valid, because the object may no
    // longer exist (thus the (BBinder*)cast above resulting in a different
    // memory address).
    //LOG_ASSERT(refs->refBase() == obj,
    // "BR_DECREFS: object %p does not match cookie %p (expected %p)",
    // refs, obj, refs->refBase());
    mPendingWeakDerefs.push(refs);
    break; case BR_ATTEMPT_ACQUIRE:
    refs = (RefBase::weakref_type*)mIn.readInt32();
    obj = (BBinder*)mIn.readInt32(); {
    const bool success = refs->attemptIncStrong(mProcess.get());
    LOG_ASSERT(success && refs->refBase() == obj,
    "BR_ATTEMPT_ACQUIRE: object %p does not match cookie %p (expected %p)",
    refs, obj, refs->refBase()); mOut.writeInt32(BC_ACQUIRE_RESULT);
    mOut.writeInt32((int32_t)success);
    }
    break; case BR_TRANSACTION:
    {
    binder_transaction_data tr;
    result = mIn.read(&tr, sizeof(tr));
    LOG_ASSERT(result == NO_ERROR,
    "Not enough command data for brTRANSACTION");
    if (result != NO_ERROR) break; Parcel buffer;
    buffer.ipcSetDataReference(
    reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
    tr.data_size,
    reinterpret_cast<const size_t*>(tr.data.ptr.offsets),
    tr.offsets_size/sizeof(size_t), freeBuffer, this); const pid_t origPid = mCallingPid;
    const uid_t origUid = mCallingUid; mCallingPid = tr.sender_pid;
    mCallingUid = tr.sender_euid; int curPrio = getpriority(PRIO_PROCESS, mMyThreadId);
    if (gDisableBackgroundScheduling) {
    if (curPrio > ANDROID_PRIORITY_NORMAL) {
    // We have inherited a reduced priority from the caller, but do not
    // want to run in that state in this process. The driver set our
    // priority already (though not our scheduling class), so bounce
    // it back to the default before invoking the transaction.
    setpriority(PRIO_PROCESS, mMyThreadId, ANDROID_PRIORITY_NORMAL);
    }
    } else {
    if (curPrio >= ANDROID_PRIORITY_BACKGROUND) {
    // We want to use the inherited priority from the caller.
    // Ensure this thread is in the background scheduling class,
    // since the driver won't modify scheduling classes for us.
    // The scheduling group is reset to default by the caller
    // once this method returns after the transaction is complete.
    androidSetThreadSchedulingGroup(mMyThreadId,
    ANDROID_TGROUP_BG_NONINTERACT);
    }
    } //LOGI(">>>> TRANSACT from pid %d uid %d\n", mCallingPid, mCallingUid); Parcel reply;
    IF_LOG_TRANSACTIONS() {
    TextOutput::Bundle _b(alog);
    alog << "BR_TRANSACTION thr " << (void*)pthread_self()
    << " / obj " << tr.target.ptr << " / code "
    << TypeCode(tr.code) << ": " << indent << buffer
    << dedent << endl
    << "Data addr = "
    << reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer)
    << ", offsets addr="
    << reinterpret_cast<const size_t*>(tr.data.ptr.offsets) << endl;
    }
    if (tr.target.ptr) {
    sp<BBinder> b((BBinder*)tr.cookie);
    const status_t error = b->transact(tr.code, buffer, &reply, tr.flags);
    if (error < NO_ERROR) reply.setError(error); } else {
    const status_t error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
    if (error < NO_ERROR) reply.setError(error);
    } //LOGI("<<<< TRANSACT from pid %d restore pid %d uid %d\n",
    // mCallingPid, origPid, origUid); if ((tr.flags & TF_ONE_WAY) == ) {
    LOG_ONEWAY("Sending reply to %d!", mCallingPid);
    sendReply(reply, );
    } else {
    LOG_ONEWAY("NOT sending reply to %d!", mCallingPid);
    } mCallingPid = origPid;
    mCallingUid = origUid; IF_LOG_TRANSACTIONS() {
    TextOutput::Bundle _b(alog);
    alog << "BC_REPLY thr " << (void*)pthread_self() << " / obj "
    << tr.target.ptr << ": " << indent << reply << dedent << endl;
    } }
    break; case BR_DEAD_BINDER:
    {
    BpBinder *proxy = (BpBinder*)mIn.readInt32();
    proxy->sendObituary();
    mOut.writeInt32(BC_DEAD_BINDER_DONE);
    mOut.writeInt32((int32_t)proxy);
    } break; case BR_CLEAR_DEATH_NOTIFICATION_DONE:
    {
    BpBinder *proxy = (BpBinder*)mIn.readInt32();
    proxy->getWeakRefs()->decWeak(proxy);
    } break; case BR_FINISHED:
    result = TIMED_OUT;
    break; case BR_NOOP:
    break; case BR_SPAWN_LOOPER:
    mProcess->spawnPooledThread(false);
    break; default:
    printf("*** BAD COMMAND %d received from Binder driver\n", cmd);
    result = UNKNOWN_ERROR;
    break;
    } if (result != NO_ERROR) {
    mLastError = result;
    } return result;
    } void IPCThreadState::threadDestructor(void *st)
    {
    IPCThreadState* const self = static_cast<IPCThreadState*>(st);
    if (self) {
    self->flushCommands();
    #if defined(HAVE_ANDROID_OS)
    ioctl(self->mProcess->mDriverFD, BINDER_THREAD_EXIT, );
    #endif
    delete self;
    }
    } void IPCThreadState::freeBuffer(Parcel* parcel, const uint8_t* data, size_t dataSize,
    const size_t* objects, size_t objectsSize,
    void* cookie)
    {
    //LOGI("Freeing parcel %p", &parcel);
    IF_LOG_COMMANDS() {
    alog << "Writing BC_FREE_BUFFER for " << data << endl;
    }
    LOG_ASSERT(data != NULL, "Called with NULL data");
    if (parcel != NULL) parcel->closeFileDescriptors();
    IPCThreadState* state = self();
    state->mOut.writeInt32(BC_FREE_BUFFER);
    state->mOut.writeInt32((int32_t)data);
    } }; // namespace android

    IPCThreadState.cpp

  • IPCThread.Self()

  •  static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER;
    static bool gHaveTLS = false;
    static pthread_key_t gTLS = ;
    static bool gShutdown = false;
    static bool gDisableBackgroundScheduling = false;
    IPCThreadState* IPCThreadState::self()
    {
    if (gHaveTLS) {
    restart:
    const pthread_key_t k = gTLS;
    IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
    if (st) return st;
    return new IPCThreadState;
    }
    if (gShutdown) return NULL;
    pthread_mutex_lock(&gTLSMutex);
    if (!gHaveTLS) {
    if (pthread_key_create(&gTLS, threadDestructor) != ) {
    pthread_mutex_unlock(&gTLSMutex);
    return NULL;
    }
    gHaveTLS = true;
    }
    pthread_mutex_unlock(&gTLSMutex);
    goto restart;
    }
    IPCThreadState::IPCThreadState()
    : mProcess(ProcessState::self()),
    mMyThreadId(androidGetTid()),
    mStrictModePolicy(),
    mLastTransactionBinderFlags()
    {
    pthread_setspecific(gTLS, this);
    clearCaller();
    mIn.setDataCapacity();
    mOut.setDataCapacity();
    }
  • joinThreadPool
  •  void IPCThreadState::joinThreadPool(bool isMain)
    {
    LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid());
    mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
    androidSetThreadSchedulingGroup(mMyThreadId, ANDROID_TGROUP_DEFAULT);
    status_t result;
    do {
    int32_t cmd;
    if (mIn.dataPosition() >= mIn.dataSize()) {
    size_t numPending = mPendingWeakDerefs.size();
    if (numPending > ) {
    for (size_t i = ; i < numPending; i++) {
    RefBase::weakref_type* refs = mPendingWeakDerefs[i];
    refs->decWeak(mProcess.get());
    }
    mPendingWeakDerefs.clear();
    }
    numPending = mPendingStrongDerefs.size();
    if (numPending > ) {
    for (size_t i = ; i < numPending; i++) {
    BBinder* obj = mPendingStrongDerefs[i];
    obj->decStrong(mProcess.get());
    }
    mPendingStrongDerefs.clear();
    }
    }
    // now get the next command to be processed, waiting if necessary
    result = talkWithDriver();
    if (result >= NO_ERROR) {
    size_t IN = mIn.dataAvail();
    if (IN < sizeof(int32_t)) continue;
    cmd = mIn.readInt32();
    IF_LOG_COMMANDS() {
    alog << "Processing top-level Command: "
    << getReturnString(cmd) << endl;
    }
    result = executeCommand(cmd);
    }
    androidSetThreadSchedulingGroup(mMyThreadId, ANDROID_TGROUP_DEFAULT);
    if(result == TIMED_OUT && !isMain) {
    break;
    }
    } while (result != -ECONNREFUSED && result != -EBADF);
    LOG_THREADPOOL("**** THREAD %p (PID %d) IS LEAVING THE THREAD POOL err=%p\n",
    (void*)pthread_self(), getpid(), (void*)result);
    mOut.writeInt32(BC_EXIT_LOOPER);
    talkWithDriver(false);
    }

Android Process & Thread的更多相关文章

  1. [Java][Android][Process] 暴力的服务能够解决一切,暴力的方式运行命令行语句

    不管是在Java或者Android中运行命令行语句殊途同归都是创建一个子进程运行调用可运行文件运行命令.类似于Windows中的CMD一样. 此时你有两种方式运行:ProcessBuilder与Run ...

  2. [Java][Android][Process] ProcessBuilder与Runtime差别

    在Android中想要进行Ping,在不Root机器的情况下似乎还仅仅能进行底层命调用才干实现. 由于在Java中要进行ICMP包发送须要Root权限. 于是仅仅能通过创建进程来攻克了.创建进程在Ja ...

  3. Android:关于声明文件中android:process属性说明

    笔者在学习Android Service组件的过程中碰到了一个问题,就是在Android应用的声明文件Manifest.xml中有时候会对相关的服务标签设置一个android:process=&quo ...

  4. Android开发之android:process=":remote"

    由于每个应用程序都运行在自己的进程空间,并且可以从应用程序UI运行另一个服务进程,而且经常会在不同的进程间传递对象.在Android平台,一个进程通常不能访问另一个进程的内存空间,所以要想对话,需要将 ...

  5. Android handler Thread 修改UI Demo

    /********************************************************************** * Android handler Thread 修改U ...

  6. android:process为耗资源操作指定一个新进程

    当有一些耗费内存比较多的操作时,可以通过android:process指定一个新的进程.保证程序运行. 例如: 一个后台长期运行的service: <service android:name=& ...

  7. apk,task,android:process与android:sharedUserId的区别

    apk一般占一个dalvik,一个进程,一个task.通过设置也可以多个进程,占多个task. task是一个activity的栈,其中"可能"含有来自多个App的activity ...

  8. android.process.acore和system进程

    从源码看来,android.process.acore进程应该是一些基本功能的载入程序. android-4.3_r2.2中,它包括以下项目: 1.UserDictionaryProvider < ...

  9. Linux中的task,process, thread 简介

    本文的主要目的是介绍在Linux内核中,task,process, thread这3个名字之间的区别和联系.并且和WINDOWS中的相应观念进行比较.如果你已经很清楚了,那么就不用往下看了. LINU ...

随机推荐

  1. 异步解决方案(三)Promise

    首先建议大家先看看这篇博文,这是我看过的最清晰给力的博文了: https://www.cnblogs.com/lvdabao/p/es6-promise-1.html 附赠一篇笑死我了的博客,加入有一 ...

  2. Life is a journey

    Life is a journey. What we should care about is not where it's headed but what we see and how we fee ...

  3. caffe 图片数据的转换成lmdb和数据集均值(转)

    转自网站: http://blog.csdn.net/muyiyushan/article/details/70578077 1.准备数据 使用dog/cat数据集,在训练项目根目录下分别建立trai ...

  4. hdu 6297(常用的输出格式总结)

    题目链接:https://cn.vjudge.net/problem/HDU-6297 题目介绍:一道关于输出格式规范问题 wrong answer代码: #include<iostream&g ...

  5. component: resolve => require(['../pages/home.vue'], resolve)

    component: resolve => require(['../pages/home.vue'], resolve) vue 路由的懒加载 import Vue from 'vue' im ...

  6. Linux IPC 共享内存

    共享内存 共享内存(shared memory)是最简单的Linux进程间通信方式之一. 使用共享内存,不同进程可以对同一块内存进行读写. 由于所有进程对共享内存的访问就和访问自己的内存空间一样,而不 ...

  7. elasticsearch 插件 大全

    本文使用的elasticsearch版本:1.7.3 推荐几款比较常用的elasticsearch插件 1.集群监控插件 bigdesk node cluster 2.集群资源查看和查询插件 kopf ...

  8. Silverlight 用户代码未处理 TypeLoadException

    在Silverlight中动态创建Enum时,多次调用改方法出现上图所示错误,后来发现定义名称都是一样的, 在程序中声明全局变量去区别就可以了. int num = 1; private Type C ...

  9. JAVA HTTP请求和HTTPS请求

    HTTP与HTTPS区别:http://blog.csdn.net/lyhjava/article/details/51860215 URL发送 HTTP.HTTPS:http://blog.csdn ...

  10. springboot 启动的java进程默默终止

    首先说明这是一个灵异事件......... 场景1 :把之前用map实现的缓存用Redis重构,高高兴兴上线更新,10 分钟后,老板告诉我,项目停了,what ??? 像我这么帅气,英俊,聪明的人,更 ...