Android中的Parcel机制,面试必会

  1. return NO_ERROR;

  2. }

  3. status_t Parcel::setData(const uint8_t* buffer, size_t len)

  4. {

  5. status_t err = restartWrite(len);

  6. if (err == NO_ERROR) {

  7. memcpy(const_cast<uint8_t*>(data()), buffer, len);

  8. mDataSize = len;

  9. mFdsKnown = false;

  10. }

  11. return err;

  12. }

  13. status_t Parcel::appendFrom(Parcel *parcel, size_t offset, size_t len)

  14. {

  15. const sp proc(ProcessState::self());

  16. status_t err;

  17. uint8_t *data = parcel->mData;

  18. size_t *objects = parcel->mObjects;

  19. size_t size = parcel->mObjectsSize;

  20. int startPos = mDataPos;

  21. int firstIndex = -1, lastIndex = -2;

  22. if (len == 0) {

  23. return NO_ERROR;

  24. }

  25. // range checks against the source parcel size

  26. if ((offset > parcel->mDataSize)

  27. || (len > parcel->mDataSize)

  28. || (offset + len > parcel->mDataSize)) {

  29. return BAD_VALUE;

  30. }

  31. // Count objects in range

  32. for (int i = 0; i < (int) size; i++) {

  33. size_t off = objects[i];

  34. if ((off >= offset) && (off < offset + len)) {

  35. if (firstIndex == -1) {

  36. firstIndex = i;

  37. }

  38. lastIndex = i;

  39. }

  40. }

  41. int numObjects = lastIndex - firstIndex + 1;

  42. // grow data

  43. err = growData(len);

  44. if (err != NO_ERROR) {

  45. return err;

  46. }

  47. // append data

  48. memcpy(mData + mDataPos, data + offset, len);

  49. mDataPos += len;

  50. mDataSize += len;

  51. if (numObjects > 0) {

  52. // grow objects

  53. if (mObjectsCapacity < mObjectsSize + numObjects) {

  54. int newSize = ((mObjectsSize + numObjects)*3)/2;

  55. size_t *objects =

  56. (size_t*)realloc(mObjects, newSize*sizeof(size_t));

  57. if (objects == (size_t*)0) {

  58. return NO_MEMORY;

  59. }

  60. mObjects = objects;

  61. mObjectsCapacity = newSize;

  62. }

  63. // append and acquire objects

  64. int idx = mObjectsSize;

  65. for (int i = firstIndex; i <= lastIndex; i++) {

  66. size_t off = objects[i] - offset + startPos;

  67. mObjects[idx++] = off;

  68. mObjectsSize++;

  69. flat_binder_object* flat

  70. = reinterpret_cast<flat_binder_object*>(mData + off);

  71. acquire_object(proc, *flat, this);

  72. if (flat->type == BINDER_TYPE_FD) {

  73. // If this is a file descriptor, we need to dup it so the

  74. // new Parcel now owns its own fd, and can declare that we

  75. // officially know we have fds.

  76. flat->handle = dup(flat->handle);

  77. flat->cookie = (void*)1;

  78. mHasFds = mFdsKnown = true;

  79. }

  80. }

  81. }

  82. return NO_ERROR;

  83. }

  84. bool Parcel::hasFileDescriptors() const

  85. {

  86. if (!mFdsKnown) {

  87. scanForFds();

  88. }

  89. return mHasFds;

  90. }

  91. status_t Parcel::writeInterfaceToken(const String16& interface)

  92. {

  93. // currently the interface identification token is just its name as a string

  94. return writeString16(interface);

  95. }

  96. bool Parcel::checkInterface(IBinder* binder) const

  97. {

  98. return enforceInterface(binder->getInterfaceDescriptor());

  99. }

  100. bool Parcel::enforceInterface(const String16& interface) const

  101. {

  102. const String16 str(readString16());

  103. if (str == interface) {

  104. return true;

  105. } else {

  106. LOGW(“**** enforceInterface() expected ‘%s’ but read ‘%s’/n”,

  107. String8(interface).string(), String8(str).string());

  108. return false;

  109. }

  110. }

  111. const size_t* Parcel::objects() const

  112. {

  113. return mObjects;

  114. }

  115. size_t Parcel::objectsCount() const

  116. {

  117. return mObjectsSize;

  118. }

  119. status_t Parcel::errorCheck() const

  120. {

  121. return mError;

  122. }

  123. void Parcel::setError(status_t err)

  124. {

  125. mError = err;

  126. }

  127. status_t Parcel::finishWrite(size_t len)

  128. {

  129. //printf(“Finish write of %d/n”, len);

  130. mDataPos += len;

  131. LOGV(“finishWrite Setting data pos of %p to %d/n”, this, mDataPos);

  132. if (mDataPos > mDataSize) {

  133. mDataSize = mDataPos;

  134. LOGV(“finishWrite Setting data size of %p to %d/n”, this, mDataSize);

  135. }

  136. //printf(“New pos=%d, size=%d/n”, mDataPos, mDataSize);

  137. return NO_ERROR;

  138. }

  139. status_t Parcel::writeUnpadded(const void* data, size_t len)

  140. {

  141. size_t end = mDataPos + len;

  142. if (end < mDataPos) {

  143. // integer overflow

  144. return BAD_VALUE;

  145. }

  146. if (end <= mDataCapacity) {

  147. restart_write:

  148. memcpy(mData+mDataPos, data, len);

  149. return finishWrite(len);

  150. }

  151. status_t err = growData(len);

  152. if (err == NO_ERROR) goto restart_write;

  153. return err;

  154. }

  155. status_t Parcel::write(const void* data, size_t len)

  156. {

  157. void* const d = writeInplace(len);

  158. if (d) {

  159. memcpy(d, data, len);

  160. return NO_ERROR;

  161. }

  162. return mError;

  163. }

  164. void* Parcel::writeInplace(size_t len)

  165. {

  166. const size_t padded = PAD_SIZE(len);

  167. // sanity check for integer overflow

  168. if (mDataPos+padded < mDataPos) {

  169. return NULL;

  170. }

  171. if ((mDataPos+padded) <= mDataCapacity) {

  172. restart_write:

  173. //printf(“Writing %ld bytes, padded to %ld/n”, len, padded);

  174. uint8_t* const data = mData+mDataPos;

  175. // Need to pad at end?

  176. if (padded != len) {

  177. #if BYTE_ORDER == BIG_ENDIAN

  178. static const uint32_t mask[4] = {

  179. 0x00000000, 0xffffff00, 0xffff0000, 0xff000000

  180. };

  181. #endif

  182. #if BYTE_ORDER == LITTLE_ENDIAN

  183. static const uint32_t mask[4] = {

  184. 0x00000000, 0x00ffffff, 0x0000ffff, 0x000000ff

  185. };

  186. #endif

  187. //printf(“Applying pad mask: %p to %p/n”, (void*)mask[padded-len],

  188. //    *reinterpret_cast<void**>(data+padded-4));

  189. *reinterpret_cast<uint32_t*>(data+padded-4) &= mask[padded-len];

  190. }

  191. finishWrite(padded);

  192. return data;

  193. }

  194. status_t err = growData(padded);

  195. if (err == NO_ERROR) goto restart_write;

  196. return NULL;

  197. }

  198. status_t Parcel::writeInt32(int32_t val)

  199. {

  200. return writeAligned(val);

  201. }

  202. status_t Parcel::writeInt64(int64_t val)

  203. {

  204. return writeAligned(val);

  205. }

  206. status_t Parcel::writeFloat(float val)

  207. {

  208. return writeAligned(val);

  209. }

  210. status_t Parcel::writeDouble(double val)

  211. {

  212. return writeAligned(val);

  213. }

  214. status_t Parcel::writeIntPtr(intptr_t val)

  215. {

  216. return writeAligned(val);

  217. }

  218. status_t Parcel::writeCString(const char* str)

  219. {

  220. return write(str, strlen(str)+1);

  221. }

  222. status_t Parcel::writeString8(const String8& str)

  223. {

  224. status_t err = writeInt32(str.bytes());

  225. if (err == NO_ERROR) {

  226. err = write(str.string(), str.bytes()+1);

  227. }

  228. return err;

  229. }

  230. status_t Parcel::writeString16(const String16& str)

  231. {

  232. return writeString16(str.string(), str.size());

  233. }

  234. status_t Parcel::writeString16(const char16_t* str, size_t len)

  235. {

  236. if (str == NULL) return writeInt32(-1);

  237. status_t err = writeInt32(len);

  238. if (err == NO_ERROR) {

  239. len *= sizeof(char16_t);

  240. uint8_t* data = (uint8_t*)writeInplace(len+sizeof(char16_t));

  241. if (data) {

  242. memcpy(data, str, len);

  243. *reinterpret_cast<char16_t*>(data+len) = 0;

  244. return NO_ERROR;

  245. }

  246. err = mError;

  247. }

  248. return err;

  249. }

  250. status_t Parcel::writeStrongBinder(const sp& val)

  251. {

  252. return flatten_binder(ProcessState::self(), val, this);

  253. }

  254. status_t Parcel::writeWeakBinder(const wp& val)

  255. {

  256. return flatten_binder(ProcessState::self(), val, this);

  257. }

  258. status_t Parcel::writeNativeHandle(const native_handle* handle)

  259. {

  260. if (!handle || handle->version != sizeof(native_handle))

  261. return BAD_TYPE;

  262. status_t err;

  263. err = writeInt32(handle->numFds);

  264. if (err != NO_ERROR) return err;

  265. err = writeInt32(handle->numInts);

  266. if (err != NO_ERROR) return err;

  267. for (int i=0 ; err==NO_ERROR && inumFds ; i++)

  268. err = writeDupFileDescriptor(handle->data[i]);

  269. if (err != NO_ERROR) {

  270. LOGD(“write native handle, write dup fd failed”);

  271. return err;

  272. }

  273. err = write(handle->data + handle->numFds, sizeof(int)*handle->numInts);

  274. return err;

  275. }

  276. status_t Parcel::writeFileDescriptor(int fd)

  277. {

  278. flat_binder_object obj;

  279. obj.type = BINDER_TYPE_FD;

  280. obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;

  281. obj.handle = fd;

  282. obj.cookie = (void*)0;

  283. return writeObject(obj, true);

  284. }

  285. status_t Parcel::writeDupFileDescriptor(int fd)

  286. {

  287. flat_binder_object obj;

  288. obj.type = BINDER_TYPE_FD;

  289. obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;

  290. obj.handle = dup(fd);

  291. obj.cookie = (void*)1;

  292. return writeObject(obj, true);

  293. }

  294. status_t Parcel::write(const Flattenable& val)

  295. {

  296. status_t err;

  297. // size if needed

  298. size_t len = val.getFlattenedSize();

  299. size_t fd_count = val.getFdCount();

  300. err = this->writeInt32(len);

  301. if (err) return err;

  302. err = this->writeInt32(fd_count);

  303. if (err) return err;

  304. // payload

  305. void* buf = this->writeInplace(PAD_SIZE(len));

  306. if (buf == NULL)

  307. return BAD_VALUE;

  308. int* fds = NULL;

  309. if (fd_count) {

  310. fds = new int[fd_count];

  311. }

  312. err = val.flatten(buf, len, fds, fd_count);

  313. for (size_t i=0 ; i<fd_count && err==NO_ERROR ; i++) {

  314. err = this->writeDupFileDescriptor( fds[i] );

  315. }

  316. if (fd_count) {

  317. delete [] fds;

  318. }

  319. return err;

  320. }

  321. status_t Parcel::writeObject(const flat_binder_object& val, bool nullMetaData)

  322. {

  323. const bool enoughData = (mDataPos+sizeof(val)) <= mDataCapacity;

  324. const bool enoughObjects = mObjectsSize < mObjectsCapacity;

  325. if (enoughData && enoughObjects) {

  326. restart_write:

  327. *reinterpret_cast<flat_binder_object*>(mData+mDataPos) = val;

  328. // Need to write meta-data?

  329. if (nullMetaData || val.binder != NULL) {

  330. mObjects[mObjectsSize] = mDataPos;

  331. acquire_object(ProcessState::self(), val, this);

  332. mObjectsSize++;

  333. }

  334. // remember if it’s a file descriptor

  335. if (val.type == BINDER_TYPE_FD) {

  336. mHasFds = mFdsKnown = true;

  337. }

  338. return finishWrite(sizeof(flat_binder_object));

  339. }

  340. if (!enoughData) {

  341. const status_t err = growData(sizeof(val));

  342. if (err != NO_ERROR) return err;

  343. }

  344. if (!enoughObjects) {

  345. size_t newSize = ((mObjectsSize+2)*3)/2;

  346. size_t* objects = (size_t*)realloc(mObjects, newSize*sizeof(size_t));

  347. if (objects == NULL) return NO_MEMORY;

  348. mObjects = objects;

  349. mObjectsCapacity = newSize;

  350. }

  351. goto restart_write;

  352. }

  353. void Parcel::remove(size_t start, size_t amt)

  354. {

  355. LOG_ALWAYS_FATAL(“Parcel::remove() not yet implemented!”);

  356. }

  357. status_t Parcel::read(void* outData, size_t len) const

  358. {

  359. if ((mDataPos+PAD_SIZE(len)) >= mDataPos && (mDataPos+PAD_SIZE(len)) <= mDataSize) {

  360. memcpy(outData, mData+mDataPos, len);

  361. mDataPos += PAD_SIZE(len);

  362. LOGV(“read Setting data pos of %p to %d/n”, this, mDataPos);

  363. return NO_ERROR;

  364. }

  365. return NOT_ENOUGH_DATA;

  366. }

  367. const void* Parcel::readInplace(size_t len) const

  368. {

  369. if ((mDataPos+PAD_SIZE(len)) >= mDataPos && (mDataPos+PAD_SIZE(len)) <= mDataSize) {

  370. const void* data = mData+mDataPos;

  371. mDataPos += PAD_SIZE(len);

  372. LOGV(“readInplace Setting data pos of %p to %d/n”, this, mDataPos);

  373. return data;

  374. }

  375. return NULL;

  376. }

  377. template

  378. status_t Parcel::readAligned(T *pArg) const {

  379. COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE(sizeof(T)) == sizeof(T));

  380. if ((mDataPos+sizeof(T)) <= mDataSize) {

  381. const void* data = mData+mDataPos;

  382. mDataPos += sizeof(T);

  383. *pArg =  *reinterpret_cast<const T*>(data);

  384. return NO_ERROR;

  385. } else {

  386. return NOT_ENOUGH_DATA;

  387. }

  388. }

  389. template

  390. T Parcel::readAligned() const {

  391. T result;

  392. if (readAligned(&result) != NO_ERROR) {

  393. result = 0;

  394. }

  395. return result;

  396. }

  397. template

  398. status_t Parcel::writeAligned(T val) {

  399. COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE(sizeof(T)) == sizeof(T));

  400. if ((mDataPos+sizeof(val)) <= mDataCapacity) {

  401. restart_write:

  402. *reinterpret_cast<T*>(mData+mDataPos) = val;

  403. return finishWrite(sizeof(val));

  404. }

  405. status_t err = growData(sizeof(val));

  406. if (err == NO_ERROR) goto restart_write;

  407. return err;

  408. }

  409. status_t Parcel::readInt32(int32_t *pArg) const

  410. {

  411. return readAligned(pArg);

  412. }

  413. int32_t Parcel::readInt32() const

  414. {

  415. return readAligned<int32_t>();

  416. }

  417. status_t Parcel::readInt64(int64_t *pArg) const

  418. {

  419. return readAligned(pArg);

  420. }

  421. int64_t Parcel::readInt64() const

  422. {

  423. return readAligned<int64_t>();

  424. }

  425. status_t Parcel::readFloat(float *pArg) const

  426. {

  427. return readAligned(pArg);

  428. }

  429. float Parcel::readFloat() const

  430. {

  431. return readAligned<float>();

  432. }

  433. status_t Parcel::readDouble(double *pArg) const

  434. {

  435. return readAligned(pArg);

  436. }

  437. double Parcel::readDouble() const

  438. {

  439. return readAligned<double>();

  440. }

  441. status_t Parcel::readIntPtr(intptr_t *pArg) const

  442. {

  443. return readAligned(pArg);

  444. }

  445. intptr_t Parcel::readIntPtr() const

  446. {

  447. return readAligned<intptr_t>();

  448. }

  449. const char* Parcel::readCString() const

  450. {

  451. const size_t avail = mDataSize-mDataPos;

  452. if (avail > 0) {

  453. const char* str = reinterpret_cast<const char*>(mData+mDataPos);

  454. // is the string’s trailing NUL within the parcel’s valid bounds?

  455. const char* eos = reinterpret_cast<const char*>(memchr(str, 0, avail));

  456. if (eos) {

  457. const size_t len = eos - str;

  458. mDataPos += PAD_SIZE(len+1);

  459. LOGV(“readCString Setting data pos of %p to %d/n”, this, mDataPos);

  460. return str;

  461. }

  462. }

  463. return NULL;

  464. }

  465. String8 Parcel::readString8() const

  466. {

  467. int32_t size = readInt32();

  468. // watch for potential int overflow adding 1 for trailing NUL

  469. if (size > 0 && size < INT32_MAX) {

  470. const char* str = (const char*)readInplace(size+1);

  471. if (str) return String8(str, size);

  472. }

  473. return String8();

  474. }

  475. String16 Parcel::readString16() const

  476. {

  477. size_t len;

  478. const char16_t* str = readString16Inplace(&len);

  479. if (str) return String16(str, len);

  480. LOGE(“Reading a NULL string not supported here.”);

  481. return String16();

  482. }

  483. const char16_t* Parcel::readString16Inplace(size_t* outLen) const

  484. {

  485. int32_t size = readInt32();

  486. // watch for potential int overflow from size+1

  487. if (size >= 0 && size < INT32_MAX) {

  488. *outLen = size;

  489. const char16_t* str = (const char16_t*)readInplace((size+1)*sizeof(char16_t));

  490. if (str != NULL) {

  491. return str;

  492. }

  493. }

  494. *outLen = 0;

  495. return NULL;

  496. }

  497. sp Parcel::readStrongBinder() const

  498. {

  499. sp val;

  500. unflatten_binder(ProcessState::self(), *this, &val);

  501. return val;

  502. }

  503. wp Parcel::readWeakBinder() const

  504. {

  505. wp val;

  506. unflatten_binder(ProcessState::self(), *this, &val);

  507. return val;

  508. }

  509. native_handle* Parcel::readNativeHandle() const

  510. {

  511. int numFds, numInts;

  512. status_t err;

  513. err = readInt32(&numFds);

  514. if (err != NO_ERROR) return 0;

  515. err = readInt32(&numInts);

  516. if (err != NO_ERROR) return 0;

  517. native_handle* h = native_handle_create(numFds, numInts);

  518. for (int i=0 ; err==NO_ERROR && i<numFds ; i++) {

  519. h->data[i] = dup(readFileDescriptor());

  520. if (h->data[i] < 0) err = BAD_VALUE;

  521. }

  522. err = read(h->data + numFds, sizeof(int)*numInts);

  523. if (err != NO_ERROR) {

  524. native_handle_close(h);

  525. native_handle_delete(h);

  526. h = 0;

  527. }

  528. return h;

  529. }

  530. int Parcel::readFileDescriptor() const

  531. {

  532. const flat_binder_object* flat = readObject(true);

  533. if (flat) {

  534. switch (flat->type) {

  535. case BINDER_TYPE_FD:

  536. //LOGI(“Returning file descriptor %ld from parcel %p/n”, flat->handle, this);

  537. return flat->handle;

  538. }

  539. }

  540. return BAD_TYPE;

  541. }

  542. status_t Parcel::read(Flattenable& val) const

  543. {

  544. // size

  545. const size_t len = this->readInt32();

  546. const size_t fd_count = this->readInt32();

  547. // payload

  548. void const* buf = this->readInplace(PAD_SIZE(len));

  549. if (buf == NULL)

  550. return BAD_VALUE;

  551. int* fds = NULL;

  552. if (fd_count) {

  553. fds = new int[fd_count];

  554. }

  555. status_t err = NO_ERROR;

  556. for (size_t i=0 ; i<fd_count && err==NO_ERROR ; i++) {

  557. fds[i] = dup(this->readFileDescriptor());

  558. if (fds[i] < 0) err = BAD_VALUE;

  559. }

  560. if (err == NO_ERROR) {

  561. err = val.unflatten(buf, len, fds, fd_count);

  562. }

  563. if (fd_count) {

  564. delete [] fds;

  565. }

  566. return err;

  567. }

  568. const flat_binder_object* Parcel::readObject(bool nullMetaData) const

  569. {

  570. const size_t DPOS = mDataPos;

  571. if ((DPOS+sizeof(flat_binder_object)) <= mDataSize) {

  572. const flat_binder_object* obj

  573. = reinterpret_cast<const flat_binder_object*>(mData+DPOS);

  574. mDataPos = DPOS + sizeof(flat_binder_object);

  575. if (!nullMetaData && (obj->cookie == NULL && obj->binder == NULL)) {

  576. // When transferring a NULL object, we don’t write it into

  577. // the object list, so we don’t want to check for it when

  578. // reading.

  579. LOGV(“readObject Setting data pos of %p to %d/n”, this, mDataPos);

  580. return obj;

  581. }

  582. // Ensure that this object is valid…

  583. size_t* const OBJS = mObjects;

  584. const size_t N = mObjectsSize;

  585. size_t opos = mNextObjectHint;

  586. if (N > 0) {

  587. LOGV(“Parcel %p looking for obj at %d, hint=%d/n”,

  588. this, DPOS, opos);

  589. // Start at the current hint position, looking for an object at

  590. // the current data position.

  591. if (opos < N) {

  592. while (opos < (N-1) && OBJS[opos] < DPOS) {

  593. opos++;

  594. }

  595. } else {

  596. opos = N-1;

  597. }

  598. if (OBJS[opos] == DPOS) {

  599. // Found it!

  600. LOGV(“Parcel found obj %d at index %d with forward search”,

  601. this, DPOS, opos);

  602. mNextObjectHint = opos+1;

  603. LOGV(“readObject Setting data pos of %p to %d/n”, this, mDataPos);

  604. return obj;

  605. }

  606. // Look backwards for it…

  607. while (opos > 0 && OBJS[opos] > DPOS) {

  608. opos–;

  609. }

  610. if (OBJS[opos] == DPOS) {

  611. // Found it!

  612. LOGV(“Parcel found obj %d at index %d with backward search”,

  613. this, DPOS, opos);

  614. mNextObjectHint = opos+1;

  615. LOGV(“readObject Setting data pos of %p to %d/n”, this, mDataPos);

  616. return obj;

  617. }

  618. }

  619. LOGW(“Attempt to read object from Parcel %p at offset %d that is not in the object list”,

  620. this, DPOS);

  621. }

  622. return NULL;

  623. }

  624. void Parcel::closeFileDescriptors()

  625. {

  626. size_t i = mObjectsSize;

  627. if (i > 0) {

  628. //LOGI(“Closing file descriptors for %d objects…”, mObjectsSize);

  629. }

  630. while (i > 0) {

  631. i–;

  632. const flat_binder_object* flat

  633. = reinterpret_cast<flat_binder_object*>(mData+mObjects[i]);

  634. if (flat->type == BINDER_TYPE_FD) {

  635. //LOGI(“Closing fd: %ld/n”, flat->handle);

  636. close(flat->handle);

  637. }

  638. }

  639. }

  640. const uint8_t* Parcel::ipcData() const

  641. {

  642. return mData;

  643. }

  644. size_t Parcel::ipcDataSize() const

  645. {

  646. return (mDataSize > mDataPos ? mDataSize : mDataPos);

  647. }

  648. const size_t* Parcel::ipcObjects() const

  649. {

  650. return mObjects;

  651. }

  652. size_t Parcel::ipcObjectsCount() const

  653. {

  654. return mObjectsSize;

  655. }

  656. void Parcel::ipcSetDataReference(const uint8_t* data, size_t dataSize,

  657. const size_t* objects, size_t objectsCount, release_func relFunc, void* relCookie)

  658. {

  659. freeDataNoInit();

  660. mError = NO_ERROR;

  661. mData = const_cast<uint8_t*>(data);

  662. mDataSize = mDataCapacity = dataSize;

  663. //LOGI(“setDataReference Setting data size of %p to %lu (pid=%d)/n”, this, mDataSize, getpid());

  664. mDataPos = 0;

  665. LOGV(“setDataReference Setting data pos of %p to %d/n”, this, mDataPos);

  666. mObjects = const_cast<size_t*>(objects);

  667. mObjectsSize = mObjectsCapacity = objectsCount;

  668. mNextObjectHint = 0;

  669. mOwner = relFunc;

  670. mOwnerCookie = relCookie;

  671. scanForFds();

  672. }

  673. void Parcel::print(TextOutput& to, uint32_t flags) const

  674. {

  675. to << “Parcel(”;

  676. if (errorCheck() != NO_ERROR) {

  677. const status_t err = errorCheck();

  678. to << “Error: " << (void*)err << " /”" << strerror(-err) << “/”";

  679. } else if (dataSize() > 0) {

  680. const uint8_t* DATA = data();

  681. to << indent << HexDump(DATA, dataSize()) << dedent;

  682. const size_t* OBJS = objects();

  683. const size_t N = objectsCount();

  684. for (size_t i=0; i<N; i++) {

  685. const flat_binder_object* flat

  686. = reinterpret_cast<const flat_binder_object*>(DATA+OBJS[i]);

  687. to << endl << “Object #” << i << " @ " << (void*)OBJS[i] << ": "

  688. << TypeCode(flat->type & 0x7f7f7f00)

  689. << " = " << flat->binder;

  690. }

  691. } else {

  692. to << “NULL”;

  693. }

  694. to << “)”;

  695. }

  696. void Parcel::releaseObjects()

  697. {

  698. const sp proc(ProcessState::self());

  699. size_t i = mObjectsSize;

  700. uint8_t* const data = mData;

  701. size_t* const objects = mObjects;

  702. while (i > 0) {

  703. i–;

  704. const flat_binder_object* flat

  705. = reinterpret_cast<flat_binder_object*>(data+objects[i]);

  706. release_object(proc, *flat, this);

  707. }

  708. }

  709. void Parcel::acquireObjects()

  710. {

  711. const sp proc(ProcessState::self());

  712. size_t i = mObjectsSize;

  713. uint8_t* const data = mData;

  714. size_t* const objects = mObjects;

  715. while (i > 0) {

  716. i–;

  717. const flat_binder_object* flat

  718. = reinterpret_cast<flat_binder_object*>(data+objects[i]);

  719. acquire_object(proc, *flat, this);

  720. }

  721. }

  722. void Parcel::freeData()

  723. {

  724. freeDataNoInit();

  725. initState();

  726. }

  727. void Parcel::freeDataNoInit()

  728. {

  729. if (mOwner) {

  730. //LOGI(“Freeing data ref of %p (pid=%d)/n”, this, getpid());

  731. mOwner(this, mData, mDataSize, mObjects, mObjectsSize, mOwnerCookie);

  732. } else {

  733. releaseObjects();

  734. if (mData) free(mData);

  735. if (mObjects) free(mObjects);

  736. }

  737. }

  738. status_t Parcel::growData(size_t len)

  739. {

  740. size_t newSize = ((mDataSize+len)*3)/2;

  741. return (newSize <= mDataSize)

  742. ? (status_t) NO_MEMORY

  743. : continueWrite(newSize);

  744. }

  745. status_t Parcel::restartWrite(size_t desired)

  746. {

  747. if (mOwner) {

  748. freeData();

  749. return continueWrite(desired);

  750. }

  751. uint8_t* data = (uint8_t*)realloc(mData, desired);

  752. if (!data && desired > mDataCapacity) {

  753. mError = NO_MEMORY;

  754. return NO_MEMORY;

  755. }

  756. releaseObjects();

  757. if (data) {

  758. mData = data;

  759. mDataCapacity = desired;

  760. }

  761. mDataSize = mDataPos = 0;

  762. LOGV(“restartWrite Setting data size of %p to %d/n”, this, mDataSize);

  763. LOGV(“restartWrite Setting data pos of %p to %d/n”, this, mDataPos);

  764. free(mObjects);

  765. mObjects = NULL;

  766. mObjectsSize = mObjectsCapacity = 0;

  767. mNextObjectHint = 0;

  768. mHasFds = false;

  769. mFdsKnown = true;

  770. return NO_ERROR;

  771. }

  772. status_t Parcel::continueWrite(size_t desired)

  773. {

  774. // If shrinking, first adjust for any objects that appear

  775. // after the new data size.

  776. size_t objectsSize = mObjectsSize;

  777. if (desired < mDataSize) {

  778. if (desired == 0) {

  779. objectsSize = 0;

  780. } else {

  781. while (objectsSize > 0) {

  782. if (mObjects[objectsSize-1] < desired)

  783. break;

  784. objectsSize–;

  785. }

  786. }

  787. }

  788. if (mOwner) {

  789. // If the size is going to zero, just release the owner’s data.

  790. if (desired == 0) {

  791. freeData();

  792. return NO_ERROR;

  793. }

  794. // If there is a different owner, we need to take

  795. // posession.

  796. uint8_t* data = (uint8_t*)malloc(desired);

  797. if (!data) {

  798. mError = NO_MEMORY;

  799. return NO_MEMORY;

  800. }

  801. size_t* objects = NULL;

  802. if (objectsSize) {

  803. objects = (size_t*)malloc(objectsSize*sizeof(size_t));

  804. if (!objects) {

  805. mError = NO_MEMORY;

  806. return NO_MEMORY;

  807. }

  808. // Little hack to only acquire references on objects

  809. // we will be keeping.

  810. size_t oldObjectsSize = mObjectsSize;

  811. mObjectsSize = objectsSize;

  812. acquireObjects();

  813. mObjectsSize = oldObjectsSize;

  814. }

  815. if (mData) {

  816. memcpy(data, mData, mDataSize < desired ? mDataSize : desired);

  817. }

  818. if (objects && mObjects) {

  819. memcpy(objects, mObjects, objectsSize*sizeof(size_t));

  820. }

  821. //LOGI(“Freeing data ref of %p (pid=%d)/n”, this, getpid());

  822. mOwner(this, mData, mDataSize, mObjects, mObjectsSize, mOwnerCookie);

  823. mOwner = NULL;

  824. mData = data;

  825. mObjects = objects;

  826. mDataSize = (mDataSize < desired) ? mDataSize : desired;

  827. LOGV(“continueWrite Setting data size of %p to %d/n”, this, mDataSize);

  828. mDataCapacity = desired;

  829. mObjectsSize = mObjectsCapacity = objectsSize;

  830. mNextObjectHint = 0;

  831. } else if (mData) {

  832. if (objectsSize < mObjectsSize) {

  833. // Need to release refs on any objects we are dropping.

  834. const sp proc(ProcessState::self());

  835. for (size_t i=objectsSize; i<mObjectsSize; i++) {

  836. const flat_binder_object* flat

  837. = reinterpret_cast<flat_binder_object*>(mData+mObjects[i]);

  838. if (flat->type == BINDER_TYPE_FD) {

  839. // will need to rescan because we may have lopped off the only FDs

  840. mFdsKnown = false;

  841. }

  842. release_object(proc, *flat, this);

  843. }

  844. size_t* objects =

  845. (size_t*)realloc(mObjects, objectsSize*sizeof(size_t));

  846. if (objects) {

  847. mObjects = objects;

  848. }

  849. mObjectsSize = objectsSize;

  850. mNextObjectHint = 0;

  851. }

  852. // We own the data, so we can just do a realloc().

  853. if (desired > mDataCapacity) {

  854. uint8_t* data = (uint8_t*)realloc(mData, desired);

  855. if (data) {

  856. mData = data;

  857. mDataCapacity = desired;

  858. } else if (desired > mDataCapacity) {

  859. mError = NO_MEMORY;

  860. return NO_MEMORY;

  861. }

  862. } else {

  863. mDataSize = desired;

  864. LOGV(“continueWrite Setting data size of %p to %d/n”, this, mDataSize);

  865. if (mDataPos > desired) {

  866. mDataPos = desired;

  867. LOGV(“continueWrite Setting data pos of %p to %d/n”, this, mDataPos);

  868. }

  869. }

  870. } else {

  871. // This is the first data.  Easy!

  872. uint8_t* data = (uint8_t*)malloc(desired);

  873. if (!data) {

  874. mError = NO_MEMORY;

  875. return NO_MEMORY;

  876. }

  877. if(!(mDataCapacity == 0 && mObjects == NULL

  878. && mObjectsCapacity == 0)) {

  879. LOGE(“continueWrite: %d/%p/%d/%d”, mDataCapacity, mObjects, mObjectsCapacity, desired);

  880. }

  881. mData = data;

  882. mDataSize = mDataPos = 0;

  883. LOGV(“continueWrite Setting data size of %p to %d/n”, this, mDataSize);

  884. LOGV(“continueWrite Setting data pos of %p to %d/n”, this, mDataPos);

  885. mDataCapacity = desired;

  886. }

  887. return NO_ERROR;

  888. }

  889. void Parcel::initState()

  890. {

  891. mError = NO_ERROR;

  892. mData = 0;

  893. mDataSize = 0;

  894. mDataCapacity = 0;

  895. mDataPos = 0;

  896. LOGV(“initState Setting data size of %p to %d/n”, this, mDataSize);

  897. LOGV(“initState Setting data pos of %p to %d/n”, this, mDataPos);

  898. mObjects = NULL;

  899. mObjectsSize = 0;

  900. mObjectsCapacity = 0;

  901. mNextObjectHint = 0;

  902. mHasFds = false;

  903. mFdsKnown = true;

  904. mOwner = NULL;

  905. }

  906. void Parcel::scanForFds() const

  907. {

  908. bool hasFds = false;

  909. for (size_t i=0; i<mObjectsSize; i++) {

  910. const flat_binder_object* flat

  911. = reinterpret_cast<const flat_binder_object*>(mData + mObjects[i]);

  912. if (flat->type == BINDER_TYPE_FD) {

  913. hasFds = true;

  914. break;

  915. }

  916. }

  917. mHasFds = hasFds;

  918. mFdsKnown = true;

  919. }

  920. }; // namespace android

本文的源码使用的是Android 2.1版本。

上一篇中我们透过源码看到了Parcel背后的机制,本质上把它当成一个Serialize就可以了,只是它是在内存中完成的序列化和反序列化,利用的是连续的内存空间,因此会更加高效。

我们接下来要说的是Parcel类如何应用。就应用程序而言,最常见使用Parcel类的场景就是在Activity间传递数据。没错,在Activity间使用Intent传递数据的时候,可以通过Parcelable机制传递复杂的对象。

在下面的程序中,MyColor用于保存一个颜色值,MainActivity在用户点击屏幕时将MyColor对象设成红色,传递到SubActivity中,此时SubActivity的TextView显示为红色的背景;当点击SubActivity时,将颜色值改为绿色,返回MainActivity,期望的是MainActivity的TextView显示绿色背景。

来看一下MyColor类的实现代码:

[java]  view plain copy

  1. package com.wenbin.test;

  2. import android.graphics.Color;

  3. import android.os.Parcel;

  4. import android.os.Parcelable;

  5. /**

  6. * @author 曹文斌

  7. * http://blog.csdn.net/caowenbin

  8. *

  9. */

  10. public class MyColor implements Parcelable {

  11. private int color=Color.BLACK;

  12. MyColor(){

  13. color=Color.BLACK;

  14. }

  15. MyColor(Parcel in){

  16. color=in.readInt();

  17. }

  18. public int getColor(){

  19. return color;

  20. }

  21. public void setColor(int color){

  22. this.color=color;

  23. }

  24. @Override

  25. public int describeContents() {

  26. return 0;

  27. }

  28. @Override

  29. public void writeToParcel(Parcel dest, int flags) {

  30. dest.writeInt(color);

  31. }

  32. public static final Parcelable.Creator CREATOR

  33. = new Parcelable.Creator() {

  34. public MyColor createFromParcel(Parcel in) {

  35. return new MyColor(in);

  36. }

  37. public MyColor[] newArray(int size) {

  38. return new MyColor[size];

  39. }

  40. };

  41. }

该类实现了Parcelable接口,提供了默认的构造函数,同时也提供了可从Parcel对象开始的构造函数,另外还实现了一个static的构造器用于构造对象和数组。代码很简单,不一一解释了。

再看MainActivity的代码:

[java]  view plain copy

  1. package com.wenbin.test;

  2. import android.app.Activity;

  3. import android.content.Intent;

  4. import android.graphics.Color;

  5. import android.os.Bundle;

  6. import android.view.MotionEvent;

  7. /**

  8. * @author 曹文斌

  9. * http://blog.csdn.net/caowenbin

  10. *

  11. */

  12. public class MainActivity extends Activity {

  13. private final int SUB_ACTIVITY=0;

  14. private MyColor color=new MyColor();

  15. @Override

  16. public void onCreate(Bundle savedInstanceState) {

  17. super.onCreate(savedInstanceState);

  18. setContentView(R.layout.main);

  19. }

  20. @Override

  21. protected void onActivityResult(int requestCode, int resultCode, Intent data) {

  22. super.onActivityResult(requestCode, resultCode, data);

  23. if (requestCode==SUB_ACTIVITY){

  24. if (resultCode==RESULT_OK){

  25. if (data.hasExtra(“MyColor”)){

  26. color=data.getParcelableExtra(“MyColor”);  //Notice

  27. findViewById(R.id.text).setBackgroundColor(color.getColor());

  28. }

  29. }

  30. }

  31. }

  32. @Override

  33. public boolean onTouchEvent(MotionEvent event){

  34. if (event.getAction()==MotionEvent.ACTION_UP){

  35. Intent intent=new Intent();

  36. intent.setClass(this, SubActivity.class);

  37. color.setColor(Color.RED);

  38. intent.putExtra(“MyColor”, color);

  39. startActivityForResult(intent,SUB_ACTIVITY);

  40. }

  41. return super.onTouchEvent(event);

  42. }

  43. }

下面是SubActivity的代码:

[java]  view plain copy

  1. package com.wenbin.test;

  2. import android.app.Activity;

  3. import android.content.Intent;

  4. import android.graphics.Color;

  5. import android.os.Bundle;

  6. import android.view.MotionEvent;

  7. import android.widget.TextView;

  8. /**

  9. * @author 曹文斌

  10. * http://blog.csdn.net/caowenbin

  11. *

  12. */

  13. public class SubActivity extends Activity {

  14. private MyColor color;

  15. @Override

  16. public void onCreate(Bundle savedInstanceState) {

  17. super.onCreate(savedInstanceState);

  18. setContentView(R.layout.main);

  19. ((TextView)findViewById(R.id.text)).setText(“SubActivity”);

  20. Intent intent=getIntent();

  21. if (intent!=null){

  22. if (intent.hasExtra(“MyColor”)){

  23. color=intent.getParcelableExtra(“MyColor”);

  24. findViewById(R.id.text).setBackgroundColor(color.getColor());

  25. }

  26. }

  27. }

  28. @Override

  29. public boolean onTouchEvent(MotionEvent event){

  30. if (event.getAction()==MotionEvent.ACTION_UP){

  31. Intent intent=new Intent();

  32. if (color!=null){

  33. color.setColor(Color.GREEN);

  34. intent.putExtra(“MyColor”, color);

  35. }

  36. setResult(RESULT_OK,intent);

  37. finish();

  38. }

  39. return super.onTouchEvent(event);

  40. }

  41. }

下面是main.xml的代码:

[xhtml]  view plain copy

  1. <?xml version\="1.0" encoding\="utf-8"?>  
  2. <LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”

  3. android:orientation=“vertical”

  4. android:layout_width=“fill_parent”

  5. android:layout_height=“fill_parent”

  6. >

  7. <TextView

  8. android:layout_width=“fill_parent”

  9. android:layout_height=“wrap_content”

  10. android:text=“@string/hello”

  11. android:id=“@+id/text”

  12. />

  13. </LinearLayout>

注意的是在MainActivity的onActivityResult()中,有一句color=data.getParcelableExtra(“MyColor”),这说明的是反序列化后是一个新的MyColor对象,因此要想使用这个对象,我们做了这个赋值语句。

记得在上一篇《探索Android中的Parcel机制(上)》中提到,如果数据本身是IBinder类型,那么反序列化的结果就是原对象,而不是新建的对象,很显然,如果是这样的话,在反序列化后在MainActivity中就不再需要color=data.getParcelableExtra(“MyColor”)这句了。因此,换一种MyColor的实现方法,令其中的int color成员变量使用IBinder类型的成员变量来表示。

新建一个BinderData类继承自Binder,代码如下:

[java]  view plain copy

  1. package com.wenbin.test;

  2. import android.os.Binder;

  3. /**

  4. * @author 曹文斌

  5. * http://blog.csdn.net/caowenbin

  6. *

  7. */

  8. public class BinderData extends Binder {

  9. public int color;

  10. }

修改MyColor的代码如下:

[java]  view plain copy

  1. package com.wenbin.test;

  2. import android.graphics.Color;

  3. import android.os.Parcel;

  4. import android.os.Parcelable;

  5. /**

  6. * @author 曹文斌

  7. * http://blog.csdn.net/caowenbin

  8. *

  9. */

  10. public class MyColor implements Parcelable {

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

作者2013年从java开发,转做Android开发,在小厂待过,也去过华为,OPPO等大厂待过,18年四月份进了阿里一直到现在。

参与过不少面试,也当面试官 面试过很多人。深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长,而且极易碰到天花板技术停滞不前!

我整理了一份阿里P7级别的最系统的Android开发主流技术,特别适合有3-5年以上经验的小伙伴深入学习提升。

主要包括阿里,以及字节跳动,腾讯,华为,小米,等一线互联网公司主流架构技术。如果你想深入系统学习Android开发,成为一名合格的高级工程师,可以收藏一下这些Android进阶技术选型

我搜集整理过这几年阿里,以及腾讯,字节跳动,华为,小米等公司的面试题,把面试的要求和技术点梳理成一份大而全的“ Android架构师”面试 Xmind(实际上比预期多花了不少精力),包含知识脉络 + 分支细节。

Java语言与原理;
大厂,小厂。Android面试先看你熟不熟悉Java语言

高级UI与自定义view;
自定义view,Android开发的基本功。

性能调优;
数据结构算法,设计模式。都是这里面的关键基础和重点需要熟练的。

NDK开发;
未来的方向,高薪必会。

前沿技术;
组件化,热升级,热修复,框架设计

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

我在搭建这些技术框架的时候,还整理了系统的高级进阶教程,会比自己碎片化学习效果强太多,CodeChina上可见;

当然,想要深入学习并掌握这些能力,并不简单。关于如何学习,做程序员这一行什么工作强度大家都懂,但是不管工作多忙,每周也要雷打不动的抽出 2 小时用来学习。

不出半年,你就能看出变化!

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

import android.os.Binder;

  1. /**

  2. * @author 曹文斌

  3. * http://blog.csdn.net/caowenbin

  4. *

  5. */

  6. public class BinderData extends Binder {

  7. public int color;

  8. }

修改MyColor的代码如下:

[java]  view plain copy

  1. package com.wenbin.test;

  2. import android.graphics.Color;

  3. import android.os.Parcel;

  4. import android.os.Parcelable;

  5. /**

  6. * @author 曹文斌

  7. * http://blog.csdn.net/caowenbin

  8. *

  9. */

  10. public class MyColor implements Parcelable {

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-oNxddtHS-1712376788619)]

[外链图片转存中…(img-N843CVe3-1712376788620)]

[外链图片转存中…(img-2c8F89ib-1712376788620)]

[外链图片转存中…(img-lhhoSEoO-1712376788620)]

[外链图片转存中…(img-oW19rWXz-1712376788621)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

作者2013年从java开发,转做Android开发,在小厂待过,也去过华为,OPPO等大厂待过,18年四月份进了阿里一直到现在。

参与过不少面试,也当面试官 面试过很多人。深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长,而且极易碰到天花板技术停滞不前!

我整理了一份阿里P7级别的最系统的Android开发主流技术,特别适合有3-5年以上经验的小伙伴深入学习提升。

主要包括阿里,以及字节跳动,腾讯,华为,小米,等一线互联网公司主流架构技术。如果你想深入系统学习Android开发,成为一名合格的高级工程师,可以收藏一下这些Android进阶技术选型

我搜集整理过这几年阿里,以及腾讯,字节跳动,华为,小米等公司的面试题,把面试的要求和技术点梳理成一份大而全的“ Android架构师”面试 Xmind(实际上比预期多花了不少精力),包含知识脉络 + 分支细节。

[外链图片转存中…(img-lpwroPaq-1712376788621)]

Java语言与原理;
大厂,小厂。Android面试先看你熟不熟悉Java语言

[外链图片转存中…(img-uqyWAF9F-1712376788621)]

高级UI与自定义view;
自定义view,Android开发的基本功。

[外链图片转存中…(img-G5losp35-1712376788622)]

性能调优;
数据结构算法,设计模式。都是这里面的关键基础和重点需要熟练的。

[外链图片转存中…(img-IH7g0sEP-1712376788622)]

NDK开发;
未来的方向,高薪必会。

[外链图片转存中…(img-AWcjwxcg-1712376788622)]

前沿技术;
组件化,热升级,热修复,框架设计

[外链图片转存中…(img-VwXIL2Nx-1712376788622)]

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

我在搭建这些技术框架的时候,还整理了系统的高级进阶教程,会比自己碎片化学习效果强太多,CodeChina上可见;

当然,想要深入学习并掌握这些能力,并不简单。关于如何学习,做程序员这一行什么工作强度大家都懂,但是不管工作多忙,每周也要雷打不动的抽出 2 小时用来学习。

不出半年,你就能看出变化!

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值