Compare commits
	
		
			467 Commits
		
	
	
		
			1.0.5
			...
			ubports/fo
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 2778ec3a88 | |||
| 6697470380 | |||
| 
						 | 
					a9dfd6e453 | ||
| 
						 | 
					2439ff878d | ||
| 
						 | 
					8c65520173 | ||
| 
						 | 
					e3764d7002 | ||
| 
						 | 
					624bfa843d | ||
| 
						 | 
					6d71a0649c | ||
| 
						 | 
					c31cd7e964 | ||
| 
						 | 
					c1db86e734 | ||
| 
						 | 
					bfb95f2bf5 | ||
| 
						 | 
					6f4c69d58a | ||
| 
						 | 
					c6b09a10d4 | ||
| 
						 | 
					545f5bc28d | ||
| 
						 | 
					78e006f1cf | ||
| 
						 | 
					3c9cc1711a | ||
| 
						 | 
					71aa3acc08 | ||
| 
						 | 
					eee26c5e98 | ||
| 
						 | 
					736a29aa4c | ||
| 
						 | 
					0d7105edbe | ||
| 
						 | 
					4420c7b2ae | ||
| 
						 | 
					52726a07b0 | ||
| 
						 | 
					12b9fd49ad | ||
| 
						 | 
					e75959e389 | ||
| 
						 | 
					9d35ca22fb | ||
| 
						 | 
					3e0d0005ce | ||
| 
						 | 
					29718f921f | ||
| 
						 | 
					99b2dd85c1 | ||
| 
						 | 
					cf5417d5db | ||
| 
						 | 
					03f214eb24 | ||
| 
						 | 
					6508a73dcd | ||
| 
						 | 
					1100d8ede1 | ||
| 
						 | 
					f89469b1a5 | ||
| 
						 | 
					fcf2ef0ea4 | ||
| 
						 | 
					f9202cab37 | ||
| 
						 | 
					49729d95c9 | ||
| 
						 | 
					11765cd80d | ||
| 
						 | 
					4820b2971f | ||
| 
						 | 
					0623fb85db | ||
| 
						 | 
					e655d8992a | ||
| 
						 | 
					44e57ea98d | ||
| 
						 | 
					e3f705c4cc | ||
| 
						 | 
					6f0e8a693d | ||
| 
						 | 
					c7fab6373b | ||
| 
						 | 
					9aded94555 | ||
| 
						 | 
					b5bab2431e | ||
| 
						 | 
					509faccba0 | ||
| 
						 | 
					a89dcd2702 | ||
| 
						 | 
					62b9b30865 | ||
| 
						 | 
					4a913590d9 | ||
| 
						 | 
					1ee872aaf2 | ||
| 
						 | 
					00e9d8ac6f | ||
| 
						 | 
					b032e151a2 | ||
| 
						 | 
					b8edc9221a | ||
| 
						 | 
					05634757d7 | ||
| 
						 | 
					03ef78c9fd | ||
| 
						 | 
					84efc32ac0 | ||
| 
						 | 
					88388de696 | ||
| 
						 | 
					daa062d981 | ||
| 
						 | 
					85db18f663 | ||
| 
						 | 
					af796828a4 | ||
| 
						 | 
					885d27c12c | ||
| 
						 | 
					38f156a8ba | ||
| 
						 | 
					d7eacd455f | ||
| 
						 | 
					b1a3dc5c64 | ||
| 
						 | 
					98ad09e803 | ||
| 
						 | 
					c94ccbd8bf | ||
| 
						 | 
					5874c88559 | ||
| 
						 | 
					b0c3b6017f | ||
| 
						 | 
					4f82e82081 | ||
| 
						 | 
					51eefbf566 | ||
| 
						 | 
					ec76cb3930 | ||
| 
						 | 
					9a0d0a7894 | ||
| 
						 | 
					32b3d4455a | ||
| 
						 | 
					09e9a9d5c1 | ||
| 
						 | 
					83b04757c6 | ||
| 
						 | 
					c636814500 | ||
| 
						 | 
					2592ea60ce | ||
| 
						 | 
					f04e21b462 | ||
| 
						 | 
					d739912faa | ||
| 
						 | 
					c2263874ec | ||
| 
						 | 
					aa23e44677 | ||
| 
						 | 
					ca38c15d3c | ||
| 
						 | 
					6f9220aedb | ||
| 
						 | 
					eafec68ff8 | ||
| 
						 | 
					0dc84b0748 | ||
| 
						 | 
					f227ae4291 | ||
| 
						 | 
					b14b68717f | ||
| 
						 | 
					8bf0d63960 | ||
| 
						 | 
					c22eafe49e | ||
| 
						 | 
					66122a2ce6 | ||
| 
						 | 
					c1ff25f6ae | ||
| 
						 | 
					af3c23a18f | ||
| 
						 | 
					5a14796c4c | ||
| 
						 | 
					3bb8a38f5f | ||
| 
						 | 
					f29f0b5a1b | ||
| 
						 | 
					2da1c7b5ca | ||
| 
						 | 
					8348bc76bd | ||
| 
						 | 
					a97a153c94 | ||
| 
						 | 
					94ddc9f0e5 | ||
| 
						 | 
					370d2dedb3 | ||
| 
						 | 
					58c9a7fe93 | ||
| 
						 | 
					3742e2ca8e | ||
| 
						 | 
					ede15da9e2 | ||
| 
						 | 
					771444a8ac | ||
| 
						 | 
					956fa90cbf | ||
| 
						 | 
					17ff87510c | ||
| 
						 | 
					552fc4f172 | ||
| 
						 | 
					4b179477ad | ||
| 
						 | 
					8419a53f23 | ||
| 
						 | 
					865a29d1dd | ||
| 
						 | 
					93fbb5b238 | ||
| 
						 | 
					1a9408f65c | ||
| 
						 | 
					14399b112f | ||
| 
						 | 
					754fa5bcda | ||
| 
						 | 
					0b43f88700 | ||
| 
						 | 
					5822a40c39 | ||
| 
						 | 
					ca5f3ad0be | ||
| 
						 | 
					3398afd701 | ||
| 
						 | 
					3c828b453a | ||
| 
						 | 
					9d95a622f4 | ||
| 
						 | 
					78dd0563e6 | ||
| 
						 | 
					5fd5b423c1 | ||
| 
						 | 
					2acec3f7ce | ||
| 
						 | 
					59dee397f0 | ||
| 
						 | 
					e196c66264 | ||
| 
						 | 
					8f62f4d65c | ||
| 
						 | 
					8583a72d11 | ||
| 
						 | 
					381446eb4f | ||
| 
						 | 
					eabf5683f4 | ||
| 
						 | 
					f4712be3b5 | ||
| 
						 | 
					08f701c96b | ||
| 
						 | 
					8c5618aaab | ||
| 
						 | 
					1bc2efd724 | ||
| 
						 | 
					066464f3af | ||
| 
						 | 
					f5b399d775 | ||
| 
						 | 
					6e127bd184 | ||
| 
						 | 
					95277d1b3d | ||
| 
						 | 
					e0c56c1226 | ||
| 
						 | 
					5e3df46da9 | ||
| 
						 | 
					393006f051 | ||
| 
						 | 
					e10e3df1eb | ||
| 
						 | 
					86ba34dc67 | ||
| 
						 | 
					b0b5595f20 | ||
| 
						 | 
					757908cd6c | ||
| 
						 | 
					e6ca4b50ec | ||
| 
						 | 
					97831a65da | ||
| 
						 | 
					5798434ead | ||
| 
						 | 
					54b1149a75 | ||
| 
						 | 
					e9f873b3a4 | ||
| 
						 | 
					8b621fe7d3 | ||
| 
						 | 
					e5542027c2 | ||
| 
						 | 
					8539f6e944 | ||
| 
						 | 
					fa53d0cf70 | ||
| 
						 | 
					d6c3ddb4e3 | ||
| 
						 | 
					fd081601a3 | ||
| 
						 | 
					7b319ba822 | ||
| 
						 | 
					d439bd467a | ||
| 
						 | 
					c99df04daf | ||
| 
						 | 
					81b6b7f087 | ||
| 
						 | 
					91bc5253e4 | ||
| 
						 | 
					ddf67e83eb | ||
| 
						 | 
					fc257ec23c | ||
| 
						 | 
					8148f03ae6 | ||
| 
						 | 
					a1616163e7 | ||
| 
						 | 
					7f12f1a476 | ||
| 
						 | 
					f3cf738265 | ||
| 
						 | 
					f8916148a9 | ||
| 
						 | 
					fe2d441e25 | ||
| 
						 | 
					85c7d8f311 | ||
| 
						 | 
					597fb84367 | ||
| 
						 | 
					30242d7124 | ||
| 
						 | 
					14327ed5f1 | ||
| 
						 | 
					36e1fed889 | ||
| 
						 | 
					cecdea76bc | ||
| 
						 | 
					7f72021075 | ||
| 
						 | 
					846037073b | ||
| 
						 | 
					f0b55886b2 | ||
| 
						 | 
					165d386436 | ||
| 
						 | 
					a07e0f2a99 | ||
| 
						 | 
					bc172346e0 | ||
| 
						 | 
					5801ed4f15 | ||
| 
						 | 
					e8c5a0c0bb | ||
| 
						 | 
					94b74ee948 | ||
| 
						 | 
					1bfacab88d | ||
| 
						 | 
					704e7d011c | ||
| 
						 | 
					3a4ae9a716 | ||
| 
						 | 
					5ddc9d94d6 | ||
| 
						 | 
					159708d829 | ||
| 
						 | 
					5753cdab1a | ||
| 
						 | 
					d4ea1261eb | ||
| 
						 | 
					7e3ac0a761 | ||
| 
						 | 
					76494c3e3d | ||
| 
						 | 
					dfbc8acd9e | ||
| 
						 | 
					158d33db5a | ||
| 
						 | 
					4b11769895 | ||
| 
						 | 
					4da96dd0b5 | ||
| 
						 | 
					d9bfb9e200 | ||
| 
						 | 
					f088e6d1bb | ||
| 
						 | 
					ca665ad3d1 | ||
| 
						 | 
					6ed9082e69 | ||
| 
						 | 
					5332dd3482 | ||
| 
						 | 
					a15f63621e | ||
| 
						 | 
					e4b5f081bd | ||
| 
						 | 
					5fab0bcdaa | ||
| 
						 | 
					5c1b23f30e | ||
| 
						 | 
					8f720e11de | ||
| 
						 | 
					3c2cd5d599 | ||
| 
						 | 
					8df1e70c0b | ||
| 
						 | 
					3833a36693 | ||
| 
						 | 
					38fd1e6dcb | ||
| 
						 | 
					5fa4cd03de | ||
| 
						 | 
					d6c0cdd231 | ||
| 
						 | 
					c38843d9c9 | ||
| 
						 | 
					a6a5df963f | ||
| 
						 | 
					b60960d955 | ||
| 
						 | 
					0adb80a9ed | ||
| 
						 | 
					f591433118 | ||
| 
						 | 
					5a897a34c2 | ||
| 
						 | 
					138423de4a | ||
| 
						 | 
					1d9f9c4487 | ||
| 
						 | 
					82f71a6c91 | ||
| 
						 | 
					0c85299efc | ||
| 
						 | 
					50195aae1d | ||
| 
						 | 
					586425bc2d | ||
| 
						 | 
					b0bde6b652 | ||
| 
						 | 
					be2369c64c | ||
| 
						 | 
					c2cf68cab6 | ||
| 
						 | 
					f7d1863615 | ||
| 
						 | 
					0bb0aee6cb | ||
| 
						 | 
					b392e019f3 | ||
| 
						 | 
					8eb5fa7394 | ||
| 
						 | 
					c5c04db81a | ||
| 
						 | 
					4056cfaa15 | ||
| 
						 | 
					ba8b226d89 | ||
| 
						 | 
					88df2edb95 | ||
| 
						 | 
					b856cf2141 | ||
| 
						 | 
					f4a2429a13 | ||
| 
						 | 
					7d1f8ad4e7 | ||
| 
						 | 
					82656db49d | ||
| 
						 | 
					d6dac912dd | ||
| 
						 | 
					207f9398b4 | ||
| 
						 | 
					7b51a82de8 | ||
| 
						 | 
					66f08bf0db | ||
| 
						 | 
					90384e921f | ||
| 
						 | 
					1ae7c2697c | ||
| 
						 | 
					536143c1d7 | ||
| 
						 | 
					6025950aab | ||
| 
						 | 
					4d69940b96 | ||
| 
						 | 
					b1f49cae13 | ||
| 
						 | 
					80e9be5343 | ||
| 
						 | 
					d6d6b76fa5 | ||
| 
						 | 
					d18a352a82 | ||
| 
						 | 
					5fbaabb47e | ||
| 
						 | 
					83cc13b817 | ||
| 
						 | 
					1679cda4c5 | ||
| 
						 | 
					e5f11aafc1 | ||
| 
						 | 
					f262c77b17 | ||
| 
						 | 
					3ef00effc5 | ||
| 
						 | 
					1ce13bea91 | ||
| 
						 | 
					eaab366dcb | ||
| 
						 | 
					784f06c415 | ||
| 
						 | 
					4b07e80a8f | ||
| 
						 | 
					9f7fac407d | ||
| 
						 | 
					47b6668876 | ||
| 
						 | 
					951977961b | ||
| 
						 | 
					f069c3a595 | ||
| 
						 | 
					b84194e8c7 | ||
| 
						 | 
					e06e989aa5 | ||
| 
						 | 
					ab75505437 | ||
| 
						 | 
					e97663b58e | ||
| 
						 | 
					a92f57a30c | ||
| 
						 | 
					ebb9381e46 | ||
| 
						 | 
					5fb441fb81 | ||
| 
						 | 
					f3a00fe8a2 | ||
| 
						 | 
					573494570c | ||
| 
						 | 
					92392f5c9a | ||
| 
						 | 
					8a634a0d95 | ||
| 
						 | 
					23c5d48b5d | ||
| 
						 | 
					f000b344dd | ||
| 
						 | 
					42177e1ff2 | ||
| 
						 | 
					091ca483e7 | ||
| 
						 | 
					42ce4f8821 | ||
| 
						 | 
					9a1781765b | ||
| 
						 | 
					544b8181e5 | ||
| 
						 | 
					82ea37ead9 | ||
| 
						 | 
					882ef93084 | ||
| 
						 | 
					881469ab7f | ||
| 
						 | 
					d7834650ae | ||
| 
						 | 
					20bf183a10 | ||
| 
						 | 
					c990ac66da | ||
| 
						 | 
					0964163a35 | ||
| 
						 | 
					fc980b1bc9 | ||
| 
						 | 
					e76c8a3ba7 | ||
| 
						 | 
					5805290369 | ||
| 
						 | 
					7dd9623929 | ||
| 
						 | 
					95ac07e4de | ||
| 
						 | 
					92cd463b34 | ||
| 
						 | 
					6832546dca | ||
| 
						 | 
					049042b134 | ||
| 
						 | 
					6d2f2efe31 | ||
| 
						 | 
					bcce4831e3 | ||
| 
						 | 
					7fb3053135 | ||
| 
						 | 
					00359a0fc8 | ||
| 
						 | 
					ccf3e1237c | ||
| 
						 | 
					e02f00fd41 | ||
| 
						 | 
					e45e640f3c | ||
| 
						 | 
					75e8015c43 | ||
| 
						 | 
					2c52fcc156 | ||
| 
						 | 
					dc5b51a41f | ||
| 
						 | 
					d12cee4690 | ||
| 
						 | 
					a74c4ac148 | ||
| 
						 | 
					53e50a8107 | ||
| 
						 | 
					e896ba94cc | ||
| 
						 | 
					87ff990c73 | ||
| 
						 | 
					e406162be2 | ||
| 
						 | 
					2de4120f25 | ||
| 
						 | 
					d8dc58a133 | ||
| 
						 | 
					8684bffe97 | ||
| 
						 | 
					a08513ade0 | ||
| 
						 | 
					1a57e01e07 | ||
| 
						 | 
					6d4faf19b8 | ||
| 
						 | 
					96e6845e16 | ||
| 
						 | 
					b33adeb708 | ||
| 
						 | 
					ea0e294a74 | ||
| 
						 | 
					2d878c2391 | ||
| 
						 | 
					6dec867cd3 | ||
| 
						 | 
					d8bd7b9366 | ||
| 
						 | 
					b52e4c6dee | ||
| 
						 | 
					21046af42f | ||
| 
						 | 
					3cbe1d6ac8 | ||
| 
						 | 
					b4b1a99a27 | ||
| 
						 | 
					f5a2d481e3 | ||
| 
						 | 
					da57a15852 | ||
| 
						 | 
					9d0ac624c5 | ||
| 
						 | 
					b8ccc80b87 | ||
| 
						 | 
					27e2dac22e | ||
| 
						 | 
					a4ec4e382d | ||
| 
						 | 
					30df5faf64 | ||
| 
						 | 
					0aa29d8a91 | ||
| 
						 | 
					3ace986e4a | ||
| 
						 | 
					064ab48eee | ||
| 
						 | 
					12c1725ab1 | ||
| 
						 | 
					ba2ddf4163 | ||
| 
						 | 
					3d16384acd | ||
| 
						 | 
					0f73626025 | ||
| 
						 | 
					84fb44e519 | ||
| 
						 | 
					aafe23396a | ||
| 
						 | 
					51f270df67 | ||
| 
						 | 
					e9c404de92 | ||
| 
						 | 
					141bda151b | ||
| 
						 | 
					e952380ce6 | ||
| 
						 | 
					721f5dc469 | ||
| 
						 | 
					434b17eefe | ||
| 
						 | 
					af6a1c84ef | ||
| 
						 | 
					a0ce447a1f | ||
| 
						 | 
					f24145f407 | ||
| 
						 | 
					11c173b2e4 | ||
| 
						 | 
					aff816d10c | ||
| 
						 | 
					e1acaa3bdb | ||
| 
						 | 
					c63743ac51 | ||
| 
						 | 
					6832d9bf46 | ||
| 
						 | 
					4c3ccbc06f | ||
| 
						 | 
					f82596c372 | ||
| 
						 | 
					4921a6ab8d | ||
| 
						 | 
					ef9c242a59 | ||
| 
						 | 
					a83c9937a5 | ||
| 
						 | 
					cfa3ad4d9e | ||
| 
						 | 
					ffc9638ebb | ||
| 
						 | 
					000534654d | ||
| 
						 | 
					68e9358d02 | ||
| 
						 | 
					37e3859f8f | ||
| 
						 | 
					e79b940b0d | ||
| 
						 | 
					d8dfe3f289 | ||
| 
						 | 
					394c286ee5 | ||
| 
						 | 
					307bd6942c | ||
| 
						 | 
					148b53e862 | ||
| 
						 | 
					5c8cb0a013 | ||
| 
						 | 
					4d644e0584 | ||
| 
						 | 
					dce9c8b3d1 | ||
| 
						 | 
					b117ee6404 | ||
| 
						 | 
					c3f783bf7e | ||
| 
						 | 
					4c65a6eded | ||
| 
						 | 
					c382cab922 | ||
| 
						 | 
					199fd4ed61 | ||
| 
						 | 
					f86d62fbf8 | ||
| 
						 | 
					3ea82dc384 | ||
| 
						 | 
					03ae5834ee | ||
| 
						 | 
					e39b5c20ee | ||
| 
						 | 
					d6e131eb6e | ||
| 
						 | 
					1c36b5f142 | ||
| 
						 | 
					827bd0b59f | ||
| 
						 | 
					2dab057652 | ||
| 
						 | 
					488fbc5b63 | ||
| 
						 | 
					17f511d7a3 | ||
| 
						 | 
					63e633c0ec | ||
| 
						 | 
					f46448c236 | ||
| 
						 | 
					43023be32d | ||
| 
						 | 
					4811d51c5d | ||
| 
						 | 
					821dabca3d | ||
| 
						 | 
					587f4ebb50 | ||
| 
						 | 
					0c0b25fcd1 | ||
| 
						 | 
					bdf07d04d4 | ||
| 
						 | 
					6936675eb9 | ||
| 
						 | 
					c39bf4b802 | ||
| 
						 | 
					5a43b1b091 | ||
| 
						 | 
					3e039e033c | ||
| 
						 | 
					6a2af83ea3 | ||
| 
						 | 
					5a12df240b | ||
| 
						 | 
					2ea7d91fc7 | ||
| 
						 | 
					d9903e7398 | ||
| 
						 | 
					39b69f27ee | ||
| 
						 | 
					31a1d19b4e | ||
| 
						 | 
					f4a923c3dc | ||
| 
						 | 
					171ff7d1e4 | ||
| 
						 | 
					5cfbf22b81 | ||
| 
						 | 
					5a35ed5ea1 | ||
| 
						 | 
					1978359f15 | ||
| 
						 | 
					fef6543f1a | ||
| 
						 | 
					b1a9200803 | ||
| 
						 | 
					fada30868a | ||
| 
						 | 
					8414e9485f | ||
| 
						 | 
					f6d8d485bc | ||
| 
						 | 
					6ea0d6c631 | ||
| 
						 | 
					31c6c05c1e | ||
| 
						 | 
					d855d695db | ||
| 
						 | 
					922cc82029 | ||
| 
						 | 
					80498378f2 | ||
| 
						 | 
					51856865df | ||
| 
						 | 
					d26dcca37e | ||
| 
						 | 
					5ac02fcb2e | ||
| 
						 | 
					110cd65779 | ||
| 
						 | 
					67e665b619 | ||
| 
						 | 
					d1c431c370 | ||
| 
						 | 
					2167a82c73 | ||
| 
						 | 
					d113d3bf4a | ||
| 
						 | 
					b2206adae5 | ||
| 
						 | 
					8075cce1b1 | ||
| 
						 | 
					29e4c79f75 | ||
| 
						 | 
					3b299d3345 | ||
| 
						 | 
					7421fff380 | ||
| 
						 | 
					694aad637b | ||
| 
						 | 
					c8c7222e06 | ||
| 
						 | 
					9c6e31ef41 | ||
| 
						 | 
					6a8d5c0c6e | ||
| 
						 | 
					96ca10396b | ||
| 
						 | 
					61cef824e8 | ||
| 
						 | 
					972517d32d | ||
| 
						 | 
					217a03642a | ||
| 
						 | 
					f14783b8cf | ||
| 
						 | 
					4f75c6e37b | ||
| 
						 | 
					4eb3b66a0e | ||
| 
						 | 
					6b74d5faed | ||
| 
						 | 
					10d72ec42c | ||
| 
						 | 
					9eae4ef819 | ||
| 
						 | 
					b3657e396f | ||
| 
						 | 
					a69885d05f | ||
| 
						 | 
					306d08112b | ||
| 
						 | 
					b489becf51 | ||
| 
						 | 
					8a27829af3 | ||
| 
						 | 
					d67b73502e | ||
| 
						 | 
					4ecf3ae24d | ||
| 
						 | 
					d0542e759d | ||
| 
						 | 
					ffa44ac5b3 | ||
| 
						 | 
					6509e5dac8 | ||
| 
						 | 
					6b956c0d3c | ||
| 
						 | 
					3b10a08bad | 
							
								
								
									
										14
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,13 +1,13 @@
 | 
				
			|||||||
*~
 | 
					*~
 | 
				
			||||||
debian/files
 | 
					debian/files
 | 
				
			||||||
debian/libgbinder-dev.debhelper.log
 | 
					 | 
				
			||||||
debian/libgbinder-dev.substvars
 | 
					 | 
				
			||||||
debian/libgbinder-dev
 | 
					 | 
				
			||||||
debian/libgbinder.debhelper.log
 | 
					 | 
				
			||||||
debian/libgbinder.postinst.debhelper
 | 
					 | 
				
			||||||
debian/libgbinder.postrm.debhelper
 | 
					 | 
				
			||||||
debian/libgbinder.substvars
 | 
					 | 
				
			||||||
debian/libgbinder
 | 
					debian/libgbinder
 | 
				
			||||||
 | 
					debian/libgbinder-dev
 | 
				
			||||||
 | 
					debian/libgbinder-tools
 | 
				
			||||||
 | 
					debian/*.debhelper.log
 | 
				
			||||||
 | 
					debian/*.debhelper
 | 
				
			||||||
 | 
					debian/*.substvars
 | 
				
			||||||
 | 
					debian/libgbinder.install
 | 
				
			||||||
 | 
					debian/libgbinder-dev.install
 | 
				
			||||||
debian/tmp
 | 
					debian/tmp
 | 
				
			||||||
documentation.list
 | 
					documentation.list
 | 
				
			||||||
installroot
 | 
					installroot
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										13
									
								
								AUTHORS
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								AUTHORS
									
									
									
									
									
								
							@@ -1,2 +1,13 @@
 | 
				
			|||||||
Slava Monich <slava.monich@jolla.com>
 | 
					Slava Monich <slava@monich.com>
 | 
				
			||||||
Matti Lehtimäki <matti.lehtimaki@gmail.com>
 | 
					Matti Lehtimäki <matti.lehtimaki@gmail.com>
 | 
				
			||||||
 | 
					Franz-Josef Haider <franz.haider@jolla.com>
 | 
				
			||||||
 | 
					Juho Hämäläinen <juho.hamalainen@jolla.com>
 | 
				
			||||||
 | 
					Andrew Branson <andrew.branson@jolla.com>
 | 
				
			||||||
 | 
					Rinigus <rinigus.git@gmail.com>
 | 
				
			||||||
 | 
					George Hopkins <george-hopkins@null.net>
 | 
				
			||||||
 | 
					Bart Ribbers <bribbers@disroot.org>
 | 
				
			||||||
 | 
					Gary Wang <gary.wang@canonical.com>
 | 
				
			||||||
 | 
					Eugenio Paolantonio <me@medesimo.eu>
 | 
				
			||||||
 | 
					Alessandro Astone <ales.astone@gmail.com>
 | 
				
			||||||
 | 
					Martin Kampas <martin.kampas@seafarix.com>
 | 
				
			||||||
 | 
					Nikita Ukhrenkov <nikita.ukhrenkov@seafarix.com>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										12
									
								
								LICENSE
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								LICENSE
									
									
									
									
									
								
							@@ -1,7 +1,5 @@
 | 
				
			|||||||
Copyright (C) 2018 Jolla Ltd.
 | 
					Copyright (C) 2018-2024 Jolla Ltd.
 | 
				
			||||||
Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
 | 
				
			||||||
 | 
					 | 
				
			||||||
You may use this file under the terms of BSD license as follows:
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
Redistribution and use in source and binary forms, with or without
 | 
					Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
modification, are permitted provided that the following conditions
 | 
					modification, are permitted provided that the following conditions
 | 
				
			||||||
@@ -12,9 +10,9 @@ are met:
 | 
				
			|||||||
  2. Redistributions in binary form must reproduce the above copyright
 | 
					  2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
     notice, this list of conditions and the following disclaimer in the
 | 
					     notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
     documentation and/or other materials provided with the distribution.
 | 
					     documentation and/or other materials provided with the distribution.
 | 
				
			||||||
  3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					  3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
     be used to endorse or promote products derived from this software
 | 
					     contributors may be used to endorse or promote products derived
 | 
				
			||||||
     without specific prior written permission.
 | 
					     from this software without specific prior written permission.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										159
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										159
									
								
								Makefile
									
									
									
									
									
								
							@@ -1,16 +1,25 @@
 | 
				
			|||||||
# -*- Mode: makefile-gmake -*-
 | 
					# -*- Mode: makefile-gmake -*-
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# LIBGLIBUTIL_PATH can be defined to point to libglibutil root directory
 | 
				
			||||||
 | 
					# for side-by-side build.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PHONY: clean all debug release test
 | 
					.PHONY: clean all debug release test
 | 
				
			||||||
.PHONY: print_debug_so print_release_so
 | 
					.PHONY: print_debug_so print_release_so
 | 
				
			||||||
.PHONY: print_debug_lib print_release_lib
 | 
					.PHONY: print_debug_lib print_release_lib print_coverage_lib
 | 
				
			||||||
.PHONY: print_debug_link print_release_link
 | 
					.PHONY: print_debug_link print_release_link
 | 
				
			||||||
.PHONY: print_debug_path print_release_path
 | 
					.PHONY: print_debug_path print_release_path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# Required packages
 | 
					# Library version
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PKGS = libglibutil glib-2.0 gobject-2.0
 | 
					VERSION_MAJOR = 1
 | 
				
			||||||
 | 
					VERSION_MINOR = 1
 | 
				
			||||||
 | 
					VERSION_RELEASE = 40
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Version for pkg-config
 | 
				
			||||||
 | 
					PCVERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_RELEASE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# Default target
 | 
					# Default target
 | 
				
			||||||
@@ -19,15 +28,34 @@ PKGS = libglibutil glib-2.0 gobject-2.0
 | 
				
			|||||||
all: debug release pkgconfig
 | 
					all: debug release pkgconfig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# Library version
 | 
					# Required packages
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VERSION_MAJOR = 1
 | 
					PKGS = glib-2.0 gobject-2.0
 | 
				
			||||||
VERSION_MINOR = 0
 | 
					 | 
				
			||||||
VERSION_RELEASE = 5
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Version for pkg-config
 | 
					ifeq ($(LIBGLIBUTIL_PATH),)
 | 
				
			||||||
PCVERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_RELEASE)
 | 
					
 | 
				
			||||||
 | 
					# Assume that libglibutil devel package is installed
 | 
				
			||||||
 | 
					PKGS += libglibutil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Side-by-side build
 | 
				
			||||||
 | 
					INCLUDES += -I$(LIBGLIBUTIL_PATH)/include
 | 
				
			||||||
 | 
					DEBUG_LIBS = -L$(LIBGLIBUTIL_PATH)/build/debug -lglibutil
 | 
				
			||||||
 | 
					RELEASE_LIBS = -L$(LIBGLIBUTIL_PATH)/build/release -lglibutil
 | 
				
			||||||
 | 
					DEBUG_DEPS = libglibutil_debug
 | 
				
			||||||
 | 
					RELEASE_DEPS = libglibutil_release
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PHONY: libglibutil_debug libglibutil_release
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libglibutil_debug:
 | 
				
			||||||
 | 
						$(MAKE) -C $(LIBGLIBUTIL_PATH) debug
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libglibutil_release:
 | 
				
			||||||
 | 
						$(MAKE) -C $(LIBGLIBUTIL_PATH) release
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# Library name
 | 
					# Library name
 | 
				
			||||||
@@ -47,27 +75,38 @@ LIB = $(LIB_NAME).a
 | 
				
			|||||||
#
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SRC = \
 | 
					SRC = \
 | 
				
			||||||
 | 
					  gbinder_bridge.c \
 | 
				
			||||||
  gbinder_buffer.c \
 | 
					  gbinder_buffer.c \
 | 
				
			||||||
  gbinder_cleanup.c \
 | 
					  gbinder_cleanup.c \
 | 
				
			||||||
  gbinder_client.c \
 | 
					  gbinder_client.c \
 | 
				
			||||||
 | 
					  gbinder_config.c \
 | 
				
			||||||
  gbinder_driver.c \
 | 
					  gbinder_driver.c \
 | 
				
			||||||
 | 
					  gbinder_eventloop.c \
 | 
				
			||||||
 | 
					  gbinder_fmq.c \
 | 
				
			||||||
  gbinder_io_32.c \
 | 
					  gbinder_io_32.c \
 | 
				
			||||||
  gbinder_io_64.c \
 | 
					  gbinder_io_64.c \
 | 
				
			||||||
  gbinder_ipc.c \
 | 
					  gbinder_ipc.c \
 | 
				
			||||||
  gbinder_local_object.c \
 | 
					  gbinder_local_object.c \
 | 
				
			||||||
  gbinder_local_reply.c \
 | 
					  gbinder_local_reply.c \
 | 
				
			||||||
  gbinder_local_request.c \
 | 
					  gbinder_local_request.c \
 | 
				
			||||||
 | 
					  gbinder_log.c \
 | 
				
			||||||
 | 
					  gbinder_proxy_object.c \
 | 
				
			||||||
  gbinder_reader.c \
 | 
					  gbinder_reader.c \
 | 
				
			||||||
  gbinder_remote_object.c \
 | 
					  gbinder_remote_object.c \
 | 
				
			||||||
  gbinder_remote_reply.c \
 | 
					  gbinder_remote_reply.c \
 | 
				
			||||||
  gbinder_remote_request.c \
 | 
					  gbinder_remote_request.c \
 | 
				
			||||||
  gbinder_rpc_protocol.c \
 | 
					  gbinder_rpc_protocol.c \
 | 
				
			||||||
 | 
					  gbinder_servicename.c \
 | 
				
			||||||
 | 
					  gbinder_servicepoll.c \
 | 
				
			||||||
  gbinder_writer.c
 | 
					  gbinder_writer.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SRC += \
 | 
					SRC += \
 | 
				
			||||||
  gbinder_defaultservicemanager.c \
 | 
					  gbinder_servicemanager.c \
 | 
				
			||||||
  gbinder_hwservicemanager.c \
 | 
					  gbinder_servicemanager_aidl.c \
 | 
				
			||||||
  gbinder_servicemanager.c
 | 
					  gbinder_servicemanager_aidl2.c \
 | 
				
			||||||
 | 
					  gbinder_servicemanager_aidl3.c \
 | 
				
			||||||
 | 
					  gbinder_servicemanager_aidl4.c \
 | 
				
			||||||
 | 
					  gbinder_servicemanager_hidl.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SRC += \
 | 
					SRC += \
 | 
				
			||||||
  gbinder_system.c
 | 
					  gbinder_system.c
 | 
				
			||||||
@@ -87,29 +126,30 @@ COVERAGE_BUILD_DIR = $(BUILD_DIR)/coverage
 | 
				
			|||||||
# Tools and flags
 | 
					# Tools and flags
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CC = $(CROSS_COMPILE)gcc
 | 
					PKG_CONFIG ?= pkg-config
 | 
				
			||||||
 | 
					CC ?= $(CROSS_COMPILE)gcc
 | 
				
			||||||
 | 
					STRIP ?= strip
 | 
				
			||||||
LD = $(CC)
 | 
					LD = $(CC)
 | 
				
			||||||
WARNINGS = -Wall -Wstrict-aliasing -Wunused-result
 | 
					WARNINGS = -Wall -Wstrict-aliasing -Wunused-result
 | 
				
			||||||
INCLUDES = -I$(INCLUDE_DIR)
 | 
					DEFINES += -DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_32 \
 | 
				
			||||||
 | 
					  -DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_MAX_ALLOWED
 | 
				
			||||||
 | 
					INCLUDES += -I$(INCLUDE_DIR)
 | 
				
			||||||
BASE_FLAGS = -fPIC
 | 
					BASE_FLAGS = -fPIC
 | 
				
			||||||
FULL_CFLAGS = $(BASE_FLAGS) $(CFLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) \
 | 
					FULL_CFLAGS = $(BASE_FLAGS) $(CFLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) \
 | 
				
			||||||
  -MMD -MP $(shell pkg-config --cflags $(PKGS))
 | 
					  -MMD -MP $(shell $(PKG_CONFIG) --cflags $(PKGS))
 | 
				
			||||||
FULL_LDFLAGS = $(BASE_FLAGS) $(LDFLAGS) -shared -Wl,-soname,$(LIB_SONAME) \
 | 
					FULL_LDFLAGS = $(BASE_FLAGS) $(LDFLAGS) -shared -Wl,-soname,$(LIB_SONAME) \
 | 
				
			||||||
  $(shell pkg-config --libs $(PKGS)) -lpthread
 | 
					  $(shell $(PKG_CONFIG) --libs $(PKGS)) -lpthread
 | 
				
			||||||
DEBUG_FLAGS = -g
 | 
					DEBUG_FLAGS = -g
 | 
				
			||||||
RELEASE_FLAGS =
 | 
					RELEASE_FLAGS =
 | 
				
			||||||
COVERAGE_FLAGS = -g
 | 
					COVERAGE_FLAGS = -g
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ifndef KEEP_SYMBOLS
 | 
					KEEP_SYMBOLS ?= 0
 | 
				
			||||||
KEEP_SYMBOLS = 0
 | 
					 | 
				
			||||||
endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ifneq ($(KEEP_SYMBOLS),0)
 | 
					ifneq ($(KEEP_SYMBOLS),0)
 | 
				
			||||||
RELEASE_FLAGS += -g
 | 
					RELEASE_FLAGS += -g
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DEBUG_LDFLAGS = $(FULL_LDFLAGS) $(DEBUG_FLAGS)
 | 
					DEBUG_LDFLAGS = $(FULL_LDFLAGS) $(DEBUG_LIBS) $(DEBUG_FLAGS)
 | 
				
			||||||
RELEASE_LDFLAGS = $(FULL_LDFLAGS) $(RELEASE_FLAGS)
 | 
					RELEASE_LDFLAGS = $(FULL_LDFLAGS) $(RELEASE_LIBS) $(RELEASE_FLAGS)
 | 
				
			||||||
DEBUG_CFLAGS = $(FULL_CFLAGS) $(DEBUG_FLAGS) -DDEBUG
 | 
					DEBUG_CFLAGS = $(FULL_CFLAGS) $(DEBUG_FLAGS) -DDEBUG
 | 
				
			||||||
RELEASE_CFLAGS = $(FULL_CFLAGS) $(RELEASE_FLAGS) -O2
 | 
					RELEASE_CFLAGS = $(FULL_CFLAGS) $(RELEASE_FLAGS) -O2
 | 
				
			||||||
COVERAGE_CFLAGS = $(FULL_CFLAGS) $(COVERAGE_FLAGS) --coverage
 | 
					COVERAGE_CFLAGS = $(FULL_CFLAGS) $(COVERAGE_FLAGS) --coverage
 | 
				
			||||||
@@ -123,6 +163,16 @@ DEBUG_OBJS = $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o)
 | 
				
			|||||||
RELEASE_OBJS = $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o)
 | 
					RELEASE_OBJS = $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o)
 | 
				
			||||||
COVERAGE_OBJS = $(SRC:%.c=$(COVERAGE_BUILD_DIR)/%.o)
 | 
					COVERAGE_OBJS = $(SRC:%.c=$(COVERAGE_BUILD_DIR)/%.o)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DEBUG_SO = $(DEBUG_BUILD_DIR)/$(LIB_SO)
 | 
				
			||||||
 | 
					RELEASE_SO = $(RELEASE_BUILD_DIR)/$(LIB_SO)
 | 
				
			||||||
 | 
					DEBUG_LINK = $(DEBUG_BUILD_DIR)/$(LIB_SYMLINK1)
 | 
				
			||||||
 | 
					RELEASE_LINK = $(RELEASE_BUILD_DIR)/$(LIB_SYMLINK1)
 | 
				
			||||||
 | 
					DEBUG_DEV_LINK = $(DEBUG_BUILD_DIR)/$(LIB_DEV_SYMLINK)
 | 
				
			||||||
 | 
					RELEASE_DEV_LINK = $(RELEASE_BUILD_DIR)/$(LIB_DEV_SYMLINK)
 | 
				
			||||||
 | 
					DEBUG_LIB = $(DEBUG_BUILD_DIR)/$(LIB)
 | 
				
			||||||
 | 
					RELEASE_LIB = $(RELEASE_BUILD_DIR)/$(LIB)
 | 
				
			||||||
 | 
					COVERAGE_LIB = $(COVERAGE_BUILD_DIR)/$(LIB)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# Dependencies
 | 
					# Dependencies
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
@@ -135,25 +185,22 @@ endif
 | 
				
			|||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(PKGCONFIG): | $(BUILD_DIR)
 | 
					$(PKGCONFIG): | $(BUILD_DIR)
 | 
				
			||||||
$(DEBUG_OBJS) $(DEBUG_SO): | $(DEBUG_BUILD_DIR)
 | 
					$(DEBUG_OBJS) $(DEBUG_SO): | $(DEBUG_BUILD_DIR) $(DEBUG_DEPS)
 | 
				
			||||||
$(RELEASE_OBJS) $(RELEASE_SO): | $(RELEASE_BUILD_DIR)
 | 
					$(RELEASE_OBJS) $(RELEASE_SO): | $(RELEASE_BUILD_DIR) $(RELEASE_DEPS)
 | 
				
			||||||
$(COVERAGE_OBJS) $(COVERAGE_LIB): | $(COVERAGE_BUILD_DIR)
 | 
					$(COVERAGE_OBJS) $(COVERAGE_LIB): | $(COVERAGE_BUILD_DIR)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(DEBUG_LINK): | $(DEBUG_LIB)
 | 
				
			||||||
 | 
					$(RELEASE_LINK): | $(RELEASE_LIB)
 | 
				
			||||||
 | 
					$(DEBUG_DEV_LINK): | $(DEBUG_LINK)
 | 
				
			||||||
 | 
					$(RELEASE_DEV_LINK): | $(RELEASE_LINK)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# Rules
 | 
					# Rules
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DEBUG_SO = $(DEBUG_BUILD_DIR)/$(LIB_SO)
 | 
					debug: $(DEBUG_SO) $(DEBUG_LINK) $(DEBUG_DEV_LINK)
 | 
				
			||||||
RELEASE_SO = $(RELEASE_BUILD_DIR)/$(LIB_SO)
 | 
					 | 
				
			||||||
DEBUG_LINK = $(DEBUG_BUILD_DIR)/$(LIB_SYMLINK1)
 | 
					 | 
				
			||||||
RELEASE_LINK = $(RELEASE_BUILD_DIR)/$(LIB_SYMLINK1)
 | 
					 | 
				
			||||||
DEBUG_LIB = $(DEBUG_BUILD_DIR)/$(LIB)
 | 
					 | 
				
			||||||
RELEASE_LIB = $(RELEASE_BUILD_DIR)/$(LIB)
 | 
					 | 
				
			||||||
COVERAGE_LIB = $(COVERAGE_BUILD_DIR)/$(LIB)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
debug: $(DEBUG_SO)
 | 
					release: $(RELEASE_SO) $(RELEASE_LINK) $(RELEASE_DEV_LINK)
 | 
				
			||||||
 | 
					 | 
				
			||||||
release: $(RELEASE_SO)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
debug_lib: $(DEBUG_LIB)
 | 
					debug_lib: $(DEBUG_LIB)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -191,17 +238,18 @@ print_release_path:
 | 
				
			|||||||
	@echo $(RELEASE_BUILD_DIR)
 | 
						@echo $(RELEASE_BUILD_DIR)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
clean:
 | 
					clean:
 | 
				
			||||||
	make -C test clean
 | 
						$(MAKE) -C test clean
 | 
				
			||||||
	make -C unit clean
 | 
						$(MAKE) -C unit clean
 | 
				
			||||||
	rm -fr test/coverage/results test/coverage/*.gcov
 | 
						rm -fr test/coverage/results test/coverage/*.gcov
 | 
				
			||||||
	rm -f *~ $(SRC_DIR)/*~ $(INCLUDE_DIR)/*~
 | 
						rm -f *~ $(SRC_DIR)/*~ $(INCLUDE_DIR)/*~
 | 
				
			||||||
	rm -fr $(BUILD_DIR) RPMS installroot
 | 
						rm -fr $(BUILD_DIR) RPMS installroot
 | 
				
			||||||
	rm -fr debian/tmp debian/libgbinder debian/libgbinder-dev
 | 
						rm -fr debian/tmp debian/libgbinder debian/libgbinder-dev
 | 
				
			||||||
	rm -f documentation.list debian/files debian/*.substvars
 | 
						rm -f documentation.list debian/files debian/*.substvars
 | 
				
			||||||
	rm -f debian/*.debhelper.log debian/*.debhelper debian/*~
 | 
						rm -f debian/*.debhelper.log debian/*.debhelper debian/*~
 | 
				
			||||||
 | 
						rm -f debian/libgbinder.install debian/libgbinder-dev.install
 | 
				
			||||||
 | 
					
 | 
				
			||||||
test:
 | 
					test:
 | 
				
			||||||
	make -C unit test
 | 
						$(MAKE) -C unit test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(BUILD_DIR):
 | 
					$(BUILD_DIR):
 | 
				
			||||||
	mkdir -p $@
 | 
						mkdir -p $@
 | 
				
			||||||
@@ -226,13 +274,11 @@ $(COVERAGE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
$(DEBUG_SO): $(DEBUG_OBJS)
 | 
					$(DEBUG_SO): $(DEBUG_OBJS)
 | 
				
			||||||
	$(LD) $(DEBUG_OBJS) $(DEBUG_LDFLAGS) -o $@
 | 
						$(LD) $(DEBUG_OBJS) $(DEBUG_LDFLAGS) -o $@
 | 
				
			||||||
	ln -sf $(LIB_SO) $(DEBUG_LINK)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(RELEASE_SO): $(RELEASE_OBJS)
 | 
					$(RELEASE_SO): $(RELEASE_OBJS)
 | 
				
			||||||
	$(LD) $(RELEASE_OBJS) $(RELEASE_LDFLAGS) -o $@
 | 
						$(LD) $(RELEASE_OBJS) $(RELEASE_LDFLAGS) -o $@
 | 
				
			||||||
	ln -sf $(LIB_SO) $(RELEASE_LINK)
 | 
					 | 
				
			||||||
ifeq ($(KEEP_SYMBOLS),0)
 | 
					ifeq ($(KEEP_SYMBOLS),0)
 | 
				
			||||||
	strip $@
 | 
						$(STRIP) $@
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(DEBUG_LIB): $(DEBUG_OBJS)
 | 
					$(DEBUG_LIB): $(DEBUG_OBJS)
 | 
				
			||||||
@@ -243,12 +289,35 @@ $(RELEASE_LIB): $(RELEASE_OBJS)
 | 
				
			|||||||
	$(AR) rc $@ $?
 | 
						$(AR) rc $@ $?
 | 
				
			||||||
	ranlib $@
 | 
						ranlib $@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(DEBUG_LINK):
 | 
				
			||||||
 | 
						ln -sf $(LIB_SO) $@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(RELEASE_LINK):
 | 
				
			||||||
 | 
						ln -sf $(LIB_SO) $@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(DEBUG_DEV_LINK):
 | 
				
			||||||
 | 
						ln -sf $(LIB_SYMLINK1) $@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(RELEASE_DEV_LINK):
 | 
				
			||||||
 | 
						ln -sf $(LIB_SYMLINK1) $@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(COVERAGE_LIB): $(COVERAGE_OBJS)
 | 
					$(COVERAGE_LIB): $(COVERAGE_OBJS)
 | 
				
			||||||
	$(AR) rc $@ $?
 | 
						$(AR) rc $@ $?
 | 
				
			||||||
	ranlib $@
 | 
						ranlib $@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(PKGCONFIG): $(LIB_NAME).pc.in
 | 
					#
 | 
				
			||||||
	sed -e 's/\[version\]/'$(PCVERSION)/g $< > $@
 | 
					# LIBDIR usually gets substituted with arch specific dir.
 | 
				
			||||||
 | 
					# It's relative in deb build and can be whatever in rpm build.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LIBDIR ?= usr/lib
 | 
				
			||||||
 | 
					ABS_LIBDIR := $(shell echo /$(LIBDIR) | sed -r 's|/+|/|g')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(PKGCONFIG): $(LIB_NAME).pc.in Makefile
 | 
				
			||||||
 | 
						sed -e 's|@version@|$(PCVERSION)|g' -e 's|@libdir@|$(ABS_LIBDIR)|g' $< > $@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					debian/%.install: debian/%.install.in
 | 
				
			||||||
 | 
						sed 's|@LIBDIR@|$(LIBDIR)|g' $< > $@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# Install
 | 
					# Install
 | 
				
			||||||
@@ -260,12 +329,12 @@ INSTALL = install
 | 
				
			|||||||
INSTALL_DIRS = $(INSTALL) -d
 | 
					INSTALL_DIRS = $(INSTALL) -d
 | 
				
			||||||
INSTALL_FILES = $(INSTALL) -m $(INSTALL_PERM)
 | 
					INSTALL_FILES = $(INSTALL) -m $(INSTALL_PERM)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
INSTALL_LIB_DIR = $(DESTDIR)/usr/lib
 | 
					INSTALL_LIB_DIR = $(DESTDIR)$(ABS_LIBDIR)
 | 
				
			||||||
INSTALL_INCLUDE_DIR = $(DESTDIR)/usr/include/$(NAME)
 | 
					INSTALL_INCLUDE_DIR = $(DESTDIR)/usr/include/$(NAME)
 | 
				
			||||||
INSTALL_PKGCONFIG_DIR = $(DESTDIR)/usr/lib/pkgconfig
 | 
					INSTALL_PKGCONFIG_DIR = $(DESTDIR)$(ABS_LIBDIR)/pkgconfig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
install: $(INSTALL_LIB_DIR)
 | 
					install: $(INSTALL_LIB_DIR)
 | 
				
			||||||
	$(INSTALL_FILES) $(RELEASE_SO) $(INSTALL_LIB_DIR)
 | 
						$(INSTALL) -m 755 $(RELEASE_SO) $(INSTALL_LIB_DIR)
 | 
				
			||||||
	ln -sf $(LIB_SO) $(INSTALL_LIB_DIR)/$(LIB_SYMLINK2)
 | 
						ln -sf $(LIB_SO) $(INSTALL_LIB_DIR)/$(LIB_SYMLINK2)
 | 
				
			||||||
	ln -sf $(LIB_SYMLINK2) $(INSTALL_LIB_DIR)/$(LIB_SYMLINK1)
 | 
						ln -sf $(LIB_SYMLINK2) $(INSTALL_LIB_DIR)/$(LIB_SYMLINK1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										45
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										45
									
								
								README
									
									
									
									
									
								
							@@ -1 +1,46 @@
 | 
				
			|||||||
GLib-style interface to binder (Android IPC mechanism)
 | 
					GLib-style interface to binder (Android IPC mechanism)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Key features:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. Integration with GLib event loop
 | 
				
			||||||
 | 
					2. Detection of 32 vs 64 bit kernel at runtime
 | 
				
			||||||
 | 
					3. Asynchronous transactions that don't block the event thread
 | 
				
			||||||
 | 
					4. Stable service manager and low-level transaction APIs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Android keeps changing both low-level RPC and service manager
 | 
				
			||||||
 | 
					protocols from version to version. To counter that, libgbinder
 | 
				
			||||||
 | 
					implements configirable backends for different variants of those,
 | 
				
			||||||
 | 
					and yet keeping its own API unchanged.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Configuration is loaded from [Protocol] and [ServiceManager] sections
 | 
				
			||||||
 | 
					of /etc/gbinder.conf file. The keys are binder device names or the
 | 
				
			||||||
 | 
					special Default value, the value is the identifier of the protocol
 | 
				
			||||||
 | 
					or service manager variant, respectively.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In addition to reading /etc/gbinder.conf if it exists, /etc/gbinder.d
 | 
				
			||||||
 | 
					directory is scanned for .conf files, the file list is sorted, files are
 | 
				
			||||||
 | 
					loaded one by one, overwriting the entries loaded from /etc/gbinder.conf
 | 
				
			||||||
 | 
					or from the previously processed file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Known protocol and service manager variants are aidl, aidl2, aidl3 and
 | 
				
			||||||
 | 
					hidl. This list is expected to expand further in the future. The default
 | 
				
			||||||
 | 
					configuration is as follows:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [Protocol]
 | 
				
			||||||
 | 
					  Default = aidl
 | 
				
			||||||
 | 
					  /dev/binder = aidl
 | 
				
			||||||
 | 
					  /dev/hwbinder = hidl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ServiceManager]
 | 
				
			||||||
 | 
					  Default = aidl
 | 
				
			||||||
 | 
					  /dev/binder = aidl
 | 
				
			||||||
 | 
					  /dev/hwbinder = hidl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Alternatively and preferably, one can specify the desired Android API
 | 
				
			||||||
 | 
					level:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [General]
 | 
				
			||||||
 | 
					  ApiLevel = 29
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					and let libgbinder pick the appropriate preset. Full list of presets can
 | 
				
			||||||
 | 
					be found in src/gbinder_config.c
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										10
									
								
								debian/Jenkinsfile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								debian/Jenkinsfile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					@Library('ubports-build-tools') _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					buildAndProvideDebianPackage()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Or if the package consists entirely of arch-independent packages:
 | 
				
			||||||
 | 
					// (optional optimization, will confuse BlueOcean's live view at build stage)
 | 
				
			||||||
 | 
					// buildAndProvideDebianPackage(/* isArchIndependent */ true)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Optionally, to skip building on some architectures (amd64 is always built):
 | 
				
			||||||
 | 
					// buildAndProvideDebianPackage(false, /* ignoredArchs */ ['arm64'])
 | 
				
			||||||
							
								
								
									
										547
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										547
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							@@ -1,3 +1,550 @@
 | 
				
			|||||||
 | 
					libgbinder (1.1.40-0ubports1) UNRELEASED; urgency=medium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Upstream release v1.1.40
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- TheKit <thekit@disroot.org>  Thu, 15 Aug 2024 15:56:51 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.35-0ubports1) UNRELEASED; urgency=unknown
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * New upstream release v1.1.35 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- UBports package upgrader bot <dev@ubports.com>  Thu, 23 Nov 2023 23:02:23 +0000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.34-0ubports1) focal; urgency=medium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * New upstream release v1.1.34
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Marius Gripsgard <mariogrip@debian.org>  Thu, 31 Aug 2023 12:09:35 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.30-0ubports1) focal; urgency=medium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Upstream release v1.1.30
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Jami Kettunen <jami.kettunen@protonmail.com>  Wed, 07 Dec 2022 00:58:38 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.30) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Fixed BC_ACQUIRE_DONE encoding
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Sun, 04 Dec 2022 19:50:10 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.29) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Added gbinder_writer_append_struct_vec
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Fri, 25 Nov 2022 00:01:41 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.28) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Allow to pass negative number as a parameter to binder-call
 | 
				
			||||||
 | 
					  * Compile tools as PIE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Tue, 22 Nov 2022 18:21:29 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.27) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Added gbinder_writer_append_struct()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Thu, 17 Nov 2022 03:25:37 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.26) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Use BINDER_TYPE_HANDLE for NULL binders
 | 
				
			||||||
 | 
					  * Fixed binder object encoding in aidl3 protocol
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Fri, 14 Oct 2022 16:48:29 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.25) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Handle RPC protocol change at run time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Tue, 19 Jul 2022 02:02:41 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.24) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Bumped debhelper compat level to 7
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Thu, 14 Jul 2022 01:32:11 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.23) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Fixed Debian build dependencies
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Thu, 23 Jun 2022 20:09:35 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.22) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Added support for Android 12 (API level 31)
 | 
				
			||||||
 | 
					  * Made binder device configurable for binder-dump
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Wed, 22 Jun 2022 17:02:20 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.21) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Properly finalize GBinderIpc and GBinderServicePoll
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Mon, 20 Jun 2022 18:53:26 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.20) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Made RPC protocol selectable at runtime
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Sat, 11 Jun 2022 02:49:49 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.19-0ubports1) xenial; urgency=medium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * New upstream version 1.1.19.
 | 
				
			||||||
 | 
					  * debian/ubports.source_location: update the location for 1.1.19
 | 
				
			||||||
 | 
					  * debian/*: bring in upstream Debian packaging changes where appropriate
 | 
				
			||||||
 | 
					  * debian/rules: pass KEEP_SYMBOLS to let dh do the strip (& auto dbgsym)
 | 
				
			||||||
 | 
					  * debian/libgbinder-tools.install: add the missing .install file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Ratchanan Srirattanamet <ratchanan@ubports.com>  Thu, 21 Apr 2022 17:22:20 +0700
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.19) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Added reader and writer for aidl parcelables
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Sun, 20 Feb 2022 03:26:24 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.18) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Disassociate auto-created proxies to stop them from piling up
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Sat, 08 Jan 2022 15:35:56 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.17) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Don't release remote proxy handle too early (sometimes hever)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Fri, 07 Jan 2022 14:43:51 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.16) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Make sure stale object pointers don't hang around
 | 
				
			||||||
 | 
					  * Properly shut down remote object inside the proxy
 | 
				
			||||||
 | 
					  * Read ref_count from GObject atomically
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Mon, 03 Jan 2022 13:58:44 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.15) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Added readers and writers for int8 and int16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Mon, 27 Dec 2021 15:13:23 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.14) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Support for FMQ (Fast Message Queues)
 | 
				
			||||||
 | 
					  * Support for Android 11 (API level 30)
 | 
				
			||||||
 | 
					  * Made GBinderReader API slightly more NULL tolerant
 | 
				
			||||||
 | 
					  * Added gbinder_client_rpc_header()
 | 
				
			||||||
 | 
					  * Added gbinder_reader_get_data()
 | 
				
			||||||
 | 
					  * Added gbinder_writer_get_data()
 | 
				
			||||||
 | 
					  * Added gbinder_servicemanager_device()
 | 
				
			||||||
 | 
					  * Added gbinder_local_reply_append_fd()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Wed, 24 Nov 2021 17:15:48 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.13) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Added gbinder_writer_strdup()
 | 
				
			||||||
 | 
					  * Added gbinder_writer_append_hidl_string_copy()
 | 
				
			||||||
 | 
					  * Dropped pkgconfig requirement for devel package
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Thu, 28 Oct 2021 14:31:01 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.12) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Added binder-call test tool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Fri, 24 Sep 2021 16:46:05 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.11) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Fix potential deadlock in gbinder_ipc_looper_free()
 | 
				
			||||||
 | 
					  * Fix occasional crashes in pthread_setname_np()
 | 
				
			||||||
 | 
					  * Fix unit tests on some musl-based systems
 | 
				
			||||||
 | 
					  * Make unit tests comptible with glib < 2.36
 | 
				
			||||||
 | 
					  * Bump libglibutil requirement for debian build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Thu, 02 Sep 2021 12:32:39 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.10) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Release dead binder nodes
 | 
				
			||||||
 | 
					  * Use gutil_memdup() instead of g_memdup()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Mon, 10 May 2021 02:36:43 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.9) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Include definition of _IOC_SIZE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Tue, 20 Apr 2021 12:52:41 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.8) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Handle out-of-range transaction codes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Fri, 16 Apr 2021 19:11:14 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.7) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Dropped use of g_main_context_invoke_full()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Wed, 31 Mar 2021 23:10:37 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.6-0ubports1) xenial; urgency=medium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Import v1.1.6 to ubports
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Marius Gripsgard <marius@ubports.com>  Fri, 05 Mar 2021 01:02:27 +0100
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.6) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Implemented support for passing object over the bridge
 | 
				
			||||||
 | 
					  * Retry service name registration
 | 
				
			||||||
 | 
					  * Wait for completion of the reply
 | 
				
			||||||
 | 
					  * Fixed death handling by GBinderBridge
 | 
				
			||||||
 | 
					  * Added gbinder_bridge_new2()
 | 
				
			||||||
 | 
					  * Added -s option to binder-bridge
 | 
				
			||||||
 | 
					  * Fixed invalid slice deallocation
 | 
				
			||||||
 | 
					  * Made unit tests more reliable
 | 
				
			||||||
 | 
					  * Make sure that libgbinder doesn't block on exit
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Tue, 02 Mar 2021 18:18:03 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.5) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Fixed gbinder_remote_reply_copy_to_local() for empty replies
 | 
				
			||||||
 | 
					  * Improved binder simulation
 | 
				
			||||||
 | 
					  * Added GBinderBridge object
 | 
				
			||||||
 | 
					  * Added proxy_object and bridge unit tests
 | 
				
			||||||
 | 
					  * Added binder-bridge to libgbinder-tools package
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Fri, 29 Jan 2021 04:00:09 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.4) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Fixed a threading issue
 | 
				
			||||||
 | 
					  * Decode NULL object reference
 | 
				
			||||||
 | 
					  * Added new basic HIDL types
 | 
				
			||||||
 | 
					  * Set TF_ACCEPT_FDS transaction flag
 | 
				
			||||||
 | 
					  * Added servicemanager_hidl unit test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Thu, 21 Jan 2021 03:34:45 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.3) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Improved unit test coverage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Wed, 23 Dec 2020 21:48:27 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.2) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Fixed random unit text failures
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Wed, 23 Dec 2020 12:39:22 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.1) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Handle corner cases for abandoned loopers
 | 
				
			||||||
 | 
					  * Pass 0x0f priority to aidl2 service list request.
 | 
				
			||||||
 | 
					  * Improved binder simulation for unit tests
 | 
				
			||||||
 | 
					  * Added servicemanager_aidl unit test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Tue, 22 Dec 2020 15:15:10 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.1.0) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Made RPC protocol configurable per binder device
 | 
				
			||||||
 | 
					  * Made service managers configurable per binder device
 | 
				
			||||||
 | 
					  * Added support for multiple config files
 | 
				
			||||||
 | 
					  * Added "aidl2" variant of service manager
 | 
				
			||||||
 | 
					  * Added "aidl2" variant of RPC protocol
 | 
				
			||||||
 | 
					  * Added support for API level presets
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Fri, 04 Dec 2020 13:47:26 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.47) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Make library executable on RPM based systems
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Sat, 19 Sep 2020 20:14:20 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.46) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Make sure we drop fds that are going to be closed
 | 
				
			||||||
 | 
					  * Better diagnostics for polling failures
 | 
				
			||||||
 | 
					  * Package binder-list and binder-ping utilities
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Fri, 31 Jul 2020 02:04:38 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.45) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Always provide data buffer for hidl vector
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Mon, 27 Jul 2020 23:19:25 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.44) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Never drop valid incoming transactions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Mon, 29 Jun 2020 17:05:22 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.43) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Hide internal symbols
 | 
				
			||||||
 | 
					  * Respect arch specific lib dir
 | 
				
			||||||
 | 
					  * Allow strip command to be replaced via environment variable
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Wed, 03 Jun 2020 15:15:40 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.42) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Allow GBinderClient to use multiple interfaces
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Tue, 05 May 2020 19:56:39 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.41) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Stop using GUtilIdlePool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Tue, 14 Apr 2020 12:36:54 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.40) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Support integration with non-glib event loops
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Thu, 09 Apr 2020 17:22:12 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.39) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Adapted to side-by-side linking
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Thu, 02 Apr 2020 18:07:16 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.38) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Allow to configure log level via environment
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Thu, 02 Apr 2020 00:12:01 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.37) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Allow side-by-side linking with libglibutil
 | 
				
			||||||
 | 
					  * Fixed compilation warnings
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Tue, 17 Mar 2020 20:15:11 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.36) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Allow overwriting CC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Mon, 16 Mar 2020 16:15:24 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.35) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Added binder-ping example
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Tue, 25 Feb 2020 13:58:19 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.34) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Better cleanup on unload to prevent crashes on exit
 | 
				
			||||||
 | 
					  * Fixed rare memory leak in GBinderServiceManager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Mon, 16 Dec 2019 12:25:56 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.33) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Reuse loopers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Fri, 13 Sep 2019 15:57:47 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.32) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Refuse to perform transactions with dead objects
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Fri, 17 May 2019 15:57:30 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.31) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Invalidate handle when remote object dies
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Mon, 13 May 2019 18:05:35 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.30) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Added gbinder_local_object_new()
 | 
				
			||||||
 | 
					  * Added gbinder_remote_object_ipc()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Wed, 20 Feb 2019 11:59:08 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.29) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Added gbinder_servicemanager_new_local_object2()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Thu, 14 Feb 2019 18:17:53 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.28) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Set type for local nulls to BINDER_TYPE_WEAK_BINDER
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Tue, 29 Jan 2019 02:49:10 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.27) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Fixed outgoing oneway transactions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Thu, 24 Jan 2019 18:55:16 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.26) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Implement PING and INTERFACE transactions
 | 
				
			||||||
 | 
					  * Add GBinderServiceName API
 | 
				
			||||||
 | 
					  * Added gbinder_reader_read_string16_utf16()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Wed, 23 Jan 2019 17:43:41 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.25) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Added ServiceManager presence API
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gbinder_servicemanager_wait()
 | 
				
			||||||
 | 
					    gbinder_servicemanager_is_present()
 | 
				
			||||||
 | 
					    gbinder_servicemanager_add_presence_handler()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Tue, 22 Jan 2019 16:03:57 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.24) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Revert "Make sure NULL objects are passed as BINDER_TYPE_WEAK_HANDLE"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Fri, 18 Jan 2019 21:36:32 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.23) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Added gbinder_reader_read_hidl_string_c()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Tue, 15 Jan 2019 15:16:41 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.22) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Added gbinder_client_interface()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Thu, 10 Jan 2019 14:09:44 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.21) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Added API to overwrite prefix length
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Tue, 18 Dec 2018 14:05:14 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.20) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Added API to block incoming requests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Mon, 17 Dec 2018 16:06:43 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.19) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Added GBinderWriter memory allocation and cleanup API
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Fri, 14 Dec 2018 16:27:51 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.18) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Implemented support for file descritors
 | 
				
			||||||
 | 
					  * Allow GBinderClient without RPC header
 | 
				
			||||||
 | 
					  * Added binder-dump test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Mon, 10 Dec 2018 13:17:22 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.17) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Added gbinder_writer_append_string16_utf16()
 | 
				
			||||||
 | 
					  * Added gbinder_reader_read_nullable_string16_utf16()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Fri, 07 Dec 2018 02:54:07 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.16) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Added GBinderHidlVec and GBinderHidlString types
 | 
				
			||||||
 | 
					  * Added gbinder_reader_copy()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Thu, 06 Dec 2018 19:03:32 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.15) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Implemented service polling for old servicemanager
 | 
				
			||||||
 | 
					  * Added new tests and improved coverage for existing ones
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Wed, 05 Dec 2018 12:11:34 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.14) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Changed bool padding from 0xff to 0x00
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Tue, 27 Nov 2018 17:20:18 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.13) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Support for service registration notifications
 | 
				
			||||||
 | 
					  * Make sure looper is started before gbinder_ipc_looper_new() returns
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Sat, 17 Nov 2018 01:52:28 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.12) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Add byte array reader and writer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Wed, 31 Oct 2018 17:04:38 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.11) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Use BINDER_TYPE_WEAK_HANDLE for NULL objects
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Wed, 24 Oct 2018 18:57:28 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.10) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Fixed dependencies for unit tests
 | 
				
			||||||
 | 
					  * Plugged memory leak in unit_reader
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Wed, 10 Oct 2018 14:44:44 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.9) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Respect strong refs to GBinderLocalObject
 | 
				
			||||||
 | 
					  * Added gbinder_reader_read_hidl_struct macro
 | 
				
			||||||
 | 
					  * Added gbinder_reader_read_hidl_type_vec macro
 | 
				
			||||||
 | 
					  * Added gbinder_reader_read_hidl_byte_vec macro
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Mon, 08 Oct 2018 11:41:33 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.8) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Added gbinder_writer_append_hidl_vec()
 | 
				
			||||||
 | 
					  * Added Added gbinder_reader_read_hidl_vec()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Tue, 25 Sep 2018 01:08:54 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.7) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Added gbinder_remote_request_copy_to_local()
 | 
				
			||||||
 | 
					  * Added gbinder_remote_reply_copy_to_local()
 | 
				
			||||||
 | 
					  * Make sure RPC protocol matches servicemanager type
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Sun, 23 Sep 2018 22:47:16 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libgbinder (1.0.6) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Fixed GBinderServiceManager lifecycle management
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Slava Monich <slava.monich@jolla.com>  Fri, 21 Sep 2018 21:15:28 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
libgbinder (1.0.5) unstable; urgency=low
 | 
					libgbinder (1.0.5) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  * Added double and float support
 | 
					  * Added double and float support
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								debian/compat
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								debian/compat
									
									
									
									
										vendored
									
									
								
							@@ -1 +1 @@
 | 
				
			|||||||
5
 | 
					7
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										12
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							@@ -2,17 +2,23 @@ Source: libgbinder
 | 
				
			|||||||
Section: libs
 | 
					Section: libs
 | 
				
			||||||
Priority: optional
 | 
					Priority: optional
 | 
				
			||||||
Maintainer: Slava Monich <slava.monich@jolla.com>
 | 
					Maintainer: Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
Build-Depends: debhelper (>= 7), libglib2.0-dev (>= 2.0), libglibutil (>= 1.0.29)
 | 
					Build-Depends: debhelper (>= 8.1.3), libglib2.0-dev (>= 2.0), libglibutil-dev (>= 1.0.52), flex, bison
 | 
				
			||||||
Standards-Version: 3.8.4
 | 
					Standards-Version: 3.8.4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Package: libgbinder
 | 
					Package: libgbinder
 | 
				
			||||||
Section: libs
 | 
					Section: libs
 | 
				
			||||||
Architecture: any
 | 
					Architecture: any
 | 
				
			||||||
Depends: libglibutil (>= 1.0.29), ${shlibs:Depends}, ${misc:Depends}
 | 
					Depends: libglibutil (>= 1.0.52), ${shlibs:Depends}, ${misc:Depends}
 | 
				
			||||||
Description: Binder client library
 | 
					Description: Binder client library
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Package: libgbinder-dev
 | 
					Package: libgbinder-dev
 | 
				
			||||||
Section: libdevel
 | 
					Section: libdevel
 | 
				
			||||||
Architecture: any
 | 
					Architecture: any
 | 
				
			||||||
Depends: libgbinder (= ${binary:Version}), ${misc:Depends}
 | 
					Depends: libgbinder (= ${binary:Version}), libglibutil-dev (>= 1.0.52), ${misc:Depends}
 | 
				
			||||||
Description: Development files for libgbinder
 | 
					Description: Development files for libgbinder
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Package: libgbinder-tools
 | 
				
			||||||
 | 
					Section: utils
 | 
				
			||||||
 | 
					Architecture: any
 | 
				
			||||||
 | 
					Depends: libgbinder, ${misc:Depends}
 | 
				
			||||||
 | 
					Description: Binder command line utilities
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										10
									
								
								debian/copyright
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								debian/copyright
									
									
									
									
										vendored
									
									
								
							@@ -1,5 +1,5 @@
 | 
				
			|||||||
Copyright (C) 2018 Jolla Ltd.
 | 
					Copyright (C) 2018-2022 Jolla Ltd.
 | 
				
			||||||
Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You may use this file under the terms of BSD license as follows:
 | 
					You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -12,9 +12,9 @@ are met:
 | 
				
			|||||||
  2. Redistributions in binary form must reproduce the above copyright
 | 
					  2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
     notice, this list of conditions and the following disclaimer in the
 | 
					     notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
     documentation and/or other materials provided with the distribution.
 | 
					     documentation and/or other materials provided with the distribution.
 | 
				
			||||||
  3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					  3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
     be used to endorse or promote products derived from this software
 | 
					     contributors may be used to endorse or promote products derived
 | 
				
			||||||
     without specific prior written permission.
 | 
					     from this software without specific prior written permission.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										37
									
								
								debian/gbinder.conf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								debian/gbinder.conf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					# Android keeps changing both low-level RPC and service manager
 | 
				
			||||||
 | 
					# protocols from version to version. To counter that, libgbinder
 | 
				
			||||||
 | 
					# implements configirable backends for different variants of those,
 | 
				
			||||||
 | 
					# and yet keeping its own API unchanged.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Configuration is loaded from [Protocol] and [ServiceManager] sections
 | 
				
			||||||
 | 
					# of /etc/gbinder.conf file. The keys are binder device names or the
 | 
				
			||||||
 | 
					# special Default value, the value is the identifier of the protocol
 | 
				
			||||||
 | 
					# or service manager variant, respectively.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# In addition to reading /etc/gbinder.conf if it exists, /etc/gbinder.d
 | 
				
			||||||
 | 
					# directory is scanned for .conf files, the file list is sorted, files are
 | 
				
			||||||
 | 
					# loaded one by one, overwriting the entries loaded from /etc/gbinder.conf
 | 
				
			||||||
 | 
					# or from the previously processed file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Known protocol and service manager variants are aidl, aidl2, aidl3 and
 | 
				
			||||||
 | 
					# hidl. This list is expected to expand further in the future. The default
 | 
				
			||||||
 | 
					# configuration is as follows:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#   [Protocol]
 | 
				
			||||||
 | 
					#   Default = aidl
 | 
				
			||||||
 | 
					#   /dev/binder = aidl
 | 
				
			||||||
 | 
					#   /dev/hwbinder = hidl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#   [ServiceManager]
 | 
				
			||||||
 | 
					#   Default = aidl
 | 
				
			||||||
 | 
					#   /dev/binder = aidl
 | 
				
			||||||
 | 
					#   /dev/hwbinder = hidl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Alternatively and preferably, one can specify the desired Android API
 | 
				
			||||||
 | 
					# level:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#   [General]
 | 
				
			||||||
 | 
					#   ApiLevel = 29
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# and let libgbinder pick the appropriate preset. Full list of presets can
 | 
				
			||||||
 | 
					# be found in src/gbinder_config.c
 | 
				
			||||||
							
								
								
									
										3
									
								
								debian/libgbinder-dev.install
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								debian/libgbinder-dev.install
									
									
									
									
										vendored
									
									
								
							@@ -1,3 +0,0 @@
 | 
				
			|||||||
debian/tmp/usr/lib/libgbinder.so usr/lib
 | 
					 | 
				
			||||||
include/*.h usr/include/gbinder
 | 
					 | 
				
			||||||
build/libgbinder.pc usr/lib/pkgconfig
 | 
					 | 
				
			||||||
							
								
								
									
										3
									
								
								debian/libgbinder-dev.install.in
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								debian/libgbinder-dev.install.in
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					debian/tmp/@LIBDIR@/libgbinder.so @LIBDIR@
 | 
				
			||||||
 | 
					debian/tmp/@LIBDIR@/pkgconfig/libgbinder.pc @LIBDIR@/pkgconfig
 | 
				
			||||||
 | 
					debian/tmp/usr/include/* usr/include
 | 
				
			||||||
							
								
								
									
										1
									
								
								debian/libgbinder-tools.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								debian/libgbinder-tools.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					debian/tmp/usr/bin/* usr/bin/
 | 
				
			||||||
							
								
								
									
										1
									
								
								debian/libgbinder.dirs
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								debian/libgbinder.dirs
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					/etc/gbinder.d/
 | 
				
			||||||
							
								
								
									
										1
									
								
								debian/libgbinder.install
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								debian/libgbinder.install
									
									
									
									
										vendored
									
									
								
							@@ -1 +0,0 @@
 | 
				
			|||||||
debian/tmp/usr/lib/libgbinder.so.* usr/lib
 | 
					 | 
				
			||||||
							
								
								
									
										2
									
								
								debian/libgbinder.install.in
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								debian/libgbinder.install.in
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					debian/tmp/@LIBDIR@/libgbinder.so.* @LIBDIR@
 | 
				
			||||||
 | 
					debian/gbinder.conf /etc/
 | 
				
			||||||
							
								
								
									
										15
									
								
								debian/rules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								debian/rules
									
									
									
									
										vendored
									
									
								
							@@ -4,8 +4,21 @@
 | 
				
			|||||||
# Uncomment this to turn on verbose mode.
 | 
					# Uncomment this to turn on verbose mode.
 | 
				
			||||||
#export DH_VERBOSE=1
 | 
					#export DH_VERBOSE=1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LIBDIR=usr/lib/$(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					override_dh_auto_build:
 | 
				
			||||||
 | 
						dh_auto_build -- LIBDIR=$(LIBDIR) KEEP_SYMBOLS=1 release pkgconfig debian/libgbinder.install debian/libgbinder-dev.install
 | 
				
			||||||
 | 
						dh_auto_build -- -C test/binder-bridge release
 | 
				
			||||||
 | 
						dh_auto_build -- -C test/binder-call release
 | 
				
			||||||
 | 
						dh_auto_build -- -C test/binder-list release
 | 
				
			||||||
 | 
						dh_auto_build -- -C test/binder-ping release
 | 
				
			||||||
 | 
					
 | 
				
			||||||
override_dh_auto_install:
 | 
					override_dh_auto_install:
 | 
				
			||||||
	dh_auto_install -- install-dev
 | 
						dh_auto_install -- LIBDIR=$(LIBDIR) install-dev
 | 
				
			||||||
 | 
						dh_auto_install -- -C test/binder-bridge
 | 
				
			||||||
 | 
						dh_auto_install -- -C test/binder-call
 | 
				
			||||||
 | 
						dh_auto_install -- -C test/binder-list
 | 
				
			||||||
 | 
						dh_auto_install -- -C test/binder-ping
 | 
				
			||||||
 | 
					
 | 
				
			||||||
%:
 | 
					%:
 | 
				
			||||||
	dh $@
 | 
						dh $@
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -35,8 +35,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* Convenience header to pull in everything at once */
 | 
					/* Convenience header to pull in everything at once */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "gbinder_bridge.h"
 | 
				
			||||||
#include "gbinder_buffer.h"
 | 
					#include "gbinder_buffer.h"
 | 
				
			||||||
#include "gbinder_client.h"
 | 
					#include "gbinder_client.h"
 | 
				
			||||||
 | 
					#include "gbinder_fmq.h"
 | 
				
			||||||
#include "gbinder_local_object.h"
 | 
					#include "gbinder_local_object.h"
 | 
				
			||||||
#include "gbinder_local_reply.h"
 | 
					#include "gbinder_local_reply.h"
 | 
				
			||||||
#include "gbinder_local_request.h"
 | 
					#include "gbinder_local_request.h"
 | 
				
			||||||
@@ -44,6 +46,7 @@
 | 
				
			|||||||
#include "gbinder_remote_object.h"
 | 
					#include "gbinder_remote_object.h"
 | 
				
			||||||
#include "gbinder_remote_reply.h"
 | 
					#include "gbinder_remote_reply.h"
 | 
				
			||||||
#include "gbinder_remote_request.h"
 | 
					#include "gbinder_remote_request.h"
 | 
				
			||||||
 | 
					#include "gbinder_servicename.h"
 | 
				
			||||||
#include "gbinder_servicemanager.h"
 | 
					#include "gbinder_servicemanager.h"
 | 
				
			||||||
#include "gbinder_writer.h"
 | 
					#include "gbinder_writer.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										89
									
								
								include/gbinder_bridge.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								include/gbinder_bridge.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,89 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2021 Jolla Ltd.
 | 
				
			||||||
 | 
					 * Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   1. Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 | 
					 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
				
			||||||
 | 
					 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
				
			||||||
 | 
					 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
				
			||||||
 | 
					 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
				
			||||||
 | 
					 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
				
			||||||
 | 
					 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
				
			||||||
 | 
					 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
				
			||||||
 | 
					 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
				
			||||||
 | 
					 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GBINDER_BRIDGE_H
 | 
				
			||||||
 | 
					#define GBINDER_BRIDGE_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "gbinder_types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Since 1.1.5 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					G_BEGIN_DECLS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * A binder bridge object.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * For example, bridging "foobar" with interfaces ["example@1.0::IFoo",
 | 
				
			||||||
 | 
					 * "example@1.0::IBar"] would:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 1. Watch "example@1.0::IFoo/foobar" and "example@1.0::IBar/foobar" on dest
 | 
				
			||||||
 | 
					 * 2. When those names appears, register objects with the same name on src
 | 
				
			||||||
 | 
					 * 3. Pass calls coming from src to the dest objects and replies in the
 | 
				
			||||||
 | 
					 *    opposite direction
 | 
				
			||||||
 | 
					 * 4. When dest objects disappear, remove the corresponding bridging objects
 | 
				
			||||||
 | 
					 *    from src
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * and so on.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderBridge*
 | 
				
			||||||
 | 
					gbinder_bridge_new(
 | 
				
			||||||
 | 
					    const char* name,
 | 
				
			||||||
 | 
					    const char* const* ifaces,
 | 
				
			||||||
 | 
					    GBinderServiceManager* src,
 | 
				
			||||||
 | 
					    GBinderServiceManager* dest) /* Since 1.1.5 */
 | 
				
			||||||
 | 
					    G_GNUC_WARN_UNUSED_RESULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderBridge*
 | 
				
			||||||
 | 
					gbinder_bridge_new2(
 | 
				
			||||||
 | 
					    const char* src_name,
 | 
				
			||||||
 | 
					    const char* dest_name,
 | 
				
			||||||
 | 
					    const char* const* ifaces,
 | 
				
			||||||
 | 
					    GBinderServiceManager* src,
 | 
				
			||||||
 | 
					    GBinderServiceManager* dest) /* Since 1.1.6 */
 | 
				
			||||||
 | 
					    G_GNUC_WARN_UNUSED_RESULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_bridge_free(
 | 
				
			||||||
 | 
					    GBinderBridge* bridge); /* Since 1.1.5 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					G_END_DECLS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* GBINDER_BRIDGE_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Local Variables:
 | 
				
			||||||
 | 
					 * mode: C
 | 
				
			||||||
 | 
					 * c-basic-offset: 4
 | 
				
			||||||
 | 
					 * indent-tabs-mode: nil
 | 
				
			||||||
 | 
					 * End:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -37,6 +37,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
G_BEGIN_DECLS
 | 
					G_BEGIN_DECLS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_client_iface_info {
 | 
				
			||||||
 | 
					    const char* iface;
 | 
				
			||||||
 | 
					    guint32 last_code;
 | 
				
			||||||
 | 
					} GBinderClientIfaceInfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef
 | 
					typedef
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
(*GBinderClientReplyFunc)(
 | 
					(*GBinderClientReplyFunc)(
 | 
				
			||||||
@@ -50,6 +55,12 @@ gbinder_client_new(
 | 
				
			|||||||
    GBinderRemoteObject* object,
 | 
					    GBinderRemoteObject* object,
 | 
				
			||||||
    const char* iface);
 | 
					    const char* iface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderClient*
 | 
				
			||||||
 | 
					gbinder_client_new2(
 | 
				
			||||||
 | 
					    GBinderRemoteObject* object,
 | 
				
			||||||
 | 
					    const GBinderClientIfaceInfo* ifaces,
 | 
				
			||||||
 | 
					    gsize count); /* since 1.0.42 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderClient*
 | 
					GBinderClient*
 | 
				
			||||||
gbinder_client_ref(
 | 
					gbinder_client_ref(
 | 
				
			||||||
    GBinderClient* client);
 | 
					    GBinderClient* client);
 | 
				
			||||||
@@ -58,10 +69,29 @@ void
 | 
				
			|||||||
gbinder_client_unref(
 | 
					gbinder_client_unref(
 | 
				
			||||||
    GBinderClient* client);
 | 
					    GBinderClient* client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char*
 | 
				
			||||||
 | 
					gbinder_client_interface(
 | 
				
			||||||
 | 
					    GBinderClient* client); /* since 1.0.22 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char*
 | 
				
			||||||
 | 
					gbinder_client_interface2(
 | 
				
			||||||
 | 
					    GBinderClient* client,
 | 
				
			||||||
 | 
					    guint32 code); /* since 1.0.42 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBytes*
 | 
				
			||||||
 | 
					gbinder_client_rpc_header(
 | 
				
			||||||
 | 
					    GBinderClient* client,
 | 
				
			||||||
 | 
					    guint32 code); /* since 1.1.14 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderLocalRequest*
 | 
					GBinderLocalRequest*
 | 
				
			||||||
gbinder_client_new_request(
 | 
					gbinder_client_new_request(
 | 
				
			||||||
    GBinderClient* client);
 | 
					    GBinderClient* client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderLocalRequest*
 | 
				
			||||||
 | 
					gbinder_client_new_request2(
 | 
				
			||||||
 | 
					    GBinderClient* client,
 | 
				
			||||||
 | 
					    guint32 code); /* since 1.0.42 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderRemoteReply*
 | 
					GBinderRemoteReply*
 | 
				
			||||||
gbinder_client_transact_sync_reply(
 | 
					gbinder_client_transact_sync_reply(
 | 
				
			||||||
    GBinderClient* client,
 | 
					    GBinderClient* client,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										194
									
								
								include/gbinder_eventloop.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										194
									
								
								include/gbinder_eventloop.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,194 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2020 Jolla Ltd.
 | 
				
			||||||
 | 
					 * Copyright (C) 2020 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   1. Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 | 
					 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
				
			||||||
 | 
					 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
				
			||||||
 | 
					 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
				
			||||||
 | 
					 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
				
			||||||
 | 
					 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
				
			||||||
 | 
					 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
				
			||||||
 | 
					 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
				
			||||||
 | 
					 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
				
			||||||
 | 
					 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GBINDER_EVENTLOOP_H
 | 
				
			||||||
 | 
					#define GBINDER_EVENTLOOP_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "gbinder_types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					G_BEGIN_DECLS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Since 1.0.40 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_eventloop_integration GBinderEventLoopIntegration;
 | 
				
			||||||
 | 
					typedef void (*GBinderEventLoopCallbackFunc)(gpointer data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_eventloop_timeout {
 | 
				
			||||||
 | 
					    const GBinderEventLoopIntegration* eventloop;
 | 
				
			||||||
 | 
					} GBinderEventLoopTimeout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_eventloop_callback {
 | 
				
			||||||
 | 
					    const GBinderEventLoopIntegration* eventloop;
 | 
				
			||||||
 | 
					} GBinderEventLoopCallback;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Main event loop integration. There is only one main event loop in the
 | 
				
			||||||
 | 
					 * process (by definition).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * By default, GLib event loop is being used for callbacks and timeouts.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * It may be necessary to replace it with e.g. Qt event loop. Quite often
 | 
				
			||||||
 | 
					 * Qt event loop is implemented by QEventDispatcherGlib which is sitting
 | 
				
			||||||
 | 
					 * on top of GLib event and therefore works with the default implementation.
 | 
				
			||||||
 | 
					 * But it won't work with e.g. QEventDispatcherUNIX.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * For Qt programs that use QEventDispatcherUNIX, it needs to be replaced
 | 
				
			||||||
 | 
					 * with the one provided by libqbinder.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef struct gbinder_eventloop_integration {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * timeout_add
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * Sets a function to be called at regular intervals (in milliseconds).
 | 
				
			||||||
 | 
					     * If the function returns G_SOURCE_REMOVE, timeout is automatically
 | 
				
			||||||
 | 
					     * destroyed (you must not call timeout_remove in this case). If the
 | 
				
			||||||
 | 
					     * function returns G_SOURCE_CONTINUE, it will be called again after
 | 
				
			||||||
 | 
					     * the same interval.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    GBinderEventLoopTimeout* (*timeout_add)(guint millis, GSourceFunc func,
 | 
				
			||||||
 | 
					        gpointer data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * timeout_remove
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * Removes a pending timeout and destroys it. The caller makes sure that
 | 
				
			||||||
 | 
					     * argument is not NULL. Note that timeout is automatically destroyed if
 | 
				
			||||||
 | 
					     * the callback function returns G_SOURCE_REMOVE.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void (*timeout_remove)(GBinderEventLoopTimeout* timeout);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * callback_new
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * Creates a callback object. It returns you a reference, you must
 | 
				
			||||||
 | 
					     * eventually pass the returned object to callback_unref to drop
 | 
				
			||||||
 | 
					     * this reference.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * Note that it doesn't automatically schedule the callback. You
 | 
				
			||||||
 | 
					     * must explicitly call callback_schedule to actually schedule it.
 | 
				
			||||||
 | 
					     * The finalize function is invoked regardless of whether callback
 | 
				
			||||||
 | 
					     * was cancelled or not.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    GBinderEventLoopCallback* (*callback_new)(GBinderEventLoopCallbackFunc fun,
 | 
				
			||||||
 | 
					        gpointer data, GDestroyNotify finalize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * callback_ref
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * Increments the reference count. That prevents the object from being
 | 
				
			||||||
 | 
					     * deleted before you drop this reference. The caller makes sure that
 | 
				
			||||||
 | 
					     * argument is not NULL.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void (*callback_ref)(GBinderEventLoopCallback* cb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * callback_unref
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * Decrements the reference count (drops the reference). When reference
 | 
				
			||||||
 | 
					     * count reaches zero, the object gets deleted. The caller makes sure
 | 
				
			||||||
 | 
					     * that argument is not NULL.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * Note that calling callback_schedule temporarily adds an internal
 | 
				
			||||||
 | 
					     * reference until the callback is invoked or callback_cancel is called,
 | 
				
			||||||
 | 
					     * whichever happens first.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void (*callback_unref)(GBinderEventLoopCallback* cb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * callback_schedule
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * Schedules the callback to be invoked in the main loop at some point
 | 
				
			||||||
 | 
					     * in the future (but as soon as possible). The caller makes sure that
 | 
				
			||||||
 | 
					     * argument is not NULL.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * This adds an internal reference to the GBinderEventLoopCallback object
 | 
				
			||||||
 | 
					     * until the callback is invoked or callback_cancel is called, whichever
 | 
				
			||||||
 | 
					     * happens first.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void (*callback_schedule)(GBinderEventLoopCallback* cb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * callback_cancel
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * Makes sure that callback won't be invoked (if it hasn't been
 | 
				
			||||||
 | 
					     * invoked yet) and drops the internal reference. Does nothing
 | 
				
			||||||
 | 
					     * if the callback has already been invoked. The caller makes sure that
 | 
				
			||||||
 | 
					     * argument is not NULL.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void (*callback_cancel)(GBinderEventLoopCallback* cb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * cleanup
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * This function is called when event loop integration is being replaced
 | 
				
			||||||
 | 
					     * with a different one, or libgbinder is being unloaded.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void (*cleanup)(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Padding for future expansion */
 | 
				
			||||||
 | 
					    void (*_reserved1)(void);
 | 
				
			||||||
 | 
					    void (*_reserved2)(void);
 | 
				
			||||||
 | 
					    void (*_reserved3)(void);
 | 
				
			||||||
 | 
					    void (*_reserved4)(void);
 | 
				
			||||||
 | 
					    void (*_reserved5)(void);
 | 
				
			||||||
 | 
					    void (*_reserved6)(void);
 | 
				
			||||||
 | 
					    void (*_reserved7)(void);
 | 
				
			||||||
 | 
					    void (*_reserved8)(void);
 | 
				
			||||||
 | 
					    void (*_reserved9)(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * api_level will remain zero (and ignored) until we run out of
 | 
				
			||||||
 | 
					     * the above placeholders. Hopefully, forever.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    int api_level;
 | 
				
			||||||
 | 
					} GBinderEventLoopIntegration;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * gbinder_eventloop_set should be called before libgbinder creates any of
 | 
				
			||||||
 | 
					 * its internal threads. And it must be done from the main thread.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_eventloop_set(
 | 
				
			||||||
 | 
					    const GBinderEventLoopIntegration* loop);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					G_END_DECLS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* GBINDER_EVENTLOOP_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Local Variables:
 | 
				
			||||||
 | 
					 * mode: C
 | 
				
			||||||
 | 
					 * c-basic-offset: 4
 | 
				
			||||||
 | 
					 * indent-tabs-mode: nil
 | 
				
			||||||
 | 
					 * End:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
							
								
								
									
										154
									
								
								include/gbinder_fmq.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								include/gbinder_fmq.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,154 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2021 Jolla Ltd.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   1. Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 | 
					 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
				
			||||||
 | 
					 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
				
			||||||
 | 
					 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
				
			||||||
 | 
					 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
				
			||||||
 | 
					 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
				
			||||||
 | 
					 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
				
			||||||
 | 
					 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
				
			||||||
 | 
					 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
				
			||||||
 | 
					 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GBINDER_FMQ_H
 | 
				
			||||||
 | 
					#define GBINDER_FMQ_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gbinder_types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					G_BEGIN_DECLS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Since 1.1.14 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef enum gbinder_fmq_type {
 | 
				
			||||||
 | 
					    GBINDER_FMQ_TYPE_SYNC_READ_WRITE = 1,
 | 
				
			||||||
 | 
					    GBINDER_FMQ_TYPE_UNSYNC_WRITE
 | 
				
			||||||
 | 
					} GBINDER_FMQ_TYPE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef enum gbinder_fmq_flags {
 | 
				
			||||||
 | 
					    GBINDER_FMQ_FLAG_CONFIGURE_EVENT_FLAG = 0x1,
 | 
				
			||||||
 | 
					    GBINDER_FMQ_FLAG_NO_RESET_POINTERS    = 0x2
 | 
				
			||||||
 | 
					} GBINDER_FMQ_FLAGS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderFmq*
 | 
				
			||||||
 | 
					gbinder_fmq_new(
 | 
				
			||||||
 | 
					    gsize item_size,
 | 
				
			||||||
 | 
					    gsize max_num_items,
 | 
				
			||||||
 | 
					    GBINDER_FMQ_TYPE type,
 | 
				
			||||||
 | 
					    GBINDER_FMQ_FLAGS flags,
 | 
				
			||||||
 | 
					    gint fd,
 | 
				
			||||||
 | 
					    gsize buffer_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderFmq*
 | 
				
			||||||
 | 
					gbinder_fmq_ref(
 | 
				
			||||||
 | 
					    GBinderFmq* fmq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_fmq_unref(
 | 
				
			||||||
 | 
					    GBinderFmq* fmq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Functions for checking how many items are available in queue */
 | 
				
			||||||
 | 
					gsize
 | 
				
			||||||
 | 
					gbinder_fmq_available_to_read(
 | 
				
			||||||
 | 
					    GBinderFmq* fmq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gsize
 | 
				
			||||||
 | 
					gbinder_fmq_available_to_write(
 | 
				
			||||||
 | 
					    GBinderFmq* fmq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gsize
 | 
				
			||||||
 | 
					gbinder_fmq_available_to_read_contiguous(
 | 
				
			||||||
 | 
					    GBinderFmq* fmq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gsize
 | 
				
			||||||
 | 
					gbinder_fmq_available_to_write_contiguous(
 | 
				
			||||||
 | 
					    GBinderFmq* fmq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Functions for obtaining data pointer for zero copy read/write */
 | 
				
			||||||
 | 
					const void*
 | 
				
			||||||
 | 
					gbinder_fmq_begin_read(
 | 
				
			||||||
 | 
					    GBinderFmq* fmq,
 | 
				
			||||||
 | 
					    gsize items);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void*
 | 
				
			||||||
 | 
					gbinder_fmq_begin_write(
 | 
				
			||||||
 | 
					    GBinderFmq* fmq,
 | 
				
			||||||
 | 
					    gsize items);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Functions for ending zero copy read/write
 | 
				
			||||||
 | 
					 * The number of items must match the value provided to gbinder_fmq_begin_read
 | 
				
			||||||
 | 
					 * or gbinder_fmq_begin_write */
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_fmq_end_read(
 | 
				
			||||||
 | 
					    GBinderFmq* fmq,
 | 
				
			||||||
 | 
					    gsize items);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_fmq_end_write(
 | 
				
			||||||
 | 
					    GBinderFmq* fmq,
 | 
				
			||||||
 | 
					    gsize items);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Regular read/write functions (non-zero-copy) */
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_fmq_read(
 | 
				
			||||||
 | 
					    GBinderFmq* fmq,
 | 
				
			||||||
 | 
					    void* data,
 | 
				
			||||||
 | 
					    gsize items);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_fmq_write(
 | 
				
			||||||
 | 
					    GBinderFmq* fmq,
 | 
				
			||||||
 | 
					    const void* data,
 | 
				
			||||||
 | 
					    gsize items);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Functions for waiting and waking message queue.
 | 
				
			||||||
 | 
					 * Requires configured event flag in message queue.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					gbinder_fmq_wait_timeout(
 | 
				
			||||||
 | 
					    GBinderFmq* fmq,
 | 
				
			||||||
 | 
					    guint32 bit_mask,
 | 
				
			||||||
 | 
					    guint32* state,
 | 
				
			||||||
 | 
					    int timeout_ms);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define gbinder_fmq_try_wait(fmq, mask, state) \
 | 
				
			||||||
 | 
					    gbinder_fmq_wait_timeout(fmq, mask, state, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define gbinder_fmq_wait(fmq, mask, state) \
 | 
				
			||||||
 | 
					    gbinder_fmq_wait_timeout(fmq, mask, state, -1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					gbinder_fmq_wake(
 | 
				
			||||||
 | 
					    GBinderFmq* fmq,
 | 
				
			||||||
 | 
					    guint32 bit_mask);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					G_END_DECLS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* GBINDER_FMQ_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Local Variables:
 | 
				
			||||||
 | 
					 * mode: C
 | 
				
			||||||
 | 
					 * c-basic-offset: 4
 | 
				
			||||||
 | 
					 * indent-tabs-mode: nil
 | 
				
			||||||
 | 
					 * End:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2019 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -37,6 +37,14 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
G_BEGIN_DECLS
 | 
					G_BEGIN_DECLS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderLocalObject*
 | 
				
			||||||
 | 
					gbinder_local_object_new(
 | 
				
			||||||
 | 
					    GBinderIpc* ipc,
 | 
				
			||||||
 | 
					    const char* const* ifaces,
 | 
				
			||||||
 | 
					    GBinderLocalTransactFunc handler,
 | 
				
			||||||
 | 
					    void* user_data) /* Since 1.0.30 */
 | 
				
			||||||
 | 
					    G_GNUC_WARN_UNUSED_RESULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderLocalObject*
 | 
					GBinderLocalObject*
 | 
				
			||||||
gbinder_local_object_ref(
 | 
					gbinder_local_object_ref(
 | 
				
			||||||
    GBinderLocalObject* obj);
 | 
					    GBinderLocalObject* obj);
 | 
				
			||||||
@@ -53,6 +61,11 @@ GBinderLocalReply*
 | 
				
			|||||||
gbinder_local_object_new_reply(
 | 
					gbinder_local_object_new_reply(
 | 
				
			||||||
    GBinderLocalObject* obj);
 | 
					    GBinderLocalObject* obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_local_object_set_stability(
 | 
				
			||||||
 | 
					    GBinderLocalObject* self,
 | 
				
			||||||
 | 
					    GBINDER_STABILITY_LEVEL stability); /* Since 1.1.40 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
G_END_DECLS
 | 
					G_END_DECLS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* GBINDER_LOCAL_OBJECT_H */
 | 
					#endif /* GBINDER_LOCAL_OBJECT_H */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -112,6 +112,11 @@ gbinder_local_reply_append_remote_object(
 | 
				
			|||||||
    GBinderLocalReply* reply,
 | 
					    GBinderLocalReply* reply,
 | 
				
			||||||
    GBinderRemoteObject* obj);
 | 
					    GBinderRemoteObject* obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderLocalReply*
 | 
				
			||||||
 | 
					gbinder_local_reply_append_fd(
 | 
				
			||||||
 | 
					    GBinderLocalReply* reply,
 | 
				
			||||||
 | 
					    int fd); /* Since 1.1.14 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
G_END_DECLS
 | 
					G_END_DECLS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* GBINDER_LOCAL_OBJECT_H */
 | 
					#endif /* GBINDER_LOCAL_OBJECT_H */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -53,7 +53,7 @@ struct gbinder_reader {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
gboolean
 | 
					gboolean
 | 
				
			||||||
gbinder_reader_at_end(
 | 
					gbinder_reader_at_end(
 | 
				
			||||||
    GBinderReader* reader);
 | 
					    const GBinderReader* reader);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gboolean
 | 
					gboolean
 | 
				
			||||||
gbinder_reader_read_byte(
 | 
					gbinder_reader_read_byte(
 | 
				
			||||||
@@ -65,6 +65,26 @@ gbinder_reader_read_bool(
 | 
				
			|||||||
    GBinderReader* reader,
 | 
					    GBinderReader* reader,
 | 
				
			||||||
    gboolean* value);
 | 
					    gboolean* value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_reader_read_int8(
 | 
				
			||||||
 | 
					    GBinderReader* reader,
 | 
				
			||||||
 | 
					    gint8* value); /* Since 1.1.15 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_reader_read_uint8(
 | 
				
			||||||
 | 
					    GBinderReader* reader,
 | 
				
			||||||
 | 
					    guint8* value); /* Since 1.1.15 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_reader_read_int16(
 | 
				
			||||||
 | 
					    GBinderReader* reader,
 | 
				
			||||||
 | 
					    gint16* value); /* Since 1.1.15 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_reader_read_uint16(
 | 
				
			||||||
 | 
					    GBinderReader* reader,
 | 
				
			||||||
 | 
					    guint16* value); /* Since 1.1.15 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gboolean
 | 
					gboolean
 | 
				
			||||||
gbinder_reader_read_int32(
 | 
					gbinder_reader_read_int32(
 | 
				
			||||||
    GBinderReader* reader,
 | 
					    GBinderReader* reader,
 | 
				
			||||||
@@ -95,6 +115,15 @@ gbinder_reader_read_double(
 | 
				
			|||||||
    GBinderReader* reader,
 | 
					    GBinderReader* reader,
 | 
				
			||||||
    gdouble* value);
 | 
					    gdouble* value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					gbinder_reader_read_fd(
 | 
				
			||||||
 | 
					    GBinderReader* reader); /* Since 1.0.18 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					gbinder_reader_read_dup_fd(
 | 
				
			||||||
 | 
					    GBinderReader* reader) /* Since 1.0.18 */
 | 
				
			||||||
 | 
					    G_GNUC_WARN_UNUSED_RESULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gboolean
 | 
					gboolean
 | 
				
			||||||
gbinder_reader_read_nullable_object(
 | 
					gbinder_reader_read_nullable_object(
 | 
				
			||||||
    GBinderReader* reader,
 | 
					    GBinderReader* reader,
 | 
				
			||||||
@@ -113,11 +142,48 @@ gbinder_reader_read_buffer(
 | 
				
			|||||||
    GBinderReader* reader)
 | 
					    GBinderReader* reader)
 | 
				
			||||||
    G_GNUC_WARN_UNUSED_RESULT;
 | 
					    G_GNUC_WARN_UNUSED_RESULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const void*
 | 
				
			||||||
 | 
					gbinder_reader_read_parcelable(
 | 
				
			||||||
 | 
					    GBinderReader* reader,
 | 
				
			||||||
 | 
					    gsize* size); /* Since 1.1.19 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const void*
 | 
				
			||||||
 | 
					gbinder_reader_read_hidl_struct1(
 | 
				
			||||||
 | 
					    GBinderReader* reader,
 | 
				
			||||||
 | 
					    gsize size); /* Since 1.0.9 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define gbinder_reader_read_hidl_struct(reader,type) \
 | 
				
			||||||
 | 
					    ((const type*)gbinder_reader_read_hidl_struct1(reader, sizeof(type)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const void*
 | 
				
			||||||
 | 
					gbinder_reader_read_hidl_vec(
 | 
				
			||||||
 | 
					    GBinderReader* reader,
 | 
				
			||||||
 | 
					    gsize* count,
 | 
				
			||||||
 | 
					    gsize* elemsize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const void*
 | 
				
			||||||
 | 
					gbinder_reader_read_hidl_vec1(
 | 
				
			||||||
 | 
					    GBinderReader* reader,
 | 
				
			||||||
 | 
					    gsize* count,
 | 
				
			||||||
 | 
					    guint expected_elemsize); /* Since 1.0.9 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define gbinder_reader_read_hidl_type_vec(reader,type,count) \
 | 
				
			||||||
 | 
					    ((const type*)gbinder_reader_read_hidl_vec1(reader, count, sizeof(type)))
 | 
				
			||||||
 | 
					#define gbinder_reader_read_hidl_byte_vec(reader,count) /* vec<uint8_t> */ \
 | 
				
			||||||
 | 
					    gbinder_reader_read_hidl_type_vec(reader,guint8,count)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
char*
 | 
					char*
 | 
				
			||||||
gbinder_reader_read_hidl_string(
 | 
					gbinder_reader_read_hidl_string(
 | 
				
			||||||
    GBinderReader* reader)
 | 
					    GBinderReader* reader)
 | 
				
			||||||
    G_GNUC_WARN_UNUSED_RESULT;
 | 
					    G_GNUC_WARN_UNUSED_RESULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char*
 | 
				
			||||||
 | 
					gbinder_reader_read_hidl_string_c(
 | 
				
			||||||
 | 
					    GBinderReader* reader); /* Since 1.0.23 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define gbinder_reader_skip_hidl_string(reader) \
 | 
				
			||||||
 | 
					    (gbinder_reader_read_hidl_string_c(reader) != NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
char**
 | 
					char**
 | 
				
			||||||
gbinder_reader_read_hidl_string_vec(
 | 
					gbinder_reader_read_hidl_string_vec(
 | 
				
			||||||
    GBinderReader* reader);
 | 
					    GBinderReader* reader);
 | 
				
			||||||
@@ -140,17 +206,43 @@ gbinder_reader_read_nullable_string16(
 | 
				
			|||||||
    GBinderReader* reader,
 | 
					    GBinderReader* reader,
 | 
				
			||||||
    char** out);
 | 
					    char** out);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_reader_read_nullable_string16_utf16(
 | 
				
			||||||
 | 
					    GBinderReader* reader,
 | 
				
			||||||
 | 
					    const gunichar2** out,
 | 
				
			||||||
 | 
					    gsize* len); /* Since 1.0.17 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const gunichar2*
 | 
				
			||||||
 | 
					gbinder_reader_read_string16_utf16(
 | 
				
			||||||
 | 
					    GBinderReader* reader,
 | 
				
			||||||
 | 
					    gsize* len); /* Since 1.0.26 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gboolean
 | 
					gboolean
 | 
				
			||||||
gbinder_reader_skip_string16(
 | 
					gbinder_reader_skip_string16(
 | 
				
			||||||
    GBinderReader* reader);
 | 
					    GBinderReader* reader);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const void*
 | 
				
			||||||
 | 
					gbinder_reader_read_byte_array(
 | 
				
			||||||
 | 
					    GBinderReader* reader,
 | 
				
			||||||
 | 
					    gsize* len); /* Since 1.0.12 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const void*
 | 
				
			||||||
 | 
					gbinder_reader_get_data(
 | 
				
			||||||
 | 
					    const GBinderReader* reader,
 | 
				
			||||||
 | 
					    gsize* size); /* Since 1.1.14 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gsize
 | 
					gsize
 | 
				
			||||||
gbinder_reader_bytes_read(
 | 
					gbinder_reader_bytes_read(
 | 
				
			||||||
    GBinderReader* reader);
 | 
					    const GBinderReader* reader);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gsize
 | 
					gsize
 | 
				
			||||||
gbinder_reader_bytes_remaining(
 | 
					gbinder_reader_bytes_remaining(
 | 
				
			||||||
    GBinderReader* reader);
 | 
					    const GBinderReader* reader);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_reader_copy(
 | 
				
			||||||
 | 
					    GBinderReader* dest,
 | 
				
			||||||
 | 
					    const GBinderReader* src); /* Since 1.0.16 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
G_END_DECLS
 | 
					G_END_DECLS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2019 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2019 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -51,6 +51,10 @@ void
 | 
				
			|||||||
gbinder_remote_object_unref(
 | 
					gbinder_remote_object_unref(
 | 
				
			||||||
    GBinderRemoteObject* obj);
 | 
					    GBinderRemoteObject* obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderIpc*
 | 
				
			||||||
 | 
					gbinder_remote_object_ipc(
 | 
				
			||||||
 | 
					    GBinderRemoteObject* obj); /* Since 1.0.30 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gboolean
 | 
					gboolean
 | 
				
			||||||
gbinder_remote_object_is_dead(
 | 
					gbinder_remote_object_is_dead(
 | 
				
			||||||
    GBinderRemoteObject* obj);
 | 
					    GBinderRemoteObject* obj);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived from
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -50,6 +50,11 @@ gbinder_remote_reply_init_reader(
 | 
				
			|||||||
    GBinderRemoteReply* reply,
 | 
					    GBinderRemoteReply* reply,
 | 
				
			||||||
    GBinderReader* reader);
 | 
					    GBinderReader* reader);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderLocalReply*
 | 
				
			||||||
 | 
					gbinder_remote_reply_copy_to_local(
 | 
				
			||||||
 | 
					    GBinderRemoteReply* reply) /* since 1.0.6 */
 | 
				
			||||||
 | 
					    G_GNUC_WARN_UNUSED_RESULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Convenience function to decode replies with just one data item */
 | 
					/* Convenience function to decode replies with just one data item */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gboolean
 | 
					gboolean
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived from
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -62,6 +62,21 @@ uid_t
 | 
				
			|||||||
gbinder_remote_request_sender_euid(
 | 
					gbinder_remote_request_sender_euid(
 | 
				
			||||||
    GBinderRemoteRequest* req); /* since 1.0.2 */
 | 
					    GBinderRemoteRequest* req); /* since 1.0.2 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderLocalRequest*
 | 
				
			||||||
 | 
					gbinder_remote_request_copy_to_local(
 | 
				
			||||||
 | 
					    GBinderRemoteRequest* req) /* since 1.0.6 */
 | 
				
			||||||
 | 
					    G_GNUC_WARN_UNUSED_RESULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_remote_request_block(
 | 
				
			||||||
 | 
					    GBinderRemoteRequest* req); /* Since 1.0.20 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_remote_request_complete(
 | 
				
			||||||
 | 
					    GBinderRemoteRequest* req,
 | 
				
			||||||
 | 
					    GBinderLocalReply* reply,
 | 
				
			||||||
 | 
					    int status); /* Since 1.0.20 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Convenience function to decode requests with just one data item */
 | 
					/* Convenience function to decode requests with just one data item */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gboolean
 | 
					gboolean
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -37,6 +37,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
G_BEGIN_DECLS
 | 
					G_BEGIN_DECLS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					(*GBinderServiceManagerFunc)(
 | 
				
			||||||
 | 
					    GBinderServiceManager* sm,
 | 
				
			||||||
 | 
					    void* user_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* GBinderServiceManagerListFunc callback returns TRUE to keep the services
 | 
					/* GBinderServiceManagerListFunc callback returns TRUE to keep the services
 | 
				
			||||||
 * list, otherwise the caller will deallocate it. */
 | 
					 * list, otherwise the caller will deallocate it. */
 | 
				
			||||||
typedef
 | 
					typedef
 | 
				
			||||||
@@ -61,24 +67,50 @@ void
 | 
				
			|||||||
    int status,
 | 
					    int status,
 | 
				
			||||||
    void* user_data);
 | 
					    void* user_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					(*GBinderServiceManagerRegistrationFunc)(
 | 
				
			||||||
 | 
					    GBinderServiceManager* sm,
 | 
				
			||||||
 | 
					    const char* name,
 | 
				
			||||||
 | 
					    void* user_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderServiceManager*
 | 
					GBinderServiceManager*
 | 
				
			||||||
gbinder_servicemanager_new(
 | 
					gbinder_servicemanager_new(
 | 
				
			||||||
    const char* dev);
 | 
					    const char* dev)
 | 
				
			||||||
 | 
					    G_GNUC_WARN_UNUSED_RESULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderServiceManager*
 | 
				
			||||||
 | 
					gbinder_servicemanager_new2(
 | 
				
			||||||
 | 
					    const char* dev,
 | 
				
			||||||
 | 
					    const char* sm_protocol,
 | 
				
			||||||
 | 
					    const char* rpc_protocol) /* Since 1.1.20 */
 | 
				
			||||||
 | 
					    G_GNUC_WARN_UNUSED_RESULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderServiceManager*
 | 
					GBinderServiceManager*
 | 
				
			||||||
gbinder_defaultservicemanager_new(
 | 
					gbinder_defaultservicemanager_new(
 | 
				
			||||||
    const char* dev);
 | 
					    const char* dev)
 | 
				
			||||||
 | 
					    G_DEPRECATED_FOR(gbinder_servicemanager_new);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderServiceManager*
 | 
					GBinderServiceManager*
 | 
				
			||||||
gbinder_hwservicemanager_new(
 | 
					gbinder_hwservicemanager_new(
 | 
				
			||||||
    const char* dev);
 | 
					    const char* dev)
 | 
				
			||||||
 | 
					    G_DEPRECATED_FOR(gbinder_servicemanager_new);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderLocalObject*
 | 
					GBinderLocalObject*
 | 
				
			||||||
gbinder_servicemanager_new_local_object(
 | 
					gbinder_servicemanager_new_local_object(
 | 
				
			||||||
    GBinderServiceManager* sm,
 | 
					    GBinderServiceManager* sm,
 | 
				
			||||||
    const char* iface,
 | 
					    const char* iface,
 | 
				
			||||||
    GBinderLocalTransactFunc handler,
 | 
					    GBinderLocalTransactFunc handler,
 | 
				
			||||||
    void* user_data);
 | 
					    void* user_data)
 | 
				
			||||||
 | 
					    G_GNUC_WARN_UNUSED_RESULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderLocalObject*
 | 
				
			||||||
 | 
					gbinder_servicemanager_new_local_object2(
 | 
				
			||||||
 | 
					    GBinderServiceManager* sm,
 | 
				
			||||||
 | 
					    const char* const* ifaces,
 | 
				
			||||||
 | 
					    GBinderLocalTransactFunc handler,
 | 
				
			||||||
 | 
					    void* user_data) /* Since 1.0.29 */
 | 
				
			||||||
 | 
					    G_GNUC_WARN_UNUSED_RESULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderServiceManager*
 | 
					GBinderServiceManager*
 | 
				
			||||||
gbinder_servicemanager_ref(
 | 
					gbinder_servicemanager_ref(
 | 
				
			||||||
@@ -88,6 +120,19 @@ void
 | 
				
			|||||||
gbinder_servicemanager_unref(
 | 
					gbinder_servicemanager_unref(
 | 
				
			||||||
    GBinderServiceManager* sm);
 | 
					    GBinderServiceManager* sm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char*
 | 
				
			||||||
 | 
					gbinder_servicemanager_device(
 | 
				
			||||||
 | 
					    GBinderServiceManager* sm); /* Since 1.1.14 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_servicemanager_is_present(
 | 
				
			||||||
 | 
					    GBinderServiceManager* sm); /* Since 1.0.25 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_servicemanager_wait(
 | 
				
			||||||
 | 
					    GBinderServiceManager* sm,
 | 
				
			||||||
 | 
					    long max_wait_ms); /* Since 1.0.25 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gulong
 | 
					gulong
 | 
				
			||||||
gbinder_servicemanager_list(
 | 
					gbinder_servicemanager_list(
 | 
				
			||||||
    GBinderServiceManager* sm,
 | 
					    GBinderServiceManager* sm,
 | 
				
			||||||
@@ -96,7 +141,9 @@ gbinder_servicemanager_list(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
char**
 | 
					char**
 | 
				
			||||||
gbinder_servicemanager_list_sync(
 | 
					gbinder_servicemanager_list_sync(
 | 
				
			||||||
    GBinderServiceManager* sm);
 | 
					    GBinderServiceManager* sm)
 | 
				
			||||||
 | 
					    G_GNUC_WARN_UNUSED_RESULT
 | 
				
			||||||
 | 
					    G_GNUC_MALLOC;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gulong
 | 
					gulong
 | 
				
			||||||
gbinder_servicemanager_get_service(
 | 
					gbinder_servicemanager_get_service(
 | 
				
			||||||
@@ -130,6 +177,33 @@ gbinder_servicemanager_cancel(
 | 
				
			|||||||
    GBinderServiceManager* sm,
 | 
					    GBinderServiceManager* sm,
 | 
				
			||||||
    gulong id);
 | 
					    gulong id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gulong
 | 
				
			||||||
 | 
					gbinder_servicemanager_add_presence_handler(
 | 
				
			||||||
 | 
					    GBinderServiceManager* sm,
 | 
				
			||||||
 | 
					    GBinderServiceManagerFunc func,
 | 
				
			||||||
 | 
					    void* user_data); /* Since 1.0.25 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gulong
 | 
				
			||||||
 | 
					gbinder_servicemanager_add_registration_handler(
 | 
				
			||||||
 | 
					    GBinderServiceManager* sm,
 | 
				
			||||||
 | 
					    const char* name,
 | 
				
			||||||
 | 
					    GBinderServiceManagerRegistrationFunc func,
 | 
				
			||||||
 | 
					    void* user_data); /* Since 1.0.13 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_remove_handler(
 | 
				
			||||||
 | 
					    GBinderServiceManager* sm,
 | 
				
			||||||
 | 
					    gulong id); /* Since 1.0.13 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_remove_handlers(
 | 
				
			||||||
 | 
					    GBinderServiceManager* sm,
 | 
				
			||||||
 | 
					    gulong* ids,
 | 
				
			||||||
 | 
					    guint count); /* Since 1.0.25 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define gbinder_servicemanager_remove_all_handlers(sm,ids) \
 | 
				
			||||||
 | 
					    gbinder_servicemanager_remove_handlers(sm, ids, G_N_ELEMENTS(ids))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
G_END_DECLS
 | 
					G_END_DECLS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* GBINDER_SERVICEMANAGER_H */
 | 
					#endif /* GBINDER_SERVICEMANAGER_H */
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										70
									
								
								include/gbinder_servicename.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								include/gbinder_servicename.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2019 Jolla Ltd.
 | 
				
			||||||
 | 
					 * Copyright (C) 2019 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   1. Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 | 
					 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
				
			||||||
 | 
					 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
				
			||||||
 | 
					 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
				
			||||||
 | 
					 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
				
			||||||
 | 
					 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
				
			||||||
 | 
					 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
				
			||||||
 | 
					 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
				
			||||||
 | 
					 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
				
			||||||
 | 
					 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GBINDER_SERVICENAME_H
 | 
				
			||||||
 | 
					#define GBINDER_SERVICENAME_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "gbinder_types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					G_BEGIN_DECLS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Since 1.0.26 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gbinder_servicename {
 | 
				
			||||||
 | 
					    const char* name;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderServiceName*
 | 
				
			||||||
 | 
					gbinder_servicename_new(
 | 
				
			||||||
 | 
					    GBinderServiceManager* sm,
 | 
				
			||||||
 | 
					    GBinderLocalObject* object,
 | 
				
			||||||
 | 
					    const char* name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderServiceName*
 | 
				
			||||||
 | 
					gbinder_servicename_ref(
 | 
				
			||||||
 | 
					    GBinderServiceName* name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicename_unref(
 | 
				
			||||||
 | 
					    GBinderServiceName* name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					G_END_DECLS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* GBINDER_SERVICENAME_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Local Variables:
 | 
				
			||||||
 | 
					 * mode: C
 | 
				
			||||||
 | 
					 * c-basic-offset: 4
 | 
				
			||||||
 | 
					 * indent-tabs-mode: nil
 | 
				
			||||||
 | 
					 * End:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -59,8 +59,11 @@ G_BEGIN_DECLS
 | 
				
			|||||||
 * 6. Reader parses the data coming with RemoteRequest and RemoteReply
 | 
					 * 6. Reader parses the data coming with RemoteRequest and RemoteReply
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_bridge GBinderBridge; /* Since 1.1.5 */
 | 
				
			||||||
typedef struct gbinder_buffer GBinderBuffer;
 | 
					typedef struct gbinder_buffer GBinderBuffer;
 | 
				
			||||||
typedef struct gbinder_client GBinderClient;
 | 
					typedef struct gbinder_client GBinderClient;
 | 
				
			||||||
 | 
					typedef struct gbinder_fmq GBinderFmq;  /* Since 1.1.14 */
 | 
				
			||||||
 | 
					typedef struct gbinder_ipc GBinderIpc;
 | 
				
			||||||
typedef struct gbinder_local_object GBinderLocalObject;
 | 
					typedef struct gbinder_local_object GBinderLocalObject;
 | 
				
			||||||
typedef struct gbinder_local_reply GBinderLocalReply;
 | 
					typedef struct gbinder_local_reply GBinderLocalReply;
 | 
				
			||||||
typedef struct gbinder_local_request GBinderLocalRequest;
 | 
					typedef struct gbinder_local_request GBinderLocalRequest;
 | 
				
			||||||
@@ -68,10 +71,80 @@ typedef struct gbinder_reader GBinderReader;
 | 
				
			|||||||
typedef struct gbinder_remote_object GBinderRemoteObject;
 | 
					typedef struct gbinder_remote_object GBinderRemoteObject;
 | 
				
			||||||
typedef struct gbinder_remote_reply GBinderRemoteReply;
 | 
					typedef struct gbinder_remote_reply GBinderRemoteReply;
 | 
				
			||||||
typedef struct gbinder_remote_request GBinderRemoteRequest;
 | 
					typedef struct gbinder_remote_request GBinderRemoteRequest;
 | 
				
			||||||
 | 
					typedef struct gbinder_servicename GBinderServiceName;
 | 
				
			||||||
typedef struct gbinder_servicemanager GBinderServiceManager;
 | 
					typedef struct gbinder_servicemanager GBinderServiceManager;
 | 
				
			||||||
typedef struct gbinder_writer GBinderWriter;
 | 
					typedef struct gbinder_writer GBinderWriter;
 | 
				
			||||||
typedef struct gbinder_parent GBinderParent;
 | 
					typedef struct gbinder_parent GBinderParent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Basic HIDL types */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define GBINDER_ALIGNED(x) __attribute__ ((aligned(x)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_hidl_vec {
 | 
				
			||||||
 | 
					    union {
 | 
				
			||||||
 | 
					        guint64 value;
 | 
				
			||||||
 | 
					        const void* ptr;
 | 
				
			||||||
 | 
					    } data;
 | 
				
			||||||
 | 
					    guint32 count;
 | 
				
			||||||
 | 
					    guint8 owns_buffer;
 | 
				
			||||||
 | 
					    guint8 pad[3];
 | 
				
			||||||
 | 
					} GBinderHidlVec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define GBINDER_HIDL_VEC_BUFFER_OFFSET (0)
 | 
				
			||||||
 | 
					G_STATIC_ASSERT(sizeof(GBinderHidlVec) == 16);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_hidl_string {
 | 
				
			||||||
 | 
					    union {
 | 
				
			||||||
 | 
					        guint64 value;
 | 
				
			||||||
 | 
					        const char* str;
 | 
				
			||||||
 | 
					    } data;
 | 
				
			||||||
 | 
					    guint32 len;
 | 
				
			||||||
 | 
					    guint8 owns_buffer;
 | 
				
			||||||
 | 
					    guint8 pad[3];
 | 
				
			||||||
 | 
					} GBinderHidlString;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define GBINDER_HIDL_STRING_BUFFER_OFFSET (0)
 | 
				
			||||||
 | 
					G_STATIC_ASSERT(sizeof(GBinderHidlString) == 16);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_fds {
 | 
				
			||||||
 | 
					    guint32 version GBINDER_ALIGNED(4);
 | 
				
			||||||
 | 
					    guint32 num_fds GBINDER_ALIGNED(4);
 | 
				
			||||||
 | 
					    guint32 num_ints GBINDER_ALIGNED(4);
 | 
				
			||||||
 | 
					} GBINDER_ALIGNED(4) GBinderFds;  /* Since 1.1.4 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Actual fds immediately follow GBinderFds: */
 | 
				
			||||||
 | 
					#define gbinder_fds_get_fd(fds,i) (((const int*)((fds) + 1))[i])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define GBINDER_HIDL_FDS_VERSION (12)
 | 
				
			||||||
 | 
					G_STATIC_ASSERT(sizeof(GBinderFds) == GBINDER_HIDL_FDS_VERSION);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_hidl_handle {
 | 
				
			||||||
 | 
					    union {
 | 
				
			||||||
 | 
					        guint64 value;
 | 
				
			||||||
 | 
					        const GBinderFds* fds;
 | 
				
			||||||
 | 
					    } data;
 | 
				
			||||||
 | 
					    guint8 owns_handle;
 | 
				
			||||||
 | 
					    guint8 pad[7];
 | 
				
			||||||
 | 
					} GBinderHidlHandle; /* Since 1.1.4 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define GBINDER_HIDL_HANDLE_VALUE_OFFSET (0)
 | 
				
			||||||
 | 
					G_STATIC_ASSERT(sizeof(GBinderHidlHandle) == 16);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_hidl_memory {
 | 
				
			||||||
 | 
					    union {
 | 
				
			||||||
 | 
					        guint64 value;
 | 
				
			||||||
 | 
					        const GBinderFds* fds;
 | 
				
			||||||
 | 
					    } data;
 | 
				
			||||||
 | 
					    guint8 owns_buffer;
 | 
				
			||||||
 | 
					    guint8 pad[7];
 | 
				
			||||||
 | 
					    guint64 size;
 | 
				
			||||||
 | 
					    GBinderHidlString name;
 | 
				
			||||||
 | 
					} GBinderHidlMemory; /* Since 1.1.4 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define GBINDER_HIDL_MEMORY_PTR_OFFSET (0)
 | 
				
			||||||
 | 
					#define GBINDER_HIDL_MEMORY_NAME_OFFSET (24)
 | 
				
			||||||
 | 
					G_STATIC_ASSERT(sizeof(GBinderHidlMemory) == 40);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Each RPC call is identified by the interface name returned
 | 
					 * Each RPC call is identified by the interface name returned
 | 
				
			||||||
 * by gbinder_remote_request_interface() the transaction code.
 | 
					 * by gbinder_remote_request_interface() the transaction code.
 | 
				
			||||||
@@ -100,6 +173,13 @@ typedef enum gbinder_status {
 | 
				
			|||||||
    GBINDER_STATUS_DEAD_OBJECT
 | 
					    GBINDER_STATUS_DEAD_OBJECT
 | 
				
			||||||
} GBINDER_STATUS;
 | 
					} GBINDER_STATUS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef enum gbinder_stability_level {
 | 
				
			||||||
 | 
					    GBINDER_STABILITY_UNDECLARED = 0,
 | 
				
			||||||
 | 
					    GBINDER_STABILITY_VENDOR = 0x03,
 | 
				
			||||||
 | 
					    GBINDER_STABILITY_SYSTEM = 0x0c,
 | 
				
			||||||
 | 
					    GBINDER_STABILITY_VINTF = 0x3f
 | 
				
			||||||
 | 
					} GBINDER_STABILITY_LEVEL; /* Since 1.1.40 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define GBINDER_FOURCC(c1,c2,c3,c4) \
 | 
					#define GBINDER_FOURCC(c1,c2,c3,c4) \
 | 
				
			||||||
    (((c1) << 24) | ((c2) << 16) | ((c3) << 8) | (c4))
 | 
					    (((c1) << 24) | ((c2) << 16) | ((c3) << 8) | (c4))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -55,6 +55,119 @@ struct gbinder_parent {
 | 
				
			|||||||
    guint32 offset;
 | 
					    guint32 offset;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Note that gbinder_writer_append_struct() doesn't copy the data, it writes
 | 
				
			||||||
 | 
					 * buffer objects pointing to whatever was passed in. The caller must make
 | 
				
			||||||
 | 
					 * sure that those pointers outlive the transaction. That's most commonly
 | 
				
			||||||
 | 
					 * done with by using gbinder_writer_malloc() and friends for allocating
 | 
				
			||||||
 | 
					 * memory for the transaction.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Below is an example of initializing GBinderWriterType which can then
 | 
				
			||||||
 | 
					 * be passed to gbinder_writer_append_struct(). Fields have to be listed
 | 
				
			||||||
 | 
					 * in the order in which they appear in the structure.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *    typedef struct data {
 | 
				
			||||||
 | 
					 *        int x;
 | 
				
			||||||
 | 
					 *    } Data;
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *    typedef struct data2 {
 | 
				
			||||||
 | 
					 *        int y;
 | 
				
			||||||
 | 
					 *        GBinderHidlString str;
 | 
				
			||||||
 | 
					 *        GBinderHidlVec vec; // vec<Data>
 | 
				
			||||||
 | 
					 *    } Data2;
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *    static const GBinderWriterType data_t = {
 | 
				
			||||||
 | 
					 *        GBINDER_WRITER_STRUCT_NAME_AND_SIZE(Data), NULL
 | 
				
			||||||
 | 
					 *    };
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *    static const GBinderWriterField data2_f[] = {
 | 
				
			||||||
 | 
					 *        GBINDER_WRITER_FIELD_HIDL_STRING(Data2,str),
 | 
				
			||||||
 | 
					 *        GBINDER_WRITER_FIELD_HIDL_VEC(Data2, vec, &data_t),
 | 
				
			||||||
 | 
					 *        GBINDER_WRITER_FIELD_END()
 | 
				
			||||||
 | 
					 *    };
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *    static const GBinderWriterType data2_t = {
 | 
				
			||||||
 | 
					 *        GBINDER_WRITER_STRUCT_NAME_AND_SIZE(Data2), data2_f
 | 
				
			||||||
 | 
					 *    };
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_writer_type {
 | 
				
			||||||
 | 
					    const char* name;
 | 
				
			||||||
 | 
					    gsize size;
 | 
				
			||||||
 | 
					    const struct gbinder_writer_field* fields;
 | 
				
			||||||
 | 
					} GBinderWriterType; /* Since 1.1.27 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_writer_field {
 | 
				
			||||||
 | 
					    const char* name;
 | 
				
			||||||
 | 
					    gsize offset;
 | 
				
			||||||
 | 
					    const GBinderWriterType* type;
 | 
				
			||||||
 | 
					    void (*write_buf)(GBinderWriter* writer, const void* ptr,
 | 
				
			||||||
 | 
					      const struct gbinder_writer_field* field, const GBinderParent* parent);
 | 
				
			||||||
 | 
					    gpointer reserved;
 | 
				
			||||||
 | 
					} GBinderWriterField; /* Since 1.1.27 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define GBINDER_WRITER_STRUCT_NAME_AND_SIZE(type) \
 | 
				
			||||||
 | 
					    #type, sizeof(type)
 | 
				
			||||||
 | 
					#define GBINDER_WRITER_FIELD_NAME_AND_OFFSET(type,field) \
 | 
				
			||||||
 | 
					    #type "." #field, G_STRUCT_OFFSET(type,field)
 | 
				
			||||||
 | 
					#define GBINDER_WRITER_FIELD_POINTER(type,field,field_type) { \
 | 
				
			||||||
 | 
					    GBINDER_WRITER_FIELD_NAME_AND_OFFSET(type,field), field_type, NULL, NULL }
 | 
				
			||||||
 | 
					#define GBINDER_WRITER_FIELD_HIDL_VEC(type,field,elem) { \
 | 
				
			||||||
 | 
					    GBINDER_WRITER_FIELD_NAME_AND_OFFSET(type,field), elem, \
 | 
				
			||||||
 | 
					    gbinder_writer_field_hidl_vec_write_buf, NULL }
 | 
				
			||||||
 | 
					#define GBINDER_WRITER_FIELD_HIDL_VEC_INT32(type,field) \
 | 
				
			||||||
 | 
					    GBINDER_WRITER_FIELD_HIDL_VEC(type,field, &gbinder_writer_type_int32)
 | 
				
			||||||
 | 
					#define GBINDER_WRITER_FIELD_HIDL_VEC_BYTE(type,field) \
 | 
				
			||||||
 | 
					    GBINDER_WRITER_FIELD_HIDL_VEC(type,field, &gbinder_writer_type_byte)
 | 
				
			||||||
 | 
					#define GBINDER_WRITER_FIELD_HIDL_VEC_STRING(type,field) \
 | 
				
			||||||
 | 
					    GBINDER_WRITER_FIELD_HIDL_VEC(type,field, &gbinder_writer_type_hidl_string)
 | 
				
			||||||
 | 
					#define GBINDER_WRITER_FIELD_HIDL_STRING(type,field) { \
 | 
				
			||||||
 | 
					    GBINDER_WRITER_FIELD_NAME_AND_OFFSET(type,field), NULL, \
 | 
				
			||||||
 | 
					    gbinder_writer_field_hidl_string_write_buf, NULL }
 | 
				
			||||||
 | 
					#define GBINDER_WRITER_FIELD_END() { NULL, 0, NULL, NULL, NULL }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern const GBinderWriterType gbinder_writer_type_byte; /* Since 1.1.27 */
 | 
				
			||||||
 | 
					extern const GBinderWriterType gbinder_writer_type_int32; /* Since 1.1.27 */
 | 
				
			||||||
 | 
					extern const GBinderWriterType gbinder_writer_type_hidl_string; /* 1.1.27 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_writer_append_struct(
 | 
				
			||||||
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
 | 
					    const void* ptr,
 | 
				
			||||||
 | 
					    const GBinderWriterType* type,
 | 
				
			||||||
 | 
					    const GBinderParent* parent); /* Since 1.1.27 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_writer_append_struct_vec(
 | 
				
			||||||
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
 | 
					    const void* ptr,
 | 
				
			||||||
 | 
					    guint count,
 | 
				
			||||||
 | 
					    const GBinderWriterType* type); /* Since 1.1.29 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_writer_field_hidl_vec_write_buf(
 | 
				
			||||||
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
 | 
					    const void* ptr,
 | 
				
			||||||
 | 
					    const GBinderWriterField* field,
 | 
				
			||||||
 | 
					    const GBinderParent* parent); /* Since 1.1.27 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_writer_field_hidl_string_write_buf(
 | 
				
			||||||
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
 | 
					    const void* ptr,
 | 
				
			||||||
 | 
					    const GBinderWriterField* field,
 | 
				
			||||||
 | 
					    const GBinderParent* parent); /* Since 1.1.27 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_writer_append_int8(
 | 
				
			||||||
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
 | 
					    guint8 value); /* Since 1.1.15 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_writer_append_int16(
 | 
				
			||||||
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
 | 
					    guint16 value); /* Since 1.1.15 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_writer_append_int32(
 | 
					gbinder_writer_append_int32(
 | 
				
			||||||
    GBinderWriter* writer,
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
@@ -86,6 +199,12 @@ gbinder_writer_append_string16_len(
 | 
				
			|||||||
    const char* utf8,
 | 
					    const char* utf8,
 | 
				
			||||||
    gssize num_bytes);
 | 
					    gssize num_bytes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_writer_append_string16_utf16(
 | 
				
			||||||
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
 | 
					    const gunichar2* utf16,
 | 
				
			||||||
 | 
					    gssize length); /* Since 1.0.17 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_writer_append_string8(
 | 
					gbinder_writer_append_string8(
 | 
				
			||||||
    GBinderWriter* writer,
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
@@ -108,6 +227,17 @@ gbinder_writer_append_bytes(
 | 
				
			|||||||
    const void* data,
 | 
					    const void* data,
 | 
				
			||||||
    gsize size);
 | 
					    gsize size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_writer_append_fd(
 | 
				
			||||||
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
 | 
					    int fd); /* Since 1.0.18 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_writer_append_fds(
 | 
				
			||||||
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
 | 
					    const GBinderFds* fds,
 | 
				
			||||||
 | 
					    const GBinderParent* parent); /* Since 1.1.14 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
guint
 | 
					guint
 | 
				
			||||||
gbinder_writer_append_buffer_object_with_parent(
 | 
					gbinder_writer_append_buffer_object_with_parent(
 | 
				
			||||||
    GBinderWriter* writer,
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
@@ -121,11 +251,29 @@ gbinder_writer_append_buffer_object(
 | 
				
			|||||||
    const void* buf,
 | 
					    const void* buf,
 | 
				
			||||||
    gsize len);
 | 
					    gsize len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_writer_append_parcelable(
 | 
				
			||||||
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
 | 
					    const void* buf,
 | 
				
			||||||
 | 
					    gsize len); /* Since 1.1.19 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_writer_append_hidl_vec(
 | 
				
			||||||
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
 | 
					    const void* base,
 | 
				
			||||||
 | 
					    guint count,
 | 
				
			||||||
 | 
					    guint elemsize); /* Since 1.0.8 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_writer_append_hidl_string(
 | 
					gbinder_writer_append_hidl_string(
 | 
				
			||||||
    GBinderWriter* writer,
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
    const char* str);
 | 
					    const char* str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_writer_append_hidl_string_copy(
 | 
				
			||||||
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
 | 
					    const char* str); /* Since 1.1.13 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_writer_append_hidl_string_vec(
 | 
					gbinder_writer_append_hidl_string_vec(
 | 
				
			||||||
    GBinderWriter* writer,
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
@@ -142,6 +290,67 @@ gbinder_writer_append_remote_object(
 | 
				
			|||||||
    GBinderWriter* writer,
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
    GBinderRemoteObject* obj);
 | 
					    GBinderRemoteObject* obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_writer_append_byte_array(
 | 
				
			||||||
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
 | 
					    const void* byte_array,
 | 
				
			||||||
 | 
					    gint32 len); /* Since 1.0.12 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_writer_append_fmq_descriptor(
 | 
				
			||||||
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
 | 
					    const GBinderFmq* queue); /* since 1.1.14 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const void*
 | 
				
			||||||
 | 
					gbinder_writer_get_data(
 | 
				
			||||||
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
 | 
					    gsize* size); /* Since 1.1.14 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gsize
 | 
				
			||||||
 | 
					gbinder_writer_bytes_written(
 | 
				
			||||||
 | 
					    GBinderWriter* writer); /* Since 1.0.21 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_writer_overwrite_int32(
 | 
				
			||||||
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
 | 
					    gsize offset,
 | 
				
			||||||
 | 
					    gint32 value); /* Since 1.0.21 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Note: memory allocated by GBinderWriter is owned by GBinderWriter */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void*
 | 
				
			||||||
 | 
					gbinder_writer_malloc(
 | 
				
			||||||
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
 | 
					    gsize size); /* Since 1.0.19 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void*
 | 
				
			||||||
 | 
					gbinder_writer_malloc0(
 | 
				
			||||||
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
 | 
					    gsize size); /* Since 1.0.19 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define gbinder_writer_new(writer,type) \
 | 
				
			||||||
 | 
					    ((type*) gbinder_writer_malloc(writer, sizeof(type)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define gbinder_writer_new0(writer,type) \
 | 
				
			||||||
 | 
					    ((type*) gbinder_writer_malloc0(writer, sizeof(type)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_writer_add_cleanup(
 | 
				
			||||||
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
 | 
					    GDestroyNotify destroy,
 | 
				
			||||||
 | 
					    gpointer data); /* Since 1.0.19 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void*
 | 
				
			||||||
 | 
					gbinder_writer_memdup(
 | 
				
			||||||
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
 | 
					    const void* buf,
 | 
				
			||||||
 | 
					    gsize size); /* Since 1.0.19 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char*
 | 
				
			||||||
 | 
					gbinder_writer_strdup(
 | 
				
			||||||
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
 | 
					    const char* str); /* Since 1.1.13 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
G_END_DECLS
 | 
					G_END_DECLS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* GBINDER_WRITER_H */
 | 
					#endif /* GBINDER_WRITER_H */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,10 +1,10 @@
 | 
				
			|||||||
name=gbinder
 | 
					name=gbinder
 | 
				
			||||||
libdir=/usr/lib
 | 
					libdir=@libdir@
 | 
				
			||||||
includedir=/usr/include
 | 
					includedir=/usr/include
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Name: libgbinder
 | 
					Name: libgbinder
 | 
				
			||||||
Description: Binder client library
 | 
					Description: Binder client library
 | 
				
			||||||
Version: [version]
 | 
					Version: @version@
 | 
				
			||||||
Requires: glib-2.0 libglibutil
 | 
					Requires.private: glib-2.0 libglibutil
 | 
				
			||||||
Libs: -L${libdir} -l${name}
 | 
					Libs: -L${libdir} -l${name}
 | 
				
			||||||
Cflags: -I${includedir} -I${includedir}/${name}
 | 
					Cflags: -I${includedir} -I${includedir}/${name}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										8
									
								
								misc/coverity_model.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								misc/coverity_model.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					typedef struct gbinder_remote_request GBinderRemoteRequest;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_remote_request_unref(
 | 
				
			||||||
 | 
					    GBinderRemoteRequest* req)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    __coverity_free__(req);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,14 +1,30 @@
 | 
				
			|||||||
Name: libgbinder
 | 
					Name: libgbinder
 | 
				
			||||||
Version: 1.0.5
 | 
					
 | 
				
			||||||
 | 
					Version: 1.1.40
 | 
				
			||||||
Release: 0
 | 
					Release: 0
 | 
				
			||||||
Summary: Binder client library
 | 
					Summary: Binder client library
 | 
				
			||||||
Group: Development/Libraries
 | 
					 | 
				
			||||||
License: BSD
 | 
					License: BSD
 | 
				
			||||||
URL: https://github.com/mer-hybris/libgbinder
 | 
					URL: https://github.com/mer-hybris/libgbinder
 | 
				
			||||||
Source: %{name}-%{version}.tar.bz2
 | 
					Source: %{name}-%{version}.tar.bz2
 | 
				
			||||||
Requires: libglibutil >= 1.0.29
 | 
					
 | 
				
			||||||
BuildRequires: pkgconfig(glib-2.0)
 | 
					%define glib_version 2.32
 | 
				
			||||||
BuildRequires: pkgconfig(libglibutil) >= 1.0.29
 | 
					%define libglibutil_version 1.0.52
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BuildRequires: pkgconfig(glib-2.0) >= %{glib_version}
 | 
				
			||||||
 | 
					BuildRequires: pkgconfig(libglibutil) >= %{libglibutil_version}
 | 
				
			||||||
 | 
					BuildRequires: pkgconfig
 | 
				
			||||||
 | 
					BuildRequires: bison
 | 
				
			||||||
 | 
					BuildRequires: flex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# license macro requires rpm >= 4.11
 | 
				
			||||||
 | 
					BuildRequires: pkgconfig(rpm)
 | 
				
			||||||
 | 
					%define license_support %(pkg-config --exists 'rpm >= 4.11'; echo $?)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# make_build macro appeared in rpm 4.12
 | 
				
			||||||
 | 
					%{!?make_build:%define make_build make %{_smp_mflags}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Requires: glib2 >= %{glib_version}
 | 
				
			||||||
 | 
					Requires: libglibutil >= %{libglibutil_version}
 | 
				
			||||||
Requires(post): /sbin/ldconfig
 | 
					Requires(post): /sbin/ldconfig
 | 
				
			||||||
Requires(postun): /sbin/ldconfig
 | 
					Requires(postun): /sbin/ldconfig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -18,7 +34,7 @@ C interfaces for Android binder
 | 
				
			|||||||
%package devel
 | 
					%package devel
 | 
				
			||||||
Summary: Development library for %{name}
 | 
					Summary: Development library for %{name}
 | 
				
			||||||
Requires: %{name} = %{version}
 | 
					Requires: %{name} = %{version}
 | 
				
			||||||
Requires: pkgconfig
 | 
					Requires: pkgconfig(glib-2.0) >= %{glib_version}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
%description devel
 | 
					%description devel
 | 
				
			||||||
This package contains the development library for %{name}.
 | 
					This package contains the development library for %{name}.
 | 
				
			||||||
@@ -27,11 +43,18 @@ This package contains the development library for %{name}.
 | 
				
			|||||||
%setup -q
 | 
					%setup -q
 | 
				
			||||||
 | 
					
 | 
				
			||||||
%build
 | 
					%build
 | 
				
			||||||
make KEEP_SYMBOLS=1 release pkgconfig
 | 
					%make_build LIBDIR=%{_libdir} KEEP_SYMBOLS=1 release pkgconfig
 | 
				
			||||||
 | 
					%make_build -C test/binder-bridge -j1 KEEP_SYMBOLS=1 release
 | 
				
			||||||
 | 
					%make_build -C test/binder-list -j1 KEEP_SYMBOLS=1 release
 | 
				
			||||||
 | 
					%make_build -C test/binder-ping -j1 KEEP_SYMBOLS=1 release
 | 
				
			||||||
 | 
					%make_build -C test/binder-call -j1 KEEP_SYMBOLS=1 release
 | 
				
			||||||
 | 
					
 | 
				
			||||||
%install
 | 
					%install
 | 
				
			||||||
rm -rf %{buildroot}
 | 
					make LIBDIR=%{_libdir} DESTDIR=%{buildroot} install-dev
 | 
				
			||||||
make install-dev DESTDIR=%{buildroot}
 | 
					make -C test/binder-bridge DESTDIR=%{buildroot} install
 | 
				
			||||||
 | 
					make -C test/binder-list DESTDIR=%{buildroot} install
 | 
				
			||||||
 | 
					make -C test/binder-ping DESTDIR=%{buildroot} install
 | 
				
			||||||
 | 
					make -C test/binder-call DESTDIR=%{buildroot} install
 | 
				
			||||||
 | 
					
 | 
				
			||||||
%check
 | 
					%check
 | 
				
			||||||
make -C unit test
 | 
					make -C unit test
 | 
				
			||||||
@@ -43,9 +66,29 @@ make -C unit test
 | 
				
			|||||||
%files
 | 
					%files
 | 
				
			||||||
%defattr(-,root,root,-)
 | 
					%defattr(-,root,root,-)
 | 
				
			||||||
%{_libdir}/%{name}.so.*
 | 
					%{_libdir}/%{name}.so.*
 | 
				
			||||||
 | 
					%if %{license_support} == 0
 | 
				
			||||||
 | 
					%license LICENSE
 | 
				
			||||||
 | 
					%endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
%files devel
 | 
					%files devel
 | 
				
			||||||
%defattr(-,root,root,-)
 | 
					%defattr(-,root,root,-)
 | 
				
			||||||
 | 
					%dir %{_includedir}/gbinder
 | 
				
			||||||
%{_libdir}/pkgconfig/*.pc
 | 
					%{_libdir}/pkgconfig/*.pc
 | 
				
			||||||
%{_libdir}/%{name}.so
 | 
					%{_libdir}/%{name}.so
 | 
				
			||||||
%{_includedir}/gbinder/*.h
 | 
					%{_includedir}/gbinder/*.h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Tools
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%package tools
 | 
				
			||||||
 | 
					Summary: Binder tools
 | 
				
			||||||
 | 
					Requires: %{name} >= %{version}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%description tools
 | 
				
			||||||
 | 
					Binder command line utilities
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%files tools
 | 
				
			||||||
 | 
					%defattr(-,root,root,-)
 | 
				
			||||||
 | 
					%{_bindir}/binder-bridge
 | 
				
			||||||
 | 
					%{_bindir}/binder-list
 | 
				
			||||||
 | 
					%{_bindir}/binder-ping
 | 
				
			||||||
 | 
					%{_bindir}/binder-call
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										272
									
								
								src/gbinder_bridge.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										272
									
								
								src/gbinder_bridge.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,272 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2021 Jolla Ltd.
 | 
				
			||||||
 | 
					 * Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   1. Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 | 
					 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
				
			||||||
 | 
					 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
				
			||||||
 | 
					 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
				
			||||||
 | 
					 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
				
			||||||
 | 
					 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
				
			||||||
 | 
					 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
				
			||||||
 | 
					 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
				
			||||||
 | 
					 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
				
			||||||
 | 
					 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "gbinder_local_request.h"
 | 
				
			||||||
 | 
					#include "gbinder_local_reply.h"
 | 
				
			||||||
 | 
					#include "gbinder_proxy_object.h"
 | 
				
			||||||
 | 
					#include "gbinder_remote_request_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_remote_reply.h"
 | 
				
			||||||
 | 
					#include "gbinder_remote_object_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_servicename.h"
 | 
				
			||||||
 | 
					#include "gbinder_servicemanager_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_client_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_bridge.h"
 | 
				
			||||||
 | 
					#include "gbinder_ipc.h"
 | 
				
			||||||
 | 
					#include "gbinder_log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gutil_strv.h>
 | 
				
			||||||
 | 
					#include <gutil_macros.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_bridge_interface {
 | 
				
			||||||
 | 
					    GBinderBridge* bridge;
 | 
				
			||||||
 | 
					    char* iface;
 | 
				
			||||||
 | 
					    char* fqname;
 | 
				
			||||||
 | 
					    char* src_name;
 | 
				
			||||||
 | 
					    char* dest_name;
 | 
				
			||||||
 | 
					    gulong dest_watch_id;
 | 
				
			||||||
 | 
					    gulong dest_death_id;
 | 
				
			||||||
 | 
					    GBinderRemoteObject* dest_obj;
 | 
				
			||||||
 | 
					    GBinderServiceName* src_service;
 | 
				
			||||||
 | 
					    GBinderProxyObject* proxy;
 | 
				
			||||||
 | 
					} GBinderBridgeInterface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gbinder_bridge {
 | 
				
			||||||
 | 
					    GBinderBridgeInterface** ifaces;
 | 
				
			||||||
 | 
					    GBinderServiceManager* src;
 | 
				
			||||||
 | 
					    GBinderServiceManager* dest;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*==========================================================================*
 | 
				
			||||||
 | 
					 * Implementation
 | 
				
			||||||
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_bridge_dest_drop_remote_object(
 | 
				
			||||||
 | 
					    GBinderBridgeInterface* bi)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (bi->dest_obj) {
 | 
				
			||||||
 | 
					        GDEBUG("Detached from %s", bi->fqname);
 | 
				
			||||||
 | 
					        gbinder_remote_object_remove_handler(bi->dest_obj, bi->dest_death_id);
 | 
				
			||||||
 | 
					        gbinder_remote_object_unref(bi->dest_obj);
 | 
				
			||||||
 | 
					        bi->dest_death_id = 0;
 | 
				
			||||||
 | 
					        bi->dest_obj = NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_bridge_interface_deactivate(
 | 
				
			||||||
 | 
					    GBinderBridgeInterface* bi)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    gbinder_bridge_dest_drop_remote_object(bi);
 | 
				
			||||||
 | 
					    if (bi->proxy) {
 | 
				
			||||||
 | 
					        gbinder_local_object_drop(GBINDER_LOCAL_OBJECT(bi->proxy));
 | 
				
			||||||
 | 
					        bi->proxy = NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (bi->src_service) {
 | 
				
			||||||
 | 
					        gbinder_servicename_unref(bi->src_service);
 | 
				
			||||||
 | 
					        bi->src_service = NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_bridge_interface_free(
 | 
				
			||||||
 | 
					    GBinderBridgeInterface* bi)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderBridge* bridge = bi->bridge;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gbinder_bridge_interface_deactivate(bi);
 | 
				
			||||||
 | 
					    gbinder_servicemanager_remove_handler(bridge->dest, bi->dest_watch_id);
 | 
				
			||||||
 | 
					    g_free(bi->iface);
 | 
				
			||||||
 | 
					    g_free(bi->fqname);
 | 
				
			||||||
 | 
					    g_free(bi->src_name);
 | 
				
			||||||
 | 
					    g_free(bi->dest_name);
 | 
				
			||||||
 | 
					    gutil_slice_free(bi);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_bridge_dest_death_proc(
 | 
				
			||||||
 | 
					    GBinderRemoteObject* obj,
 | 
				
			||||||
 | 
					    void* user_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderBridgeInterface* bi = user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    GDEBUG("%s has died", bi->fqname);
 | 
				
			||||||
 | 
					    gbinder_bridge_interface_deactivate(bi);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_bridge_interface_activate(
 | 
				
			||||||
 | 
					    GBinderBridgeInterface* bi)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderBridge* bridge = bi->bridge;
 | 
				
			||||||
 | 
					    GBinderServiceManager* src = bridge->src;
 | 
				
			||||||
 | 
					    GBinderServiceManager* dest = bridge->dest;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (bi->dest_obj && bi->dest_obj->dead) {
 | 
				
			||||||
 | 
					        gbinder_bridge_dest_drop_remote_object(bi);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (!bi->dest_obj) {
 | 
				
			||||||
 | 
					        bi->dest_obj = gbinder_servicemanager_get_service_sync(dest,
 | 
				
			||||||
 | 
					            bi->fqname, NULL);
 | 
				
			||||||
 | 
					        if (bi->dest_obj) {
 | 
				
			||||||
 | 
					            GDEBUG("Attached to %s", bi->fqname);
 | 
				
			||||||
 | 
					            gbinder_remote_object_ref(bi->dest_obj);
 | 
				
			||||||
 | 
					            bi->dest_death_id = gbinder_remote_object_add_death_handler
 | 
				
			||||||
 | 
					                (bi->dest_obj, gbinder_bridge_dest_death_proc, bi);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (bi->dest_obj && !bi->proxy) {
 | 
				
			||||||
 | 
					        bi->proxy = gbinder_proxy_object_new(gbinder_servicemanager_ipc(src),
 | 
				
			||||||
 | 
					            bi->dest_obj);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (bi->proxy && !bi->src_service) {
 | 
				
			||||||
 | 
					        bi->src_service = gbinder_servicename_new(src,
 | 
				
			||||||
 | 
					            GBINDER_LOCAL_OBJECT(bi->proxy), bi->src_name);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_bridge_dest_registration_proc(
 | 
				
			||||||
 | 
					    GBinderServiceManager* sm,
 | 
				
			||||||
 | 
					    const char* name,
 | 
				
			||||||
 | 
					    void* user_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderBridgeInterface* bi = user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!g_strcmp0(name, bi->fqname)) {
 | 
				
			||||||
 | 
					        GDEBUG("%s has been registered", bi->fqname);
 | 
				
			||||||
 | 
					        gbinder_bridge_interface_activate(bi);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					GBinderBridgeInterface*
 | 
				
			||||||
 | 
					gbinder_bridge_interface_new(
 | 
				
			||||||
 | 
					    GBinderBridge* self,
 | 
				
			||||||
 | 
					    const char* src_name,
 | 
				
			||||||
 | 
					    const char* dest_name,
 | 
				
			||||||
 | 
					    const char* iface)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderBridgeInterface* bi = g_slice_new0(GBinderBridgeInterface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bi->bridge = self;
 | 
				
			||||||
 | 
					    bi->iface = g_strdup(iface);
 | 
				
			||||||
 | 
					    bi->fqname = g_strconcat(iface, "/", dest_name, NULL);
 | 
				
			||||||
 | 
					    bi->src_name = g_strdup(src_name);
 | 
				
			||||||
 | 
					    bi->dest_name = g_strdup(dest_name);
 | 
				
			||||||
 | 
					    bi->dest_watch_id = gbinder_servicemanager_add_registration_handler
 | 
				
			||||||
 | 
					        (self->dest, bi->fqname, gbinder_bridge_dest_registration_proc, bi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Try to activate at startup */
 | 
				
			||||||
 | 
					    gbinder_bridge_interface_activate(bi);
 | 
				
			||||||
 | 
					    return bi;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*==========================================================================*
 | 
				
			||||||
 | 
					 * Interface
 | 
				
			||||||
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderBridge*
 | 
				
			||||||
 | 
					gbinder_bridge_new(
 | 
				
			||||||
 | 
					    const char* name,
 | 
				
			||||||
 | 
					    const char* const* ifaces,
 | 
				
			||||||
 | 
					    GBinderServiceManager* src,
 | 
				
			||||||
 | 
					    GBinderServiceManager* dest) /* Since 1.1.5 */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return gbinder_bridge_new2(name, NULL, ifaces, src, dest);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderBridge*
 | 
				
			||||||
 | 
					gbinder_bridge_new2(
 | 
				
			||||||
 | 
					    const char* src_name,
 | 
				
			||||||
 | 
					    const char* dest_name,
 | 
				
			||||||
 | 
					    const char* const* ifaces,
 | 
				
			||||||
 | 
					    GBinderServiceManager* src,
 | 
				
			||||||
 | 
					    GBinderServiceManager* dest) /* Since 1.1.6 */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const guint n = gutil_strv_length((const GStrV*)ifaces);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!src_name) {
 | 
				
			||||||
 | 
					        src_name = dest_name;
 | 
				
			||||||
 | 
					    } else if (!dest_name) {
 | 
				
			||||||
 | 
					        dest_name = src_name;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (G_LIKELY(src_name) && G_LIKELY(n) && G_LIKELY(src) && G_LIKELY(dest)) {
 | 
				
			||||||
 | 
					        GBinderBridge* self = g_slice_new0(GBinderBridge);
 | 
				
			||||||
 | 
					        guint i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self->src = gbinder_servicemanager_ref(src);
 | 
				
			||||||
 | 
					        self->dest = gbinder_servicemanager_ref(dest);
 | 
				
			||||||
 | 
					        self->ifaces = g_new(GBinderBridgeInterface*, n + 1);
 | 
				
			||||||
 | 
					        for (i = 0; i < n; i++) {
 | 
				
			||||||
 | 
					            self->ifaces[i] = gbinder_bridge_interface_new(self,
 | 
				
			||||||
 | 
					                src_name, dest_name, ifaces[i]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        self->ifaces[i] = NULL;
 | 
				
			||||||
 | 
					        return self;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_bridge_free(
 | 
				
			||||||
 | 
					    GBinderBridge* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
 | 
					        GBinderBridgeInterface** bi = self->ifaces;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        while (*bi) {
 | 
				
			||||||
 | 
					            gbinder_bridge_interface_free(*bi);
 | 
				
			||||||
 | 
					            bi++;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        gbinder_servicemanager_unref(self->src);
 | 
				
			||||||
 | 
					        gbinder_servicemanager_unref(self->dest);
 | 
				
			||||||
 | 
					        g_free(self->ifaces);
 | 
				
			||||||
 | 
					        gutil_slice_free(self);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Local Variables:
 | 
				
			||||||
 | 
					 * mode: C
 | 
				
			||||||
 | 
					 * c-basic-offset: 4
 | 
				
			||||||
 | 
					 * indent-tabs-mode: nil
 | 
				
			||||||
 | 
					 * End:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -36,55 +36,62 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <gutil_macros.h>
 | 
					#include <gutil_macros.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct gbinder_buffer_memory {
 | 
					struct gbinder_buffer_contents {
 | 
				
			||||||
    gint refcount;
 | 
					    gint refcount;
 | 
				
			||||||
    void* buffer;
 | 
					    void* buffer;
 | 
				
			||||||
    gsize size;
 | 
					    gsize size;
 | 
				
			||||||
 | 
					    void** objects;
 | 
				
			||||||
    GBinderDriver* driver;
 | 
					    GBinderDriver* driver;
 | 
				
			||||||
} GBinderBufferMemory;
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct gbinder_buffer_priv {
 | 
					typedef struct gbinder_buffer_priv {
 | 
				
			||||||
    GBinderBuffer pub;
 | 
					    GBinderBuffer pub;
 | 
				
			||||||
    GBinderBufferMemory* memory;
 | 
					    GBinderBufferContents* contents;
 | 
				
			||||||
} GBinderBufferPriv;
 | 
					} GBinderBufferPriv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline GBinderBufferPriv* gbinder_buffer_cast(GBinderBuffer* buf)
 | 
					static inline GBinderBufferPriv* gbinder_buffer_cast(GBinderBuffer* buf)
 | 
				
			||||||
    { return G_CAST(buf, GBinderBufferPriv, pub); }
 | 
					    { return G_CAST(buf, GBinderBufferPriv, pub); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*==========================================================================*
 | 
					/*==========================================================================*
 | 
				
			||||||
 * GBinderBufferMemory
 | 
					 * GBinderBufferContents
 | 
				
			||||||
 *==========================================================================*/
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
GBinderBufferMemory*
 | 
					GBinderBufferContents*
 | 
				
			||||||
gbinder_buffer_memory_new(
 | 
					gbinder_buffer_contents_new(
 | 
				
			||||||
    GBinderDriver* driver,
 | 
					    GBinderDriver* driver,
 | 
				
			||||||
    void* buffer,
 | 
					    void* buffer,
 | 
				
			||||||
    gsize size)
 | 
					    gsize size,
 | 
				
			||||||
 | 
					    void** objects)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GBinderBufferMemory* self = g_slice_new0(GBinderBufferMemory);
 | 
					    GBinderBufferContents* self = g_slice_new0(GBinderBufferContents);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    g_atomic_int_set(&self->refcount, 1);
 | 
					    g_atomic_int_set(&self->refcount, 1);
 | 
				
			||||||
    self->buffer = buffer;
 | 
					    self->buffer = buffer;
 | 
				
			||||||
    self->size = size;
 | 
					    self->size = size;
 | 
				
			||||||
 | 
					    self->objects = objects;
 | 
				
			||||||
    self->driver = gbinder_driver_ref(driver);
 | 
					    self->driver = gbinder_driver_ref(driver);
 | 
				
			||||||
    return self;
 | 
					    return self;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_buffer_memory_free(
 | 
					gbinder_buffer_contents_free(
 | 
				
			||||||
    GBinderBufferMemory* self)
 | 
					    GBinderBufferContents* self)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    if (self->objects) {
 | 
				
			||||||
 | 
					        gbinder_driver_close_fds(self->driver, self->objects,
 | 
				
			||||||
 | 
					            ((guint8*)self->buffer) + self->size);
 | 
				
			||||||
 | 
					        g_free(self->objects);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    gbinder_driver_free_buffer(self->driver, self->buffer);
 | 
					    gbinder_driver_free_buffer(self->driver, self->buffer);
 | 
				
			||||||
    gbinder_driver_unref(self->driver);
 | 
					    gbinder_driver_unref(self->driver);
 | 
				
			||||||
    g_slice_free(GBinderBufferMemory, self);
 | 
					    g_slice_free(GBinderBufferContents, self);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					GBinderBufferContents*
 | 
				
			||||||
GBinderBufferMemory*
 | 
					gbinder_buffer_contents_ref(
 | 
				
			||||||
gbinder_buffer_memory_ref(
 | 
					    GBinderBufferContents* self)
 | 
				
			||||||
    GBinderBufferMemory* self)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (G_LIKELY(self)) {
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
        GASSERT(self->refcount > 0);
 | 
					        GASSERT(self->refcount > 0);
 | 
				
			||||||
@@ -93,19 +100,59 @@ gbinder_buffer_memory_ref(
 | 
				
			|||||||
    return self;
 | 
					    return self;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_buffer_memory_unref(
 | 
					gbinder_buffer_contents_unref(
 | 
				
			||||||
    GBinderBufferMemory* self)
 | 
					    GBinderBufferContents* self)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (G_LIKELY(self)) {
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
        GASSERT(self->refcount > 0);
 | 
					        GASSERT(self->refcount > 0);
 | 
				
			||||||
        if (g_atomic_int_dec_and_test(&self->refcount)) {
 | 
					        if (g_atomic_int_dec_and_test(&self->refcount)) {
 | 
				
			||||||
            gbinder_buffer_memory_free(self);
 | 
					            gbinder_buffer_contents_free(self);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*==========================================================================*
 | 
				
			||||||
 | 
					 * GBinderBufferContentsList
 | 
				
			||||||
 | 
					 * It's actually a GSList containing GBinderBufferContents refs.
 | 
				
			||||||
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderBufferContentsList*
 | 
				
			||||||
 | 
					gbinder_buffer_contents_list_add(
 | 
				
			||||||
 | 
					    GBinderBufferContentsList* list,
 | 
				
			||||||
 | 
					    GBinderBufferContents* contents)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /* Prepend rather than append for better efficiency */
 | 
				
			||||||
 | 
					    return contents ? (GBinderBufferContentsList*) g_slist_prepend((GSList*)
 | 
				
			||||||
 | 
					            list, gbinder_buffer_contents_ref(contents)) : list;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderBufferContentsList*
 | 
				
			||||||
 | 
					gbinder_buffer_contents_list_dup(
 | 
				
			||||||
 | 
					    GBinderBufferContentsList* list)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GSList* out = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (list) {
 | 
				
			||||||
 | 
					        GSList* l = (GSList*) list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* The order gets reversed but it doesn't matter */
 | 
				
			||||||
 | 
					        while (l) {
 | 
				
			||||||
 | 
					            out = g_slist_prepend(out, gbinder_buffer_contents_ref(l->data));
 | 
				
			||||||
 | 
					            l = l->next;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return (GBinderBufferContentsList*) out;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_buffer_contents_list_free(
 | 
				
			||||||
 | 
					    GBinderBufferContentsList* list)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    g_slist_free_full((GSList*) list, (GDestroyNotify)
 | 
				
			||||||
 | 
					        gbinder_buffer_contents_unref);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*==========================================================================*
 | 
					/*==========================================================================*
 | 
				
			||||||
 * GBinderBuffer
 | 
					 * GBinderBuffer
 | 
				
			||||||
 *==========================================================================*/
 | 
					 *==========================================================================*/
 | 
				
			||||||
@@ -113,14 +160,14 @@ gbinder_buffer_memory_unref(
 | 
				
			|||||||
static
 | 
					static
 | 
				
			||||||
GBinderBuffer*
 | 
					GBinderBuffer*
 | 
				
			||||||
gbinder_buffer_alloc(
 | 
					gbinder_buffer_alloc(
 | 
				
			||||||
    GBinderBufferMemory* memory,
 | 
					    GBinderBufferContents* contents,
 | 
				
			||||||
    void* data,
 | 
					    void* data,
 | 
				
			||||||
    gsize size)
 | 
					    gsize size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GBinderBufferPriv* priv = g_slice_new0(GBinderBufferPriv);
 | 
					    GBinderBufferPriv* priv = g_slice_new0(GBinderBufferPriv);
 | 
				
			||||||
    GBinderBuffer* self = &priv->pub;
 | 
					    GBinderBuffer* self = &priv->pub;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    priv->memory = memory;
 | 
					    priv->contents = contents;
 | 
				
			||||||
    self->data = data;
 | 
					    self->data = data;
 | 
				
			||||||
    self->size = size;
 | 
					    self->size = size;
 | 
				
			||||||
    return self;
 | 
					    return self;
 | 
				
			||||||
@@ -133,7 +180,7 @@ gbinder_buffer_free(
 | 
				
			|||||||
    if (G_LIKELY(self)) {
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
        GBinderBufferPriv* priv = gbinder_buffer_cast(self);
 | 
					        GBinderBufferPriv* priv = gbinder_buffer_cast(self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gbinder_buffer_memory_unref(priv->memory);
 | 
					        gbinder_buffer_contents_unref(priv->contents);
 | 
				
			||||||
        g_slice_free(GBinderBufferPriv, priv);
 | 
					        g_slice_free(GBinderBufferPriv, priv);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -142,10 +189,12 @@ GBinderBuffer*
 | 
				
			|||||||
gbinder_buffer_new(
 | 
					gbinder_buffer_new(
 | 
				
			||||||
    GBinderDriver* driver,
 | 
					    GBinderDriver* driver,
 | 
				
			||||||
    void* data,
 | 
					    void* data,
 | 
				
			||||||
    gsize size)
 | 
					    gsize size,
 | 
				
			||||||
 | 
					    void** objects)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return gbinder_buffer_alloc((driver && data) ?
 | 
					    return gbinder_buffer_alloc((driver && data) ?
 | 
				
			||||||
        gbinder_buffer_memory_new(driver, data, size) : NULL, data, size);
 | 
					        gbinder_buffer_contents_new(driver, data, size, objects) : NULL,
 | 
				
			||||||
 | 
					        data, size);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderBuffer*
 | 
					GBinderBuffer*
 | 
				
			||||||
@@ -155,10 +204,30 @@ gbinder_buffer_new_with_parent(
 | 
				
			|||||||
    gsize size)
 | 
					    gsize size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return gbinder_buffer_alloc(parent ?
 | 
					    return gbinder_buffer_alloc(parent ?
 | 
				
			||||||
        gbinder_buffer_memory_ref(gbinder_buffer_cast(parent)->memory) : NULL,
 | 
					        gbinder_buffer_contents_ref(gbinder_buffer_contents(parent)) : NULL,
 | 
				
			||||||
        data, size);
 | 
					        data, size);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gconstpointer
 | 
				
			||||||
 | 
					gbinder_buffer_data(
 | 
				
			||||||
 | 
					    GBinderBuffer* self,
 | 
				
			||||||
 | 
					    gsize* size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderBufferContents* contents = gbinder_buffer_contents(self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (G_LIKELY(contents)) {
 | 
				
			||||||
 | 
					        if (size) {
 | 
				
			||||||
 | 
					            *size = contents->size;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return contents->buffer;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        if (size) {
 | 
				
			||||||
 | 
					            *size = 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderDriver*
 | 
					GBinderDriver*
 | 
				
			||||||
gbinder_buffer_driver(
 | 
					gbinder_buffer_driver(
 | 
				
			||||||
    GBinderBuffer* self)
 | 
					    GBinderBuffer* self)
 | 
				
			||||||
@@ -166,13 +235,52 @@ gbinder_buffer_driver(
 | 
				
			|||||||
    if (G_LIKELY(self)) {
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
        GBinderBufferPriv* priv = gbinder_buffer_cast(self);
 | 
					        GBinderBufferPriv* priv = gbinder_buffer_cast(self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (priv->memory) {
 | 
					        if (priv->contents) {
 | 
				
			||||||
            return priv->memory->driver;
 | 
					            return priv->contents->driver;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const GBinderIo*
 | 
				
			||||||
 | 
					gbinder_buffer_io(
 | 
				
			||||||
 | 
					    GBinderBuffer* buf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderDriver* driver = gbinder_buffer_driver(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return driver ? gbinder_driver_io(driver) : NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const GBinderRpcProtocol*
 | 
				
			||||||
 | 
					gbinder_buffer_protocol(
 | 
				
			||||||
 | 
					    GBinderBuffer* buf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderDriver* driver = gbinder_buffer_driver(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return driver ? gbinder_driver_protocol(driver) : NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void**
 | 
				
			||||||
 | 
					gbinder_buffer_objects(
 | 
				
			||||||
 | 
					    GBinderBuffer* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
 | 
					        GBinderBufferPriv* priv = gbinder_buffer_cast(self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (priv->contents) {
 | 
				
			||||||
 | 
					            return priv->contents->objects;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderBufferContents*
 | 
				
			||||||
 | 
					gbinder_buffer_contents(
 | 
				
			||||||
 | 
					    GBinderBuffer* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return G_LIKELY(self) ? gbinder_buffer_cast(self)->contents : NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Local Variables:
 | 
					 * Local Variables:
 | 
				
			||||||
 * mode: C
 | 
					 * mode: C
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -41,20 +41,73 @@ GBinderBuffer*
 | 
				
			|||||||
gbinder_buffer_new(
 | 
					gbinder_buffer_new(
 | 
				
			||||||
    GBinderDriver* driver,
 | 
					    GBinderDriver* driver,
 | 
				
			||||||
    void* data,
 | 
					    void* data,
 | 
				
			||||||
    gsize size);
 | 
					    gsize size,
 | 
				
			||||||
 | 
					    void** objects)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderBuffer*
 | 
					GBinderBuffer*
 | 
				
			||||||
gbinder_buffer_new_with_parent(
 | 
					gbinder_buffer_new_with_parent(
 | 
				
			||||||
    GBinderBuffer* parent,
 | 
					    GBinderBuffer* parent,
 | 
				
			||||||
    void* data,
 | 
					    void* data,
 | 
				
			||||||
    gsize size);
 | 
					    gsize size)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderDriver*
 | 
					GBinderDriver*
 | 
				
			||||||
gbinder_buffer_driver(
 | 
					gbinder_buffer_driver(
 | 
				
			||||||
    GBinderBuffer* buf);
 | 
					    GBinderBuffer* buf)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define gbinder_buffer_io(buf) \
 | 
					GBinderBufferContents*
 | 
				
			||||||
    gbinder_driver_io(gbinder_buffer_driver(buf))
 | 
					gbinder_buffer_contents(
 | 
				
			||||||
 | 
					    GBinderBuffer* buf)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gconstpointer
 | 
				
			||||||
 | 
					gbinder_buffer_data(
 | 
				
			||||||
 | 
					    GBinderBuffer* buf,
 | 
				
			||||||
 | 
					    gsize* size)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const GBinderIo*
 | 
				
			||||||
 | 
					gbinder_buffer_io(
 | 
				
			||||||
 | 
					    GBinderBuffer* buf)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const GBinderRpcProtocol*
 | 
				
			||||||
 | 
					gbinder_buffer_protocol(
 | 
				
			||||||
 | 
					    GBinderBuffer* buf)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void**
 | 
				
			||||||
 | 
					gbinder_buffer_objects(
 | 
				
			||||||
 | 
					    GBinderBuffer* buffer)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderBufferContents*
 | 
				
			||||||
 | 
					gbinder_buffer_contents_ref(
 | 
				
			||||||
 | 
					    GBinderBufferContents* contents)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_buffer_contents_unref(
 | 
				
			||||||
 | 
					    GBinderBufferContents* contents)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderBufferContentsList*
 | 
				
			||||||
 | 
					gbinder_buffer_contents_list_add(
 | 
				
			||||||
 | 
					    GBinderBufferContentsList* list,
 | 
				
			||||||
 | 
					    GBinderBufferContents* contents)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderBufferContentsList*
 | 
				
			||||||
 | 
					gbinder_buffer_contents_list_dup(
 | 
				
			||||||
 | 
					    GBinderBufferContentsList* list)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_buffer_contents_list_free(
 | 
				
			||||||
 | 
					    GBinderBufferContentsList* list)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* GBINDER_BUFFER_PRIVATE_H */
 | 
					#endif /* GBINDER_BUFFER_PRIVATE_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -48,11 +48,33 @@ struct gbinder_cleanup {
 | 
				
			|||||||
G_STATIC_ASSERT(sizeof(GBinderCleanup) == sizeof(GArray));
 | 
					G_STATIC_ASSERT(sizeof(GBinderCleanup) == sizeof(GArray));
 | 
				
			||||||
#define ELEMENT_SIZE (sizeof(GBinderCleanupItem))
 | 
					#define ELEMENT_SIZE (sizeof(GBinderCleanupItem))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_cleanup_destroy_func(
 | 
				
			||||||
 | 
					    gpointer data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderCleanupItem* item = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    item->destroy(item->pointer);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
GBinderCleanup*
 | 
					GBinderCleanup*
 | 
				
			||||||
gbinder_cleanup_new()
 | 
					gbinder_cleanup_new()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return (GBinderCleanup*)g_array_sized_new(FALSE, FALSE, ELEMENT_SIZE, 0);
 | 
					    GArray* array = g_array_sized_new(FALSE, FALSE, ELEMENT_SIZE, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_array_set_clear_func(array, gbinder_cleanup_destroy_func);
 | 
				
			||||||
 | 
					    return (GBinderCleanup*)array;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_cleanup_reset(
 | 
				
			||||||
 | 
					    GBinderCleanup* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
 | 
					        g_array_set_size((GArray*)self, 0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
@@ -60,11 +82,6 @@ gbinder_cleanup_free(
 | 
				
			|||||||
    GBinderCleanup* self)
 | 
					    GBinderCleanup* self)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (G_LIKELY(self)) {
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
        guint i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (i = 0; i < self->count; i++) {
 | 
					 | 
				
			||||||
            self->items[i].destroy(self->items[i].pointer);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        g_array_free((GArray*)self, TRUE);
 | 
					        g_array_free((GArray*)self, TRUE);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2020 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -37,13 +37,20 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_cleanup_free(
 | 
					gbinder_cleanup_free(
 | 
				
			||||||
    GBinderCleanup* cleanup);
 | 
					    GBinderCleanup* cleanup)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_cleanup_reset(
 | 
				
			||||||
 | 
					    GBinderCleanup* cleanup)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderCleanup*
 | 
					GBinderCleanup*
 | 
				
			||||||
gbinder_cleanup_add(
 | 
					gbinder_cleanup_add(
 | 
				
			||||||
    GBinderCleanup* cleanup,
 | 
					    GBinderCleanup* cleanup,
 | 
				
			||||||
    GDestroyNotify destroy,
 | 
					    GDestroyNotify destroy,
 | 
				
			||||||
    gpointer pointer);
 | 
					    gpointer pointer)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* GBINDER_CLEANUP_H */
 | 
					#endif /* GBINDER_CLEANUP_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -41,14 +41,22 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <gutil_macros.h>
 | 
					#include <gutil_macros.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <errno.h>
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					#include <limits.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_client_iface_range {
 | 
				
			||||||
 | 
					    char* iface;
 | 
				
			||||||
 | 
					    GBytes* rpc_header;
 | 
				
			||||||
 | 
					    GBinderLocalRequest* basic_req;
 | 
				
			||||||
 | 
					    guint32 last_code;
 | 
				
			||||||
 | 
					} GBinderClientIfaceRange;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct gbinder_client_priv {
 | 
					typedef struct gbinder_client_priv {
 | 
				
			||||||
    GBinderClient pub;
 | 
					    GBinderClient pub;
 | 
				
			||||||
    guint32 refcount;
 | 
					    guint32 refcount;
 | 
				
			||||||
    char* iface;
 | 
					    GBinderClientIfaceRange* ranges;
 | 
				
			||||||
    GBytes* rpc_header;
 | 
					    guint nr;
 | 
				
			||||||
    GBinderLocalRequest* basic_req;
 | 
					 | 
				
			||||||
} GBinderClientPriv;
 | 
					} GBinderClientPriv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct gbinder_client_tx {
 | 
					typedef struct gbinder_client_tx {
 | 
				
			||||||
@@ -65,17 +73,79 @@ static inline GBinderClientPriv* gbinder_client_cast(GBinderClient* client)
 | 
				
			|||||||
 * Implementation
 | 
					 * Implementation
 | 
				
			||||||
 *==========================================================================*/
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					const GBinderClientIfaceRange*
 | 
				
			||||||
 | 
					gbinder_client_find_range(
 | 
				
			||||||
 | 
					    GBinderClientPriv* priv,
 | 
				
			||||||
 | 
					    guint32 code)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    guint i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < priv->nr; i++) {
 | 
				
			||||||
 | 
					        const GBinderClientIfaceRange* r = priv->ranges + i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (r->last_code >= code) {
 | 
				
			||||||
 | 
					            return r;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Generates basic request (without additional parameters) for the
 | 
				
			||||||
 | 
					 * specified interface and pulls header data out of it. The basic
 | 
				
			||||||
 | 
					 * request can be reused for those transactions which have no
 | 
				
			||||||
 | 
					 * additional parameters. The header data are needed for building
 | 
				
			||||||
 | 
					 * non-trivial requests.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_client_init_range(
 | 
				
			||||||
 | 
					    GBinderClientIfaceRange* r,
 | 
				
			||||||
 | 
					    GBinderDriver* driver,
 | 
				
			||||||
 | 
					    const GBinderClientIfaceInfo* info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderOutputData* hdr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    r->basic_req = gbinder_driver_local_request_new(driver, info->iface);
 | 
				
			||||||
 | 
					    hdr = gbinder_local_request_data(r->basic_req);
 | 
				
			||||||
 | 
					    r->rpc_header = g_bytes_new(hdr->bytes->data, hdr->bytes->len);
 | 
				
			||||||
 | 
					    r->iface = g_strdup(info->iface);
 | 
				
			||||||
 | 
					    r->last_code = info->last_code;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					gbinder_client_sort_ranges(
 | 
				
			||||||
 | 
					    const void* p1,
 | 
				
			||||||
 | 
					    const void* p2)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const GBinderClientIfaceRange* r1 = p1;
 | 
				
			||||||
 | 
					    const GBinderClientIfaceRange* r2 = p2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (r1->last_code < r2->last_code) ? (-1) :
 | 
				
			||||||
 | 
					        (r1->last_code > r2->last_code) ? 1 : 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_client_free(
 | 
					gbinder_client_free(
 | 
				
			||||||
    GBinderClientPriv* priv)
 | 
					    GBinderClientPriv* priv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GBinderClient* self = &priv->pub;
 | 
					    GBinderClient* self = &priv->pub;
 | 
				
			||||||
 | 
					    guint i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < priv->nr; i++) {
 | 
				
			||||||
 | 
					        GBinderClientIfaceRange* r = priv->ranges + i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gbinder_local_request_unref(r->basic_req);
 | 
				
			||||||
 | 
					        g_free(r->iface);
 | 
				
			||||||
 | 
					        if (r->rpc_header) {
 | 
				
			||||||
 | 
					            g_bytes_unref(r->rpc_header);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    g_free(priv->ranges);
 | 
				
			||||||
    gbinder_remote_object_unref(self->remote);
 | 
					    gbinder_remote_object_unref(self->remote);
 | 
				
			||||||
    gbinder_local_request_unref(priv->basic_req);
 | 
					 | 
				
			||||||
    g_free(priv->iface);
 | 
					 | 
				
			||||||
    g_bytes_unref(priv->rpc_header);
 | 
					 | 
				
			||||||
    g_slice_free(GBinderClientPriv, priv);
 | 
					    g_slice_free(GBinderClientPriv, priv);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -108,38 +178,128 @@ gbinder_client_transact_destroy(
 | 
				
			|||||||
    g_slice_free(GBinderClientTx, tx);
 | 
					    g_slice_free(GBinderClientTx, tx);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*==========================================================================*
 | 
				
			||||||
 | 
					 * Internal interface
 | 
				
			||||||
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderRemoteReply*
 | 
				
			||||||
 | 
					gbinder_client_transact_sync_reply2(
 | 
				
			||||||
 | 
					    GBinderClient* self,
 | 
				
			||||||
 | 
					    guint32 code,
 | 
				
			||||||
 | 
					    GBinderLocalRequest* req,
 | 
				
			||||||
 | 
					    int* status,
 | 
				
			||||||
 | 
					    const GBinderIpcSyncApi* api)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
 | 
					        GBinderRemoteObject* obj = self->remote;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (G_LIKELY(!obj->dead)) {
 | 
				
			||||||
 | 
					            if (!req) {
 | 
				
			||||||
 | 
					                const GBinderClientIfaceRange* r = gbinder_client_find_range
 | 
				
			||||||
 | 
					                    (gbinder_client_cast(self), code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Default empty request (just the header, no parameters) */
 | 
				
			||||||
 | 
					                if (r) {
 | 
				
			||||||
 | 
					                    req = r->basic_req;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (req) {
 | 
				
			||||||
 | 
					                return api->sync_reply(obj->ipc, obj->handle, code, req,
 | 
				
			||||||
 | 
					                    status);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                GWARN("Unable to build empty request for tx code %u", code);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            GDEBUG("Refusing to perform transaction with a dead object");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					gbinder_client_transact_sync_oneway2(
 | 
				
			||||||
 | 
					    GBinderClient* self,
 | 
				
			||||||
 | 
					    guint32 code,
 | 
				
			||||||
 | 
					    GBinderLocalRequest* req,
 | 
				
			||||||
 | 
					    const GBinderIpcSyncApi* api)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
 | 
					        GBinderRemoteObject* obj = self->remote;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (G_LIKELY(!obj->dead)) {
 | 
				
			||||||
 | 
					            if (!req) {
 | 
				
			||||||
 | 
					                const GBinderClientIfaceRange* r = gbinder_client_find_range
 | 
				
			||||||
 | 
					                    (gbinder_client_cast(self), code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Default empty request (just the header, no parameters) */
 | 
				
			||||||
 | 
					                if (r) {
 | 
				
			||||||
 | 
					                    req = r->basic_req;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (req) {
 | 
				
			||||||
 | 
					                return api->sync_oneway(obj->ipc, obj->handle, code, req);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                GWARN("Unable to build empty request for tx code %u", code);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            GDEBUG("Refusing to perform transaction with a dead object");
 | 
				
			||||||
 | 
					            return (-ESTALE);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return (-EINVAL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*==========================================================================*
 | 
					/*==========================================================================*
 | 
				
			||||||
 * Interface
 | 
					 * Interface
 | 
				
			||||||
 *==========================================================================*/
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderClient*
 | 
				
			||||||
 | 
					gbinder_client_new2(
 | 
				
			||||||
 | 
					    GBinderRemoteObject* remote,
 | 
				
			||||||
 | 
					    const GBinderClientIfaceInfo* ifaces,
 | 
				
			||||||
 | 
					    gsize count)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (G_LIKELY(remote)) {
 | 
				
			||||||
 | 
					        GBinderClientPriv* priv = g_slice_new0(GBinderClientPriv);
 | 
				
			||||||
 | 
					        GBinderClient* self = &priv->pub;
 | 
				
			||||||
 | 
					        GBinderDriver* driver = remote->ipc->driver;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        g_atomic_int_set(&priv->refcount, 1);
 | 
				
			||||||
 | 
					        self->remote = gbinder_remote_object_ref(remote);
 | 
				
			||||||
 | 
					        if (count > 0) {
 | 
				
			||||||
 | 
					            gsize i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            priv->nr = count;
 | 
				
			||||||
 | 
					            priv->ranges = g_new(GBinderClientIfaceRange, priv->nr);
 | 
				
			||||||
 | 
					            for (i = 0; i < count; i++) {
 | 
				
			||||||
 | 
					                gbinder_client_init_range(priv->ranges + i, driver, ifaces + i);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            qsort(priv->ranges, count, sizeof(GBinderClientIfaceRange),
 | 
				
			||||||
 | 
					                gbinder_client_sort_ranges);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            /* No interface info */
 | 
				
			||||||
 | 
					            priv->nr = 1;
 | 
				
			||||||
 | 
					            priv->ranges = g_new0(GBinderClientIfaceRange, 1);
 | 
				
			||||||
 | 
					            priv->ranges[0].last_code = UINT_MAX;
 | 
				
			||||||
 | 
					            priv->ranges[0].basic_req = gbinder_local_request_new
 | 
				
			||||||
 | 
					                (gbinder_driver_io(driver), gbinder_driver_protocol(driver),
 | 
				
			||||||
 | 
					                    NULL);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return self;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderClient*
 | 
					GBinderClient*
 | 
				
			||||||
gbinder_client_new(
 | 
					gbinder_client_new(
 | 
				
			||||||
    GBinderRemoteObject* remote,
 | 
					    GBinderRemoteObject* remote,
 | 
				
			||||||
    const char* iface)
 | 
					    const char* iface)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (G_LIKELY(remote) && G_LIKELY(iface)) {
 | 
					    GBinderClientIfaceInfo info;
 | 
				
			||||||
        GBinderClientPriv* priv = g_slice_new0(GBinderClientPriv);
 | 
					 | 
				
			||||||
        GBinderClient* self = &priv->pub;
 | 
					 | 
				
			||||||
        GBinderIpc* ipc = remote->ipc;
 | 
					 | 
				
			||||||
        GBinderOutputData* hdr;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        g_atomic_int_set(&priv->refcount, 1);
 | 
					    info.iface = iface;
 | 
				
			||||||
 | 
					    info.last_code = UINT_MAX;
 | 
				
			||||||
        /*
 | 
					    return gbinder_client_new2(remote, &info, 1);
 | 
				
			||||||
         * Generate basic request (without additional parameters) and pull
 | 
					 | 
				
			||||||
         * header data out of it. The basic request can be reused for those
 | 
					 | 
				
			||||||
         * transactions which has no additional parameters. The header data
 | 
					 | 
				
			||||||
         * are needed for building non-trivial requests.
 | 
					 | 
				
			||||||
         */
 | 
					 | 
				
			||||||
        priv->basic_req = gbinder_driver_local_request_new(ipc->driver, iface);
 | 
					 | 
				
			||||||
        hdr = gbinder_local_request_data(priv->basic_req);
 | 
					 | 
				
			||||||
        priv->rpc_header = g_bytes_new(hdr->bytes->data, hdr->bytes->len);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        self->remote = gbinder_remote_object_ref(remote);
 | 
					 | 
				
			||||||
        self->iface = priv->iface = g_strdup(iface);
 | 
					 | 
				
			||||||
        return self;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return NULL;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderClient*
 | 
					GBinderClient*
 | 
				
			||||||
@@ -169,14 +329,75 @@ gbinder_client_unref(
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char*
 | 
				
			||||||
 | 
					gbinder_client_interface(
 | 
				
			||||||
 | 
					    GBinderClient* self) /* since 1.0.22 */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return G_LIKELY(self) ? gbinder_client_cast(self)->ranges->iface : NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char*
 | 
				
			||||||
 | 
					gbinder_client_interface2(
 | 
				
			||||||
 | 
					    GBinderClient* self,
 | 
				
			||||||
 | 
					    guint32 code) /* since 1.0.42 */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
 | 
					        const GBinderClientIfaceRange* r =
 | 
				
			||||||
 | 
					            gbinder_client_find_range(gbinder_client_cast(self), code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (r) {
 | 
				
			||||||
 | 
					            return r->iface;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBytes*
 | 
				
			||||||
 | 
					gbinder_client_rpc_header(
 | 
				
			||||||
 | 
					    GBinderClient* self,
 | 
				
			||||||
 | 
					    guint32 code) /* since 1.1.14 */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
 | 
					        const GBinderClientIfaceRange* r =
 | 
				
			||||||
 | 
					            gbinder_client_find_range(gbinder_client_cast(self), code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (r) {
 | 
				
			||||||
 | 
					            return r->rpc_header;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderLocalRequest*
 | 
					GBinderLocalRequest*
 | 
				
			||||||
gbinder_client_new_request(
 | 
					gbinder_client_new_request(
 | 
				
			||||||
    GBinderClient* self)
 | 
					    GBinderClient* self)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (G_LIKELY(self)) {
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
        GBinderClientPriv* priv = gbinder_client_cast(self);
 | 
					        GBinderClientPriv* priv = gbinder_client_cast(self);
 | 
				
			||||||
        const GBinderIo* io = gbinder_driver_io(self->remote->ipc->driver);
 | 
					        GBinderDriver* driver = self->remote->ipc->driver;
 | 
				
			||||||
        return gbinder_local_request_new(io, priv->rpc_header);
 | 
					
 | 
				
			||||||
 | 
					        return gbinder_local_request_new(gbinder_driver_io(driver),
 | 
				
			||||||
 | 
					            gbinder_driver_protocol(driver), priv->ranges->rpc_header);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderLocalRequest*
 | 
				
			||||||
 | 
					gbinder_client_new_request2(
 | 
				
			||||||
 | 
					    GBinderClient* self,
 | 
				
			||||||
 | 
					    guint32 code) /* since 1.0.42 */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
 | 
					        GBinderClientPriv* priv = gbinder_client_cast(self);
 | 
				
			||||||
 | 
					        const GBinderClientIfaceRange* range = gbinder_client_find_range
 | 
				
			||||||
 | 
					            (priv, code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (range) {
 | 
				
			||||||
 | 
					            GBinderDriver* driver = self->remote->ipc->driver;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return gbinder_local_request_new(gbinder_driver_io(driver),
 | 
				
			||||||
 | 
					                gbinder_driver_protocol(driver), range->rpc_header);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -188,17 +409,8 @@ gbinder_client_transact_sync_reply(
 | 
				
			|||||||
    GBinderLocalRequest* req,
 | 
					    GBinderLocalRequest* req,
 | 
				
			||||||
    int* status)
 | 
					    int* status)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (G_LIKELY(self)) {
 | 
					    return gbinder_client_transact_sync_reply2(self, code, req, status,
 | 
				
			||||||
        GBinderRemoteObject* obj = self->remote;
 | 
					        &gbinder_ipc_sync_main);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!req) {
 | 
					 | 
				
			||||||
            /* Default empty request (just the header, no parameters) */
 | 
					 | 
				
			||||||
            req = gbinder_client_cast(self)->basic_req;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return gbinder_ipc_transact_sync_reply(obj->ipc, obj->handle,
 | 
					 | 
				
			||||||
            code, req, status);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return NULL;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
@@ -207,18 +419,8 @@ gbinder_client_transact_sync_oneway(
 | 
				
			|||||||
    guint32 code,
 | 
					    guint32 code,
 | 
				
			||||||
    GBinderLocalRequest* req)
 | 
					    GBinderLocalRequest* req)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (G_LIKELY(self)) {
 | 
					    return gbinder_client_transact_sync_oneway2(self, code, req,
 | 
				
			||||||
        GBinderRemoteObject* obj = self->remote;
 | 
					        &gbinder_ipc_sync_main);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!req) {
 | 
					 | 
				
			||||||
            /* Default empty request (just the header, no parameters) */
 | 
					 | 
				
			||||||
            req = gbinder_client_cast(self)->basic_req;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return gbinder_ipc_transact_sync_oneway(obj->ipc, obj->handle,
 | 
					 | 
				
			||||||
            code, req);
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        return (-EINVAL);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gulong
 | 
					gulong
 | 
				
			||||||
@@ -233,23 +435,35 @@ gbinder_client_transact(
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    if (G_LIKELY(self)) {
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
        GBinderRemoteObject* obj = self->remote;
 | 
					        GBinderRemoteObject* obj = self->remote;
 | 
				
			||||||
        GBinderClientTx* tx = g_slice_new0(GBinderClientTx);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        tx->client = gbinder_client_ref(self);
 | 
					        if (G_LIKELY(!obj->dead)) {
 | 
				
			||||||
        tx->reply = reply;
 | 
					            if (!req) {
 | 
				
			||||||
        tx->destroy = destroy;
 | 
					                const GBinderClientIfaceRange* r = gbinder_client_find_range
 | 
				
			||||||
        tx->user_data = user_data;
 | 
					                    (gbinder_client_cast(self), code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!req) {
 | 
					                /* Default empty request (just the header, no parameters) */
 | 
				
			||||||
            /* Default empty request (just the header, no parameters) */
 | 
					                if (r) {
 | 
				
			||||||
            req = gbinder_client_cast(self)->basic_req;
 | 
					                    req = r->basic_req;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (req) {
 | 
				
			||||||
 | 
					                GBinderClientTx* tx = g_slice_new0(GBinderClientTx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                tx->client = gbinder_client_ref(self);
 | 
				
			||||||
 | 
					                tx->reply = reply;
 | 
				
			||||||
 | 
					                tx->destroy = destroy;
 | 
				
			||||||
 | 
					                tx->user_data = user_data;
 | 
				
			||||||
 | 
					                return gbinder_ipc_transact(obj->ipc, obj->handle, code,
 | 
				
			||||||
 | 
					                    flags, req, gbinder_client_transact_reply,
 | 
				
			||||||
 | 
					                    gbinder_client_transact_destroy, tx);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                GWARN("Unable to build empty request for tx code %u", code);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            GDEBUG("Refusing to perform transaction with a dead object");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
        return gbinder_ipc_transact(obj->ipc, obj->handle, code, flags, req,
 | 
					 | 
				
			||||||
            gbinder_client_transact_reply, gbinder_client_transact_destroy, tx);
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        return 0;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -38,10 +38,27 @@
 | 
				
			|||||||
#include "gbinder_types_p.h"
 | 
					#include "gbinder_types_p.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct gbinder_client {
 | 
					struct gbinder_client {
 | 
				
			||||||
    const char* iface;
 | 
					 | 
				
			||||||
    GBinderRemoteObject* remote;
 | 
					    GBinderRemoteObject* remote;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderRemoteReply*
 | 
				
			||||||
 | 
					gbinder_client_transact_sync_reply2(
 | 
				
			||||||
 | 
					    GBinderClient* self,
 | 
				
			||||||
 | 
					    guint32 code,
 | 
				
			||||||
 | 
					    GBinderLocalRequest* req,
 | 
				
			||||||
 | 
					    int* status,
 | 
				
			||||||
 | 
					    const GBinderIpcSyncApi* api)
 | 
				
			||||||
 | 
					    G_GNUC_WARN_UNUSED_RESULT
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					gbinder_client_transact_sync_oneway2(
 | 
				
			||||||
 | 
					    GBinderClient* self,
 | 
				
			||||||
 | 
					    guint32 code,
 | 
				
			||||||
 | 
					    GBinderLocalRequest* req,
 | 
				
			||||||
 | 
					    const GBinderIpcSyncApi* api)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define gbinder_client_ipc(client) ((client)->remote->ipc)
 | 
					#define gbinder_client_ipc(client) ((client)->remote->ipc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* GBINDER_CLIENT_PRIVATE_H */
 | 
					#endif /* GBINDER_CLIENT_PRIVATE_H */
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										429
									
								
								src/gbinder_config.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										429
									
								
								src/gbinder_config.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,429 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2020 Jolla Ltd.
 | 
				
			||||||
 | 
					 * Copyright (C) 2020 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   1. Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 | 
					 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
				
			||||||
 | 
					 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
				
			||||||
 | 
					 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
				
			||||||
 | 
					 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
				
			||||||
 | 
					 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
				
			||||||
 | 
					 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
				
			||||||
 | 
					 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
				
			||||||
 | 
					 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
				
			||||||
 | 
					 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "gbinder_config.h"
 | 
				
			||||||
 | 
					#include "gbinder_eventloop_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gutil_strv.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					#include <sys/stat.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * The contents of the config file is queried from (at least) two places,
 | 
				
			||||||
 | 
					 * and pretty much always this happens the same stack. Which means that
 | 
				
			||||||
 | 
					 * we can avoid reading the same file twice if we delay dereferencing of
 | 
				
			||||||
 | 
					 * GKeyFile until the next idle loop.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static GKeyFile* gbinder_config_keyfile = NULL;
 | 
				
			||||||
 | 
					static GBinderEventLoopCallback* gbinder_config_autorelease = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const char gbinder_config_suffix[] = ".conf";
 | 
				
			||||||
 | 
					static const char gbinder_config_default_file[] = "/etc/gbinder.conf";
 | 
				
			||||||
 | 
					static const char gbinder_config_default_dir[] = "/etc/gbinder.d";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char* gbinder_config_file = gbinder_config_default_file;
 | 
				
			||||||
 | 
					const char* gbinder_config_dir = gbinder_config_default_dir;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Presets for particular API level can be chosen with ApiLevel
 | 
				
			||||||
 | 
					 * setting, e.g.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * [General]
 | 
				
			||||||
 | 
					 * ApiLevel=29
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const char CONF_GENERAL[] = "General";
 | 
				
			||||||
 | 
					static const char CONG_API_LEVEL[] = "ApiLevel";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_config_preset_entry {
 | 
				
			||||||
 | 
					    const char* key;
 | 
				
			||||||
 | 
					    const char* value;
 | 
				
			||||||
 | 
					} GBinderConfigPresetEntry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_config_preset_group {
 | 
				
			||||||
 | 
					    const char* name;
 | 
				
			||||||
 | 
					    const GBinderConfigPresetEntry* entries;
 | 
				
			||||||
 | 
					} GBinderConfigPresetGroup;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_config_preset {
 | 
				
			||||||
 | 
					    guint api_level;
 | 
				
			||||||
 | 
					    const GBinderConfigPresetGroup* groups;
 | 
				
			||||||
 | 
					} GBinderConfigPreset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* API level 28 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const GBinderConfigPresetEntry gbinder_config_28_servicemanager[] = {
 | 
				
			||||||
 | 
					    { "/dev/binder", "aidl2" },
 | 
				
			||||||
 | 
					    { "/dev/vndbinder", "aidl2" },
 | 
				
			||||||
 | 
					    { NULL, NULL }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const GBinderConfigPresetGroup gbinder_config_28[] = {
 | 
				
			||||||
 | 
					    { GBINDER_CONFIG_GROUP_SERVICEMANAGER, gbinder_config_28_servicemanager },
 | 
				
			||||||
 | 
					    { NULL, NULL }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* API level 29 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const GBinderConfigPresetEntry gbinder_config_29_protocol[] = {
 | 
				
			||||||
 | 
					    { "/dev/binder", "aidl2" },
 | 
				
			||||||
 | 
					    { "/dev/vndbinder", "aidl2" },
 | 
				
			||||||
 | 
					    { NULL, NULL }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define gbinder_config_29_servicemanager gbinder_config_28_servicemanager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const GBinderConfigPresetGroup gbinder_config_29[] = {
 | 
				
			||||||
 | 
					    { GBINDER_CONFIG_GROUP_PROTOCOL, gbinder_config_29_protocol },
 | 
				
			||||||
 | 
					    { GBINDER_CONFIG_GROUP_SERVICEMANAGER, gbinder_config_29_servicemanager },
 | 
				
			||||||
 | 
					    { NULL, NULL }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* API level 30 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const GBinderConfigPresetEntry gbinder_config_30_protocol[] = {
 | 
				
			||||||
 | 
					    { "/dev/binder", "aidl3" },
 | 
				
			||||||
 | 
					    { "/dev/vndbinder", "aidl3" },
 | 
				
			||||||
 | 
					    { NULL, NULL }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const GBinderConfigPresetEntry gbinder_config_30_servicemanager[] = {
 | 
				
			||||||
 | 
					    { "/dev/binder", "aidl3" },
 | 
				
			||||||
 | 
					    { "/dev/vndbinder", "aidl3" },
 | 
				
			||||||
 | 
					    { NULL, NULL }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const GBinderConfigPresetGroup gbinder_config_30[] = {
 | 
				
			||||||
 | 
					    { GBINDER_CONFIG_GROUP_PROTOCOL, gbinder_config_30_protocol },
 | 
				
			||||||
 | 
					    { GBINDER_CONFIG_GROUP_SERVICEMANAGER, gbinder_config_30_servicemanager },
 | 
				
			||||||
 | 
					    { NULL, NULL }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* API level 31 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const GBinderConfigPresetEntry gbinder_config_31_protocol[] = {
 | 
				
			||||||
 | 
					    { "/dev/binder", "aidl4" },
 | 
				
			||||||
 | 
					    { "/dev/vndbinder", "aidl4" },
 | 
				
			||||||
 | 
					    { NULL, NULL }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const GBinderConfigPresetGroup gbinder_config_31[] = {
 | 
				
			||||||
 | 
					    { GBINDER_CONFIG_GROUP_PROTOCOL, gbinder_config_31_protocol },
 | 
				
			||||||
 | 
					    { GBINDER_CONFIG_GROUP_SERVICEMANAGER, gbinder_config_30_servicemanager },
 | 
				
			||||||
 | 
					    { NULL, NULL }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* API level 33 - reverts back to AIDL3 protocol */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const GBinderConfigPresetGroup gbinder_config_33[] = {
 | 
				
			||||||
 | 
					    { GBINDER_CONFIG_GROUP_PROTOCOL, gbinder_config_30_protocol },
 | 
				
			||||||
 | 
					    { GBINDER_CONFIG_GROUP_SERVICEMANAGER, gbinder_config_30_servicemanager },
 | 
				
			||||||
 | 
					    { NULL, NULL }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Presets sorted by API level in descending order */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const GBinderConfigPreset gbinder_config_presets[] = {
 | 
				
			||||||
 | 
					    { 33, gbinder_config_33 },
 | 
				
			||||||
 | 
					    { 31, gbinder_config_31 },
 | 
				
			||||||
 | 
					    { 30, gbinder_config_30 },
 | 
				
			||||||
 | 
					    { 29, gbinder_config_29 },
 | 
				
			||||||
 | 
					    { 28, gbinder_config_28 }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					char**
 | 
				
			||||||
 | 
					gbinder_config_collect_files(
 | 
				
			||||||
 | 
					    const char* path,
 | 
				
			||||||
 | 
					    const char* suffix)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * Returns sorted list of regular files in the directory,
 | 
				
			||||||
 | 
					     * optionally having the specified suffix (e.g. ".conf").
 | 
				
			||||||
 | 
					     * Returns NULL if nothing appropriate has been found.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    char** files = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (path) {
 | 
				
			||||||
 | 
					        GDir* dir = g_dir_open(path, 0, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (dir) {
 | 
				
			||||||
 | 
					            GPtrArray* list = g_ptr_array_new();
 | 
				
			||||||
 | 
					            const gchar* name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            while ((name = g_dir_read_name(dir)) != NULL) {
 | 
				
			||||||
 | 
					                if (g_str_has_suffix(name, suffix)) {
 | 
				
			||||||
 | 
					                    char* fullname = g_build_filename(path, name, NULL);
 | 
				
			||||||
 | 
					                    struct stat st;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (!stat(fullname, &st) && S_ISREG(st.st_mode)) {
 | 
				
			||||||
 | 
					                        g_ptr_array_add(list, fullname);
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        g_free(fullname);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (list->len > 0) {
 | 
				
			||||||
 | 
					                g_ptr_array_add(list, NULL);
 | 
				
			||||||
 | 
					                files = (char**) g_ptr_array_free(list, FALSE);
 | 
				
			||||||
 | 
					                gutil_strv_sort(files, TRUE);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                g_ptr_array_free(list, TRUE);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            g_dir_close(dir);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return files;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					GKeyFile*
 | 
				
			||||||
 | 
					gbinder_config_merge_keyfiles(
 | 
				
			||||||
 | 
					    GKeyFile* dest,
 | 
				
			||||||
 | 
					    GKeyFile* src)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    gsize i, ngroups;
 | 
				
			||||||
 | 
					    gchar** groups = g_key_file_get_groups(src, &ngroups);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < ngroups; i++) {
 | 
				
			||||||
 | 
					        gsize k, nkeys;
 | 
				
			||||||
 | 
					        const char* group = groups[i];
 | 
				
			||||||
 | 
					        char** keys = g_key_file_get_keys(src, group, &nkeys, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (k = 0; k < nkeys; k++) {
 | 
				
			||||||
 | 
					            const char* key = keys[k];
 | 
				
			||||||
 | 
					            char* value = g_key_file_get_value(src, group, key, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            g_key_file_set_value(dest, group, key, value);
 | 
				
			||||||
 | 
					            g_free(value);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        g_strfreev(keys);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_strfreev(groups);
 | 
				
			||||||
 | 
					    return dest;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_config_apply_presets(
 | 
				
			||||||
 | 
					    GKeyFile* config,
 | 
				
			||||||
 | 
					    const GBinderConfigPreset* preset)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const GBinderConfigPresetGroup* g;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    GDEBUG("Applying presets for API level %d", preset->api_level);
 | 
				
			||||||
 | 
					    for (g = preset->groups; g->name; g++) {
 | 
				
			||||||
 | 
					        const GBinderConfigPresetEntry* e;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (e = g->entries; e->key; e++) {
 | 
				
			||||||
 | 
					            if (!g_key_file_has_key(config, g->name, e->key, NULL)) {
 | 
				
			||||||
 | 
					                g_key_file_set_value(config, g->name, e->key, e->value);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					GKeyFile*
 | 
				
			||||||
 | 
					gbinder_config_load_files()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GError* error = NULL;
 | 
				
			||||||
 | 
					    GKeyFile* out = NULL;
 | 
				
			||||||
 | 
					    char** files = gbinder_config_collect_files(gbinder_config_dir,
 | 
				
			||||||
 | 
					        gbinder_config_suffix);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (gbinder_config_file &&
 | 
				
			||||||
 | 
					        g_file_test(gbinder_config_file, G_FILE_TEST_EXISTS)) {
 | 
				
			||||||
 | 
					        out = g_key_file_new();
 | 
				
			||||||
 | 
					        if (g_key_file_load_from_file(out, gbinder_config_file,
 | 
				
			||||||
 | 
					            G_KEY_FILE_NONE, &error)) {
 | 
				
			||||||
 | 
					            GDEBUG("Loaded %s", gbinder_config_file);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            GERR("Error loading %s: %s", gbinder_config_file, error->message);
 | 
				
			||||||
 | 
					            g_error_free(error);
 | 
				
			||||||
 | 
					            error = NULL;
 | 
				
			||||||
 | 
					            gbinder_config_file = NULL; /* Don't retry */
 | 
				
			||||||
 | 
					            g_key_file_unref(out);
 | 
				
			||||||
 | 
					            out = NULL;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Files in the config directory overwrite /etc/gbinder.conf */
 | 
				
			||||||
 | 
					    if (files) {
 | 
				
			||||||
 | 
					        char** ptr;
 | 
				
			||||||
 | 
					        GKeyFile* override = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (ptr = files; *ptr; ptr++) {
 | 
				
			||||||
 | 
					            const char* file = *ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!override) {
 | 
				
			||||||
 | 
					                override = g_key_file_new();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (g_key_file_load_from_file(override, file,
 | 
				
			||||||
 | 
					                G_KEY_FILE_NONE, &error)) {
 | 
				
			||||||
 | 
					                GDEBUG("Loaded %s", file);
 | 
				
			||||||
 | 
					                if (!out) {
 | 
				
			||||||
 | 
					                    out = override;
 | 
				
			||||||
 | 
					                    override = NULL;
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    out = gbinder_config_merge_keyfiles(out, override);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                GERR("Error loading %s: %s", file, error->message);
 | 
				
			||||||
 | 
					                g_error_free(error);
 | 
				
			||||||
 | 
					                error = NULL;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        g_strfreev(files);
 | 
				
			||||||
 | 
					        if (override) {
 | 
				
			||||||
 | 
					            g_key_file_unref(override);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (out) {
 | 
				
			||||||
 | 
					        /* Apply presets */
 | 
				
			||||||
 | 
					        const int api_level = g_key_file_get_integer(out,
 | 
				
			||||||
 | 
					            CONF_GENERAL, CONG_API_LEVEL, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (api_level > 0) {
 | 
				
			||||||
 | 
					            int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            GDEBUG("API level %d", api_level);
 | 
				
			||||||
 | 
					            for (i = 0; i < G_N_ELEMENTS(gbinder_config_presets); i++) {
 | 
				
			||||||
 | 
					                const GBinderConfigPreset* preset = gbinder_config_presets + i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (api_level >= preset->api_level) {
 | 
				
			||||||
 | 
					                    gbinder_config_apply_presets(out, preset);
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return out;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_config_autorelease_cb(
 | 
				
			||||||
 | 
					    gpointer data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GASSERT(gbinder_config_keyfile == data);
 | 
				
			||||||
 | 
					    gbinder_config_keyfile = NULL;
 | 
				
			||||||
 | 
					    g_key_file_unref(data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GKeyFile* /* autoreleased */
 | 
				
			||||||
 | 
					gbinder_config_get()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (!gbinder_config_keyfile &&
 | 
				
			||||||
 | 
					        (gbinder_config_file || gbinder_config_dir)) {
 | 
				
			||||||
 | 
					        gbinder_config_keyfile = gbinder_config_load_files();
 | 
				
			||||||
 | 
					        if (gbinder_config_keyfile) {
 | 
				
			||||||
 | 
					            /* See the comment at the top of the file why this is needed */
 | 
				
			||||||
 | 
					            gbinder_config_autorelease = gbinder_idle_callback_schedule_new
 | 
				
			||||||
 | 
					               (gbinder_config_autorelease_cb, gbinder_config_keyfile, NULL);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return gbinder_config_keyfile;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Helper for loading config group in device = ident format */
 | 
				
			||||||
 | 
					GHashTable*
 | 
				
			||||||
 | 
					gbinder_config_load(
 | 
				
			||||||
 | 
					    const char* group,
 | 
				
			||||||
 | 
					    GBinderConfigValueMapFunc mapper)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GKeyFile* k = gbinder_config_get();
 | 
				
			||||||
 | 
					    GHashTable* map = g_hash_table_new_full(g_str_hash, g_str_equal,
 | 
				
			||||||
 | 
					        g_free, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (k) {
 | 
				
			||||||
 | 
					        gsize n;
 | 
				
			||||||
 | 
					        char** devs = g_key_file_get_keys(k, group, &n, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (devs) {
 | 
				
			||||||
 | 
					            gsize i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for (i = 0; i < n; i++) {
 | 
				
			||||||
 | 
					                char* dev = devs[i];
 | 
				
			||||||
 | 
					                char* sval = g_key_file_get_value(k, group, dev, NULL);
 | 
				
			||||||
 | 
					                gconstpointer val = mapper(sval);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (val) {
 | 
				
			||||||
 | 
					                    g_hash_table_replace(map, dev, (gpointer) val);
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    GWARN("Unknown gbinder config '%s' for %s in group [%s]",
 | 
				
			||||||
 | 
					                        sval, dev, group);
 | 
				
			||||||
 | 
					                    g_free(dev);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                g_free(sval);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* Shallow delete (contents got stolen or freed) */
 | 
				
			||||||
 | 
					            g_free(devs);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return map;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_config_exit()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (gbinder_config_autorelease) {
 | 
				
			||||||
 | 
					        gbinder_idle_callback_destroy(gbinder_config_autorelease);
 | 
				
			||||||
 | 
					        gbinder_config_autorelease = NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (gbinder_config_keyfile) {
 | 
				
			||||||
 | 
					        g_key_file_unref(gbinder_config_keyfile);
 | 
				
			||||||
 | 
					        gbinder_config_keyfile = NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Local Variables:
 | 
				
			||||||
 | 
					 * mode: C
 | 
				
			||||||
 | 
					 * c-basic-offset: 4
 | 
				
			||||||
 | 
					 * indent-tabs-mode: nil
 | 
				
			||||||
 | 
					 * End:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
							
								
								
									
										78
									
								
								src/gbinder_config.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								src/gbinder_config.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,78 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2020 Jolla Ltd.
 | 
				
			||||||
 | 
					 * Copyright (C) 2020 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   1. Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 | 
					 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
				
			||||||
 | 
					 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
				
			||||||
 | 
					 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
				
			||||||
 | 
					 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
				
			||||||
 | 
					 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
				
			||||||
 | 
					 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
				
			||||||
 | 
					 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
				
			||||||
 | 
					 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
				
			||||||
 | 
					 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GBINDER_CONFIG_H
 | 
				
			||||||
 | 
					#define GBINDER_CONFIG_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "gbinder_types_p.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef
 | 
				
			||||||
 | 
					gconstpointer
 | 
				
			||||||
 | 
					(*GBinderConfigValueMapFunc)(
 | 
				
			||||||
 | 
					    const char* value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GHashTable*
 | 
				
			||||||
 | 
					gbinder_config_load(
 | 
				
			||||||
 | 
					    const char* group,
 | 
				
			||||||
 | 
					    GBinderConfigValueMapFunc map)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GKeyFile* /* autoreleased */
 | 
				
			||||||
 | 
					gbinder_config_get(
 | 
				
			||||||
 | 
					    void)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* This one declared strictly for unit tests */
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_config_exit(
 | 
				
			||||||
 | 
					    void)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL
 | 
				
			||||||
 | 
					    GBINDER_DESTRUCTOR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* And these too */
 | 
				
			||||||
 | 
					extern const char* gbinder_config_file GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					extern const char* gbinder_config_dir GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Configuration groups and special value */
 | 
				
			||||||
 | 
					#define GBINDER_CONFIG_GROUP_PROTOCOL "Protocol"
 | 
				
			||||||
 | 
					#define GBINDER_CONFIG_GROUP_SERVICEMANAGER "ServiceManager"
 | 
				
			||||||
 | 
					#define GBINDER_CONFIG_VALUE_DEFAULT "Default"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* GBINDER_CONFIG_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Local Variables:
 | 
				
			||||||
 | 
					 * mode: C
 | 
				
			||||||
 | 
					 * c-basic-offset: 4
 | 
				
			||||||
 | 
					 * indent-tabs-mode: nil
 | 
				
			||||||
 | 
					 * End:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
@@ -1,180 +0,0 @@
 | 
				
			|||||||
/*
 | 
					 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Redistribution and use in source and binary forms, with or without
 | 
					 | 
				
			||||||
 * modification, are permitted provided that the following conditions
 | 
					 | 
				
			||||||
 * are met:
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *   1. Redistributions of source code must retain the above copyright
 | 
					 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer.
 | 
					 | 
				
			||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 | 
				
			||||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
					 | 
				
			||||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
					 | 
				
			||||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
					 | 
				
			||||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
					 | 
				
			||||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
					 | 
				
			||||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
					 | 
				
			||||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
					 | 
				
			||||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
					 | 
				
			||||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "gbinder_servicemanager_p.h"
 | 
					 | 
				
			||||||
#include "gbinder_log.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <gbinder_client.h>
 | 
					 | 
				
			||||||
#include <gbinder_local_request.h>
 | 
					 | 
				
			||||||
#include <gbinder_remote_reply.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <gutil_macros.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <errno.h>
 | 
					 | 
				
			||||||
#include <pthread.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef GBinderServiceManager GBinderDefaultServiceManager;
 | 
					 | 
				
			||||||
typedef GBinderServiceManagerClass GBinderDefaultServiceManagerClass;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
G_DEFINE_TYPE(GBinderDefaultServiceManager,
 | 
					 | 
				
			||||||
    gbinder_defaultservicemanager,
 | 
					 | 
				
			||||||
    GBINDER_TYPE_SERVICEMANAGER)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum gbinder_defaultservicemanager_calls {
 | 
					 | 
				
			||||||
    GET_SERVICE_TRANSACTION = GBINDER_FIRST_CALL_TRANSACTION,
 | 
					 | 
				
			||||||
    CHECK_SERVICE_TRANSACTION,
 | 
					 | 
				
			||||||
    ADD_SERVICE_TRANSACTION,
 | 
					 | 
				
			||||||
    LIST_SERVICES_TRANSACTION
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* As a special case, ServiceManager's handle is zero */
 | 
					 | 
				
			||||||
#define DEFAULTSERVICEMANAGER_HANDLE (0)
 | 
					 | 
				
			||||||
#define DEFAULTSERVICEMANAGER_IFACE  "android.os.IServiceManager"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
GBinderServiceManager*
 | 
					 | 
				
			||||||
gbinder_defaultservicemanager_new(
 | 
					 | 
				
			||||||
    const char* dev)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    return gbinder_servicemanager_new_with_type
 | 
					 | 
				
			||||||
        (gbinder_defaultservicemanager_get_type(), dev);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static
 | 
					 | 
				
			||||||
GBinderLocalRequest*
 | 
					 | 
				
			||||||
gbinder_servicemanager_list_services_req(
 | 
					 | 
				
			||||||
    GBinderServiceManager* self,
 | 
					 | 
				
			||||||
    gint32 index)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    return gbinder_local_request_append_int32
 | 
					 | 
				
			||||||
        (gbinder_client_new_request(self->client), index);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static
 | 
					 | 
				
			||||||
char**
 | 
					 | 
				
			||||||
gbinder_defaultservicemanager_list(
 | 
					 | 
				
			||||||
    GBinderServiceManager* self)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    GPtrArray* list = g_ptr_array_new();
 | 
					 | 
				
			||||||
    GBinderLocalRequest* req = gbinder_servicemanager_list_services_req(self,0);
 | 
					 | 
				
			||||||
    GBinderRemoteReply* reply;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    while ((reply = gbinder_client_transact_sync_reply(self->client,
 | 
					 | 
				
			||||||
        LIST_SERVICES_TRANSACTION, req, NULL)) != NULL) {
 | 
					 | 
				
			||||||
        char* service = gbinder_remote_reply_read_string16(reply);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        gbinder_remote_reply_unref(reply);
 | 
					 | 
				
			||||||
        if (service) {
 | 
					 | 
				
			||||||
            g_ptr_array_add(list, service);
 | 
					 | 
				
			||||||
            gbinder_local_request_unref(req);
 | 
					 | 
				
			||||||
            req = gbinder_servicemanager_list_services_req(self, list->len);
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    gbinder_local_request_unref(req);
 | 
					 | 
				
			||||||
    g_ptr_array_add(list, NULL);
 | 
					 | 
				
			||||||
    return (char**)g_ptr_array_free(list, FALSE);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static
 | 
					 | 
				
			||||||
GBinderRemoteObject*
 | 
					 | 
				
			||||||
gbinder_defaultservicemanager_get_service(
 | 
					 | 
				
			||||||
    GBinderServiceManager* self,
 | 
					 | 
				
			||||||
    const char* name,
 | 
					 | 
				
			||||||
    int* status)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    GBinderRemoteObject* obj;
 | 
					 | 
				
			||||||
    GBinderRemoteReply* reply;
 | 
					 | 
				
			||||||
    GBinderLocalRequest* req = gbinder_client_new_request(self->client);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    gbinder_local_request_append_string16(req, name);
 | 
					 | 
				
			||||||
    reply = gbinder_client_transact_sync_reply(self->client,
 | 
					 | 
				
			||||||
        CHECK_SERVICE_TRANSACTION, req, status);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    obj = gbinder_remote_reply_read_object(reply);
 | 
					 | 
				
			||||||
    gbinder_remote_reply_unref(reply);
 | 
					 | 
				
			||||||
    gbinder_local_request_unref(req);
 | 
					 | 
				
			||||||
    return obj;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
gbinder_defaultservicemanager_add_service(
 | 
					 | 
				
			||||||
    GBinderServiceManager* self,
 | 
					 | 
				
			||||||
    const char* name,
 | 
					 | 
				
			||||||
    GBinderLocalObject* obj)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    int status;
 | 
					 | 
				
			||||||
    GBinderRemoteReply* reply;
 | 
					 | 
				
			||||||
    GBinderLocalRequest* req = gbinder_client_new_request(self->client);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    gbinder_local_request_append_string16(req, name);
 | 
					 | 
				
			||||||
    gbinder_local_request_append_local_object(req, obj);
 | 
					 | 
				
			||||||
    gbinder_local_request_append_int32(req, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    reply = gbinder_client_transact_sync_reply(self->client,
 | 
					 | 
				
			||||||
        ADD_SERVICE_TRANSACTION, req, &status);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    gbinder_remote_reply_unref(reply);
 | 
					 | 
				
			||||||
    gbinder_local_request_unref(req);
 | 
					 | 
				
			||||||
    return status;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
gbinder_defaultservicemanager_init(
 | 
					 | 
				
			||||||
    GBinderDefaultServiceManager* self)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
gbinder_defaultservicemanager_class_init(
 | 
					 | 
				
			||||||
    GBinderDefaultServiceManagerClass* klass)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    klass->handle = DEFAULTSERVICEMANAGER_HANDLE;
 | 
					 | 
				
			||||||
    klass->iface = DEFAULTSERVICEMANAGER_IFACE;
 | 
					 | 
				
			||||||
    klass->default_device = GBINDER_DEFAULT_BINDER;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    klass->list = gbinder_defaultservicemanager_list;
 | 
					 | 
				
			||||||
    klass->get_service = gbinder_defaultservicemanager_get_service;
 | 
					 | 
				
			||||||
    klass->add_service = gbinder_defaultservicemanager_add_service;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Local Variables:
 | 
					 | 
				
			||||||
 * mode: C
 | 
					 | 
				
			||||||
 * c-basic-offset: 4
 | 
					 | 
				
			||||||
 * indent-tabs-mode: nil
 | 
					 | 
				
			||||||
 * End:
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -39,95 +39,150 @@ struct pollfd;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
GBinderDriver*
 | 
					GBinderDriver*
 | 
				
			||||||
gbinder_driver_new(
 | 
					gbinder_driver_new(
 | 
				
			||||||
    const char* dev);
 | 
					    const char* dev,
 | 
				
			||||||
 | 
					    const GBinderRpcProtocol* protocol)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderDriver*
 | 
					GBinderDriver*
 | 
				
			||||||
gbinder_driver_ref(
 | 
					gbinder_driver_ref(
 | 
				
			||||||
    GBinderDriver* driver);
 | 
					    GBinderDriver* driver)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_driver_unref(
 | 
					gbinder_driver_unref(
 | 
				
			||||||
    GBinderDriver* driver);
 | 
					    GBinderDriver* driver)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_driver_close(
 | 
				
			||||||
 | 
					    GBinderDriver* driver)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
gbinder_driver_fd(
 | 
					gbinder_driver_fd(
 | 
				
			||||||
    GBinderDriver* driver);
 | 
					    GBinderDriver* driver)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
gbinder_driver_poll(
 | 
					gbinder_driver_poll(
 | 
				
			||||||
    GBinderDriver* driver,
 | 
					    GBinderDriver* driver,
 | 
				
			||||||
    struct pollfd* pollfd);
 | 
					    struct pollfd* pollfd)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const char*
 | 
					const char*
 | 
				
			||||||
gbinder_driver_dev(
 | 
					gbinder_driver_dev(
 | 
				
			||||||
    GBinderDriver* driver);
 | 
					    GBinderDriver* driver)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const GBinderIo*
 | 
					const GBinderIo*
 | 
				
			||||||
gbinder_driver_io(
 | 
					gbinder_driver_io(
 | 
				
			||||||
    GBinderDriver* driver);
 | 
					    GBinderDriver* driver)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const GBinderRpcProtocol*
 | 
				
			||||||
 | 
					gbinder_driver_protocol(
 | 
				
			||||||
 | 
					    GBinderDriver* driver)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_driver_acquire_done(
 | 
				
			||||||
 | 
					    GBinderDriver* driver,
 | 
				
			||||||
 | 
					    GBinderLocalObject* obj)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_driver_dead_binder_done(
 | 
				
			||||||
 | 
					    GBinderDriver* driver,
 | 
				
			||||||
 | 
					    GBinderRemoteObject* obj)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gboolean
 | 
					gboolean
 | 
				
			||||||
gbinder_driver_request_death_notification(
 | 
					gbinder_driver_request_death_notification(
 | 
				
			||||||
    GBinderDriver* driver,
 | 
					    GBinderDriver* driver,
 | 
				
			||||||
    GBinderRemoteObject* obj);
 | 
					    GBinderRemoteObject* obj)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gboolean
 | 
					gboolean
 | 
				
			||||||
gbinder_driver_clear_death_notification(
 | 
					gbinder_driver_clear_death_notification(
 | 
				
			||||||
    GBinderDriver* driver,
 | 
					    GBinderDriver* driver,
 | 
				
			||||||
    GBinderRemoteObject* obj);
 | 
					    GBinderRemoteObject* obj)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gboolean
 | 
					gboolean
 | 
				
			||||||
gbinder_driver_increfs(
 | 
					gbinder_driver_increfs(
 | 
				
			||||||
    GBinderDriver* driver,
 | 
					    GBinderDriver* driver,
 | 
				
			||||||
    guint32 handle);
 | 
					    guint32 handle)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gboolean
 | 
					gboolean
 | 
				
			||||||
gbinder_driver_decrefs(
 | 
					gbinder_driver_decrefs(
 | 
				
			||||||
    GBinderDriver* driver,
 | 
					    GBinderDriver* driver,
 | 
				
			||||||
    guint32 handle);
 | 
					    guint32 handle)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gboolean
 | 
					gboolean
 | 
				
			||||||
gbinder_driver_acquire(
 | 
					gbinder_driver_acquire(
 | 
				
			||||||
    GBinderDriver* driver,
 | 
					    GBinderDriver* driver,
 | 
				
			||||||
    guint32 handle);
 | 
					    guint32 handle)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gboolean
 | 
					gboolean
 | 
				
			||||||
gbinder_driver_release(
 | 
					gbinder_driver_release(
 | 
				
			||||||
    GBinderDriver* driver,
 | 
					    GBinderDriver* driver,
 | 
				
			||||||
    guint32 handle);
 | 
					    guint32 handle)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_driver_close_fds(
 | 
				
			||||||
 | 
					    GBinderDriver* driver,
 | 
				
			||||||
 | 
					    void** objects,
 | 
				
			||||||
 | 
					    const void* end)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_driver_free_buffer(
 | 
					gbinder_driver_free_buffer(
 | 
				
			||||||
    GBinderDriver* driver,
 | 
					    GBinderDriver* driver,
 | 
				
			||||||
    void* buffer);
 | 
					    void* buffer)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gboolean
 | 
					gboolean
 | 
				
			||||||
gbinder_driver_enter_looper(
 | 
					gbinder_driver_enter_looper(
 | 
				
			||||||
    GBinderDriver* driver);
 | 
					    GBinderDriver* driver)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gboolean
 | 
					gboolean
 | 
				
			||||||
gbinder_driver_exit_looper(
 | 
					gbinder_driver_exit_looper(
 | 
				
			||||||
    GBinderDriver* driver);
 | 
					    GBinderDriver* driver)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
gbinder_driver_read(
 | 
					gbinder_driver_read(
 | 
				
			||||||
    GBinderDriver* driver,
 | 
					    GBinderDriver* driver,
 | 
				
			||||||
    GBinderObjectRegistry* reg,
 | 
					    GBinderObjectRegistry* reg,
 | 
				
			||||||
    GBinderHandler* handler);
 | 
					    GBinderHandler* handler)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
gbinder_driver_transact(
 | 
					gbinder_driver_transact(
 | 
				
			||||||
    GBinderDriver* driver,
 | 
					    GBinderDriver* driver,
 | 
				
			||||||
    GBinderObjectRegistry* reg,
 | 
					    GBinderObjectRegistry* reg,
 | 
				
			||||||
 | 
					    GBinderHandler* handler,
 | 
				
			||||||
    guint32 handle,
 | 
					    guint32 handle,
 | 
				
			||||||
    guint32 code,
 | 
					    guint32 code,
 | 
				
			||||||
    GBinderLocalRequest* request,
 | 
					    GBinderLocalRequest* request,
 | 
				
			||||||
    GBinderRemoteReply* reply);
 | 
					    GBinderRemoteReply* reply)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderLocalRequest*
 | 
					GBinderLocalRequest*
 | 
				
			||||||
gbinder_driver_local_request_new(
 | 
					gbinder_driver_local_request_new(
 | 
				
			||||||
    GBinderDriver* self,
 | 
					    GBinderDriver* driver,
 | 
				
			||||||
    const char* iface);
 | 
					    const char* iface)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderLocalRequest*
 | 
				
			||||||
 | 
					gbinder_driver_local_request_new_ping(
 | 
				
			||||||
 | 
					    GBinderDriver* self)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* GBINDER_DRIVER_H */
 | 
					#endif /* GBINDER_DRIVER_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										405
									
								
								src/gbinder_eventloop.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										405
									
								
								src/gbinder_eventloop.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,405 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2020-2021 Jolla Ltd.
 | 
				
			||||||
 | 
					 * Copyright (C) 2020-2021 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   1. Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 | 
					 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
				
			||||||
 | 
					 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
				
			||||||
 | 
					 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
				
			||||||
 | 
					 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
				
			||||||
 | 
					 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
				
			||||||
 | 
					 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
				
			||||||
 | 
					 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
				
			||||||
 | 
					 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
				
			||||||
 | 
					 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "gbinder_eventloop_p.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gutil_macros.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_idle_callback_data {
 | 
				
			||||||
 | 
					    GBinderEventLoopCallback* cb;
 | 
				
			||||||
 | 
					    GBinderEventLoopCallbackFunc func;
 | 
				
			||||||
 | 
					    GDestroyNotify destroy;
 | 
				
			||||||
 | 
					    gpointer data;
 | 
				
			||||||
 | 
					} GBinderIdleCallbackData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define GBINDER_DEFAULT_EVENTLOOP (&gbinder_eventloop_glib)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const GBinderEventLoopIntegration gbinder_eventloop_glib;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*==========================================================================*
 | 
				
			||||||
 | 
					 * GLib event loop integration
 | 
				
			||||||
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_eventloop_glib_timeout {
 | 
				
			||||||
 | 
					    GBinderEventLoopTimeout timeout;
 | 
				
			||||||
 | 
					    guint id;
 | 
				
			||||||
 | 
					    GSourceFunc func;
 | 
				
			||||||
 | 
					    gpointer data;
 | 
				
			||||||
 | 
					} GBinderEventLoopTimeoutGLib;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_eventloop_glib_callback {
 | 
				
			||||||
 | 
					    GSource source;
 | 
				
			||||||
 | 
					    GBinderEventLoopCallback callback;
 | 
				
			||||||
 | 
					} GBinderEventLoopCallbackGLib;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					inline
 | 
				
			||||||
 | 
					GBinderEventLoopTimeoutGLib*
 | 
				
			||||||
 | 
					gbinder_eventloop_glib_timeout_cast(
 | 
				
			||||||
 | 
					    GBinderEventLoopTimeout* timeout)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return G_CAST(timeout,GBinderEventLoopTimeoutGLib,timeout);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					inline
 | 
				
			||||||
 | 
					GSource*
 | 
				
			||||||
 | 
					gbinder_eventloop_glib_callback_source(
 | 
				
			||||||
 | 
					    GBinderEventLoopCallback* callback)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return &(G_CAST(callback,GBinderEventLoopCallbackGLib,callback)->source);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_eventloop_glib_timeout_callback(
 | 
				
			||||||
 | 
					    gpointer data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderEventLoopTimeoutGLib* timeout = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return timeout->func(timeout->data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_eventloop_glib_timeout_finalize(
 | 
				
			||||||
 | 
					    gpointer data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    g_slice_free1(sizeof(GBinderEventLoopTimeoutGLib), data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					GBinderEventLoopTimeout*
 | 
				
			||||||
 | 
					gbinder_eventloop_glib_timeout_add(
 | 
				
			||||||
 | 
					    guint interval,
 | 
				
			||||||
 | 
					    GSourceFunc func,
 | 
				
			||||||
 | 
					    gpointer data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderEventLoopTimeoutGLib* impl =
 | 
				
			||||||
 | 
					        g_slice_new(GBinderEventLoopTimeoutGLib);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    impl->timeout.eventloop = &gbinder_eventloop_glib;
 | 
				
			||||||
 | 
					    impl->func = func;
 | 
				
			||||||
 | 
					    impl->data = data;
 | 
				
			||||||
 | 
					    impl->id = g_timeout_add_full(G_PRIORITY_DEFAULT, interval,
 | 
				
			||||||
 | 
					        gbinder_eventloop_glib_timeout_callback, impl,
 | 
				
			||||||
 | 
					        gbinder_eventloop_glib_timeout_finalize);
 | 
				
			||||||
 | 
					    return &impl->timeout;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_eventloop_glib_timeout_remove(
 | 
				
			||||||
 | 
					    GBinderEventLoopTimeout* timeout)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    g_source_remove(gbinder_eventloop_glib_timeout_cast(timeout)->id);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_eventloop_glib_callback_prepare(
 | 
				
			||||||
 | 
					    GSource* source,
 | 
				
			||||||
 | 
					    gint* timeout)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    *timeout = 0;
 | 
				
			||||||
 | 
					    return TRUE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_eventloop_glib_callback_check(
 | 
				
			||||||
 | 
					    GSource* source)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return TRUE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_eventloop_glib_callback_dispatch(
 | 
				
			||||||
 | 
					    GSource* source,
 | 
				
			||||||
 | 
					    GSourceFunc callback,
 | 
				
			||||||
 | 
					    gpointer user_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    ((GBinderEventLoopCallbackFunc)callback)(user_data);
 | 
				
			||||||
 | 
					    return G_SOURCE_REMOVE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					GBinderEventLoopCallback*
 | 
				
			||||||
 | 
					gbinder_eventloop_glib_callback_new(
 | 
				
			||||||
 | 
					    GBinderEventLoopCallbackFunc func,
 | 
				
			||||||
 | 
					    gpointer data,
 | 
				
			||||||
 | 
					    GDestroyNotify finalize)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static GSourceFuncs callback_funcs = {
 | 
				
			||||||
 | 
					        gbinder_eventloop_glib_callback_prepare,
 | 
				
			||||||
 | 
					        gbinder_eventloop_glib_callback_check,
 | 
				
			||||||
 | 
					        gbinder_eventloop_glib_callback_dispatch
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    GBinderEventLoopCallbackGLib* impl = (GBinderEventLoopCallbackGLib*)
 | 
				
			||||||
 | 
					        g_source_new(&callback_funcs, sizeof(GBinderEventLoopCallbackGLib));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    impl->callback.eventloop = &gbinder_eventloop_glib;
 | 
				
			||||||
 | 
					    g_source_set_callback(&impl->source, (GSourceFunc) func, data, finalize);
 | 
				
			||||||
 | 
					    return &impl->callback;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_eventloop_glib_callback_ref(
 | 
				
			||||||
 | 
					    GBinderEventLoopCallback* cb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    g_source_ref(gbinder_eventloop_glib_callback_source(cb));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_eventloop_glib_callback_unref(
 | 
				
			||||||
 | 
					    GBinderEventLoopCallback* cb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    g_source_unref(gbinder_eventloop_glib_callback_source(cb));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_eventloop_glib_callback_schedule(
 | 
				
			||||||
 | 
					    GBinderEventLoopCallback* cb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static GMainContext* context = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!context) context = g_main_context_default();
 | 
				
			||||||
 | 
					    g_source_attach(gbinder_eventloop_glib_callback_source(cb), context);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_eventloop_glib_callback_cancel(
 | 
				
			||||||
 | 
					    GBinderEventLoopCallback* cb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    g_source_destroy(gbinder_eventloop_glib_callback_source(cb));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_eventloop_glib_cleanup(
 | 
				
			||||||
 | 
					    void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const GBinderEventLoopIntegration gbinder_eventloop_glib = {
 | 
				
			||||||
 | 
					    gbinder_eventloop_glib_timeout_add,
 | 
				
			||||||
 | 
					    gbinder_eventloop_glib_timeout_remove,
 | 
				
			||||||
 | 
					    gbinder_eventloop_glib_callback_new,
 | 
				
			||||||
 | 
					    gbinder_eventloop_glib_callback_ref,
 | 
				
			||||||
 | 
					    gbinder_eventloop_glib_callback_unref,
 | 
				
			||||||
 | 
					    gbinder_eventloop_glib_callback_schedule,
 | 
				
			||||||
 | 
					    gbinder_eventloop_glib_callback_cancel,
 | 
				
			||||||
 | 
					    gbinder_eventloop_glib_cleanup
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*==========================================================================*
 | 
				
			||||||
 | 
					 * Implementation
 | 
				
			||||||
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_idle_callback_invoke_proc(
 | 
				
			||||||
 | 
					    void* user_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderIdleCallbackData* idle = user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (idle->func) {
 | 
				
			||||||
 | 
					        idle->func(idle->data);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    gbinder_idle_callback_unref(idle->cb);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_idle_callback_invoke_done(
 | 
				
			||||||
 | 
					    void* user_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderIdleCallbackData* idle = user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (idle->destroy) {
 | 
				
			||||||
 | 
					        idle->destroy(idle->data);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    gutil_slice_free(idle);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*==========================================================================*
 | 
				
			||||||
 | 
					 * Internal interface
 | 
				
			||||||
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const GBinderEventLoopIntegration* gbinder_eventloop =
 | 
				
			||||||
 | 
					    GBINDER_DEFAULT_EVENTLOOP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderEventLoopTimeout*
 | 
				
			||||||
 | 
					gbinder_timeout_add(
 | 
				
			||||||
 | 
					    guint interval,
 | 
				
			||||||
 | 
					    GSourceFunc function,
 | 
				
			||||||
 | 
					    gpointer data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return gbinder_eventloop->timeout_add(interval, function, data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderEventLoopTimeout*
 | 
				
			||||||
 | 
					gbinder_idle_add(
 | 
				
			||||||
 | 
					    GSourceFunc function,
 | 
				
			||||||
 | 
					    gpointer data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return gbinder_eventloop->timeout_add(0, function, data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_timeout_remove(
 | 
				
			||||||
 | 
					    GBinderEventLoopTimeout* timeout)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (timeout) {
 | 
				
			||||||
 | 
					        timeout->eventloop->timeout_remove(timeout);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderEventLoopCallback*
 | 
				
			||||||
 | 
					gbinder_idle_callback_new(
 | 
				
			||||||
 | 
					    GBinderEventLoopCallbackFunc func,
 | 
				
			||||||
 | 
					    gpointer data,
 | 
				
			||||||
 | 
					    GDestroyNotify finalize)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return gbinder_eventloop->callback_new(func, data, finalize);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderEventLoopCallback*
 | 
				
			||||||
 | 
					gbinder_idle_callback_schedule_new(
 | 
				
			||||||
 | 
					    GBinderEventLoopCallbackFunc func,
 | 
				
			||||||
 | 
					    gpointer data,
 | 
				
			||||||
 | 
					    GDestroyNotify finalize)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderEventLoopCallback* cb =
 | 
				
			||||||
 | 
					        gbinder_eventloop->callback_new(func, data, finalize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gbinder_idle_callback_schedule(cb);
 | 
				
			||||||
 | 
					    return cb;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderEventLoopCallback*
 | 
				
			||||||
 | 
					gbinder_idle_callback_ref(
 | 
				
			||||||
 | 
					    GBinderEventLoopCallback* cb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (cb) {
 | 
				
			||||||
 | 
					        cb->eventloop->callback_ref(cb);
 | 
				
			||||||
 | 
					        return cb;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_idle_callback_unref(
 | 
				
			||||||
 | 
					    GBinderEventLoopCallback* cb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (cb) {
 | 
				
			||||||
 | 
					        cb->eventloop->callback_unref(cb);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_idle_callback_schedule(
 | 
				
			||||||
 | 
					    GBinderEventLoopCallback* cb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (cb) {
 | 
				
			||||||
 | 
					        cb->eventloop->callback_schedule(cb);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_idle_callback_cancel(
 | 
				
			||||||
 | 
					    GBinderEventLoopCallback* cb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (cb) {
 | 
				
			||||||
 | 
					        cb->eventloop->callback_cancel(cb);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_idle_callback_destroy(
 | 
				
			||||||
 | 
					    GBinderEventLoopCallback* cb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (cb) {
 | 
				
			||||||
 | 
					        const GBinderEventLoopIntegration* eventloop = cb->eventloop;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        eventloop->callback_cancel(cb);
 | 
				
			||||||
 | 
					        eventloop->callback_unref(cb);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Non-cancellable callback */
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_idle_callback_invoke_later(
 | 
				
			||||||
 | 
					    GBinderEventLoopCallbackFunc func,
 | 
				
			||||||
 | 
					    gpointer data,
 | 
				
			||||||
 | 
					    GDestroyNotify destroy)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderIdleCallbackData* idle = g_slice_new(GBinderIdleCallbackData);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    idle->func = func;
 | 
				
			||||||
 | 
					    idle->data = data;
 | 
				
			||||||
 | 
					    idle->destroy = destroy;
 | 
				
			||||||
 | 
					    idle->cb = gbinder_idle_callback_new(gbinder_idle_callback_invoke_proc,
 | 
				
			||||||
 | 
					        idle, gbinder_idle_callback_invoke_done);
 | 
				
			||||||
 | 
					    gbinder_idle_callback_schedule(idle->cb);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*==========================================================================*
 | 
				
			||||||
 | 
					 * Public interface
 | 
				
			||||||
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_eventloop_set(
 | 
				
			||||||
 | 
					    const GBinderEventLoopIntegration* loop)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (!loop) loop = GBINDER_DEFAULT_EVENTLOOP;
 | 
				
			||||||
 | 
					    if (gbinder_eventloop != loop) {
 | 
				
			||||||
 | 
					        const GBinderEventLoopIntegration* prev = gbinder_eventloop;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gbinder_eventloop = loop;
 | 
				
			||||||
 | 
					        prev->cleanup();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Local Variables:
 | 
				
			||||||
 | 
					 * mode: C
 | 
				
			||||||
 | 
					 * c-basic-offset: 4
 | 
				
			||||||
 | 
					 * indent-tabs-mode: nil
 | 
				
			||||||
 | 
					 * End:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
							
								
								
									
										115
									
								
								src/gbinder_eventloop_p.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								src/gbinder_eventloop_p.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,115 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2020-2021 Jolla Ltd.
 | 
				
			||||||
 | 
					 * Copyright (C) 2020-2021 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   1. Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 | 
					 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
				
			||||||
 | 
					 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
				
			||||||
 | 
					 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
				
			||||||
 | 
					 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
				
			||||||
 | 
					 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
				
			||||||
 | 
					 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
				
			||||||
 | 
					 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
				
			||||||
 | 
					 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
				
			||||||
 | 
					 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GBINDER_EVENTLOOP_PRIVATE_H
 | 
				
			||||||
 | 
					#define GBINDER_EVENTLOOP_PRIVATE_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "gbinder_types_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_eventloop.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderEventLoopTimeout*
 | 
				
			||||||
 | 
					gbinder_timeout_add(
 | 
				
			||||||
 | 
					    guint millis,
 | 
				
			||||||
 | 
					    GSourceFunc func,
 | 
				
			||||||
 | 
					    gpointer data)
 | 
				
			||||||
 | 
					    G_GNUC_WARN_UNUSED_RESULT
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderEventLoopTimeout*
 | 
				
			||||||
 | 
					gbinder_idle_add(
 | 
				
			||||||
 | 
					    GSourceFunc func,
 | 
				
			||||||
 | 
					    gpointer data)
 | 
				
			||||||
 | 
					    G_GNUC_WARN_UNUSED_RESULT
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_timeout_remove(
 | 
				
			||||||
 | 
					    GBinderEventLoopTimeout* timeout)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderEventLoopCallback*
 | 
				
			||||||
 | 
					gbinder_idle_callback_new(
 | 
				
			||||||
 | 
					    GBinderEventLoopCallbackFunc func,
 | 
				
			||||||
 | 
					    gpointer data,
 | 
				
			||||||
 | 
					    GDestroyNotify destroy)
 | 
				
			||||||
 | 
					    G_GNUC_WARN_UNUSED_RESULT
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderEventLoopCallback*
 | 
				
			||||||
 | 
					gbinder_idle_callback_schedule_new(
 | 
				
			||||||
 | 
					    GBinderEventLoopCallbackFunc func,
 | 
				
			||||||
 | 
					    gpointer data,
 | 
				
			||||||
 | 
					    GDestroyNotify destroy)
 | 
				
			||||||
 | 
					    G_GNUC_WARN_UNUSED_RESULT
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderEventLoopCallback*
 | 
				
			||||||
 | 
					gbinder_idle_callback_ref(
 | 
				
			||||||
 | 
					    GBinderEventLoopCallback* cb)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_idle_callback_unref(
 | 
				
			||||||
 | 
					    GBinderEventLoopCallback* cb)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_idle_callback_schedule(
 | 
				
			||||||
 | 
					    GBinderEventLoopCallback* cb)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_idle_callback_cancel(
 | 
				
			||||||
 | 
					    GBinderEventLoopCallback* cb)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_idle_callback_destroy(
 | 
				
			||||||
 | 
					    GBinderEventLoopCallback* cb)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_idle_callback_invoke_later(
 | 
				
			||||||
 | 
					    GBinderEventLoopCallbackFunc func,
 | 
				
			||||||
 | 
					    gpointer data,
 | 
				
			||||||
 | 
					    GDestroyNotify destroy)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* GBINDER_EVENTLOOP_PRIVATE_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Local Variables:
 | 
				
			||||||
 | 
					 * mode: C
 | 
				
			||||||
 | 
					 * c-basic-offset: 4
 | 
				
			||||||
 | 
					 * indent-tabs-mode: nil
 | 
				
			||||||
 | 
					 * End:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
							
								
								
									
										699
									
								
								src/gbinder_fmq.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										699
									
								
								src/gbinder_fmq.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,699 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2021 Jolla Ltd.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   1. Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 | 
					 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
				
			||||||
 | 
					 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
				
			||||||
 | 
					 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
				
			||||||
 | 
					 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
				
			||||||
 | 
					 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
				
			||||||
 | 
					 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
				
			||||||
 | 
					 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
				
			||||||
 | 
					 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
				
			||||||
 | 
					 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "gbinder_fmq_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gutil_macros.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					#include <fcntl.h>
 | 
				
			||||||
 | 
					#include <linux/futex.h>
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <sys/mman.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if GBINDER_FMQ_SUPPORTED
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Grantor data positions */
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
					    READ_PTR_POS = 0,
 | 
				
			||||||
 | 
					    WRITE_PTR_POS,
 | 
				
			||||||
 | 
					    DATA_PTR_POS,
 | 
				
			||||||
 | 
					    EVENT_FLAG_PTR_POS
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_fmq {
 | 
				
			||||||
 | 
					    GBinderMQDescriptor* desc;
 | 
				
			||||||
 | 
					    guint8* ring;
 | 
				
			||||||
 | 
					    guint64* read_ptr;
 | 
				
			||||||
 | 
					    guint64* write_ptr;
 | 
				
			||||||
 | 
					    guint32* event_flag_ptr;
 | 
				
			||||||
 | 
					    guint32 refcount;
 | 
				
			||||||
 | 
					} GBinderFmq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBINDER_INLINE_FUNC
 | 
				
			||||||
 | 
					GBinderFmqGrantorDescriptor*
 | 
				
			||||||
 | 
					gbinder_fmq_get_grantor_descriptor(
 | 
				
			||||||
 | 
					    GBinderFmq* self,
 | 
				
			||||||
 | 
					    gint index)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return (GBinderFmqGrantorDescriptor*)(self->desc->grantors.data.ptr) +
 | 
				
			||||||
 | 
					        index;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					gsize
 | 
				
			||||||
 | 
					gbinder_fmq_available_to_read_bytes(
 | 
				
			||||||
 | 
					    GBinderFmq* self,
 | 
				
			||||||
 | 
					    gboolean contiguous)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const guint64 read_ptr = __atomic_load_n(self->read_ptr, __ATOMIC_ACQUIRE);
 | 
				
			||||||
 | 
					    const gsize available_total = __atomic_load_n(self->write_ptr,
 | 
				
			||||||
 | 
					        __ATOMIC_ACQUIRE) - read_ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (contiguous) {
 | 
				
			||||||
 | 
					        /*
 | 
				
			||||||
 | 
					         * The number of bytes that can be read contiguously from
 | 
				
			||||||
 | 
					         * read offset without wrapping around the ring buffer.
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        const gsize size = gbinder_fmq_get_grantor_descriptor(self,
 | 
				
			||||||
 | 
					            DATA_PTR_POS)->extent;
 | 
				
			||||||
 | 
					        const gsize available_contiguous = size - (read_ptr % size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return (available_contiguous < available_total) ?
 | 
				
			||||||
 | 
					            available_contiguous : available_total;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        return available_total;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					gsize
 | 
				
			||||||
 | 
					gbinder_fmq_available_to_write_bytes(
 | 
				
			||||||
 | 
					    GBinderFmq* self,
 | 
				
			||||||
 | 
					    gboolean contiguous)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const guint32 size = gbinder_fmq_get_grantor_descriptor(self,
 | 
				
			||||||
 | 
					        DATA_PTR_POS)->extent;
 | 
				
			||||||
 | 
					    const gsize available_total = size -
 | 
				
			||||||
 | 
					        gbinder_fmq_available_to_read_bytes(self, FALSE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (contiguous) {
 | 
				
			||||||
 | 
					        /*
 | 
				
			||||||
 | 
					         * The number of bytes that can be written contiguously starting from
 | 
				
			||||||
 | 
					         * write_offset without wrapping around the ring buffer.
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        const guint64 write_ptr = __atomic_load_n(self->write_ptr,
 | 
				
			||||||
 | 
					            __ATOMIC_RELAXED);
 | 
				
			||||||
 | 
					        const gsize available_contiguous = size - (write_ptr % size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return (available_contiguous < available_total) ?
 | 
				
			||||||
 | 
					            available_contiguous : available_total;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        return available_total;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					GBinderFmqGrantorDescriptor*
 | 
				
			||||||
 | 
					gbinder_fmq_create_grantors(
 | 
				
			||||||
 | 
					    gsize queue_size_bytes,
 | 
				
			||||||
 | 
					    gsize num_fds,
 | 
				
			||||||
 | 
					    gboolean configure_event_flag)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const gsize num_grantors = configure_event_flag ?
 | 
				
			||||||
 | 
					        (EVENT_FLAG_PTR_POS + 1) : (DATA_PTR_POS + 1);
 | 
				
			||||||
 | 
					    GBinderFmqGrantorDescriptor* grantors =
 | 
				
			||||||
 | 
					        g_new0(GBinderFmqGrantorDescriptor, num_grantors);
 | 
				
			||||||
 | 
					    gsize pos, offset;
 | 
				
			||||||
 | 
					    gsize mem_sizes[] = {
 | 
				
			||||||
 | 
					        sizeof(guint64),  /* read pointer counter */
 | 
				
			||||||
 | 
					        sizeof(guint64),  /* write pointer counter */
 | 
				
			||||||
 | 
					        queue_size_bytes, /* data buffer */
 | 
				
			||||||
 | 
					        sizeof(guint32)   /* event flag pointer */
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (pos = 0, offset = 0; pos < num_grantors; pos++) {
 | 
				
			||||||
 | 
					        GBinderFmqGrantorDescriptor* grantor = grantors + pos;
 | 
				
			||||||
 | 
					        guint32 grantor_fd_index;
 | 
				
			||||||
 | 
					        gsize grantor_offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (pos == DATA_PTR_POS && num_fds == 2) {
 | 
				
			||||||
 | 
					            grantor_fd_index = 1;
 | 
				
			||||||
 | 
					            grantor_offset = 0;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            grantor_fd_index = 0;
 | 
				
			||||||
 | 
					            grantor_offset = offset;
 | 
				
			||||||
 | 
					            offset += mem_sizes[pos];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        grantor->fd_index = grantor_fd_index;
 | 
				
			||||||
 | 
					        grantor->offset = (guint32)G_ALIGN8(grantor_offset);
 | 
				
			||||||
 | 
					        grantor->extent = mem_sizes[pos];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return grantors;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void*
 | 
				
			||||||
 | 
					gbinder_fmq_map_grantor_descriptor(
 | 
				
			||||||
 | 
					    GBinderFmq* self,
 | 
				
			||||||
 | 
					    guint32 index)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (index < self->desc->grantors.count) {
 | 
				
			||||||
 | 
					        const GBinderFmqGrantorDescriptor* desc =
 | 
				
			||||||
 | 
					            gbinder_fmq_get_grantor_descriptor(self, index);
 | 
				
			||||||
 | 
					        /* Offset for mmap must be a multiple of PAGE_SIZE */
 | 
				
			||||||
 | 
					        const guint32 map_offset = (desc->offset & ~(getpagesize()-1));
 | 
				
			||||||
 | 
					        const guint32 map_length = desc->offset - map_offset + desc->extent;
 | 
				
			||||||
 | 
					        const GBinderFds* fds = self->desc->data.fds;
 | 
				
			||||||
 | 
					        void* address = mmap(0, map_length, PROT_READ | PROT_WRITE, MAP_SHARED,
 | 
				
			||||||
 | 
					            gbinder_fds_get_fd(fds, desc->fd_index), map_offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (address != MAP_FAILED) {
 | 
				
			||||||
 | 
					            return (guint8*)address + (desc->offset - map_offset);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            GWARN("mmap failed: %d", errno);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_fmq_unmap_grantor_descriptor(
 | 
				
			||||||
 | 
					    GBinderFmq* self,
 | 
				
			||||||
 | 
					    void* address,
 | 
				
			||||||
 | 
					    guint index)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (index < self->desc->grantors.count && address) {
 | 
				
			||||||
 | 
					        const GBinderFmqGrantorDescriptor* desc =
 | 
				
			||||||
 | 
					            gbinder_fmq_get_grantor_descriptor(self, index);
 | 
				
			||||||
 | 
					        const gsize remainder = desc->offset & (getpagesize() - 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        munmap((guint8*)address - remainder, remainder + desc->extent);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_fmq_free(
 | 
				
			||||||
 | 
					    GBinderFmq* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (self->desc) {
 | 
				
			||||||
 | 
					        if (self->desc->flags == GBINDER_FMQ_TYPE_UNSYNC_WRITE) {
 | 
				
			||||||
 | 
					            g_free(self->read_ptr);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            gbinder_fmq_unmap_grantor_descriptor(self, self->read_ptr,
 | 
				
			||||||
 | 
					                READ_PTR_POS);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        gbinder_fmq_unmap_grantor_descriptor(self, self->write_ptr,
 | 
				
			||||||
 | 
					            WRITE_PTR_POS);
 | 
				
			||||||
 | 
					        gbinder_fmq_unmap_grantor_descriptor(self, self->ring,
 | 
				
			||||||
 | 
					            DATA_PTR_POS);
 | 
				
			||||||
 | 
					        gbinder_fmq_unmap_grantor_descriptor(self, self->event_flag_ptr,
 | 
				
			||||||
 | 
					            EVENT_FLAG_PTR_POS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        g_free((GBinderFmqGrantorDescriptor*)self->desc->grantors.data.ptr);
 | 
				
			||||||
 | 
					        g_free((GBinderFds*)self->desc->data.fds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        g_free(self->desc);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    g_slice_free(GBinderFmq, self);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Private API */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderMQDescriptor*
 | 
				
			||||||
 | 
					gbinder_fmq_get_descriptor(
 | 
				
			||||||
 | 
					    const GBinderFmq* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return self->desc;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Public API */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderFmq*
 | 
				
			||||||
 | 
					gbinder_fmq_new(
 | 
				
			||||||
 | 
					    gsize item_size,
 | 
				
			||||||
 | 
					    gsize num_items,
 | 
				
			||||||
 | 
					    GBINDER_FMQ_TYPE type,
 | 
				
			||||||
 | 
					    GBINDER_FMQ_FLAGS flags,
 | 
				
			||||||
 | 
					    gint fd,
 | 
				
			||||||
 | 
					    gsize buffer_size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (item_size <= 0) {
 | 
				
			||||||
 | 
					        GWARN("Incorrect item size");
 | 
				
			||||||
 | 
					    } else if (num_items <= 0) {
 | 
				
			||||||
 | 
					        GWARN("Empty queue requested");
 | 
				
			||||||
 | 
					    } else if (num_items > SIZE_MAX / item_size) {
 | 
				
			||||||
 | 
					        GWARN("Requested message queue size too large");
 | 
				
			||||||
 | 
					    } else if (fd != -1 && num_items * item_size > buffer_size) {
 | 
				
			||||||
 | 
					        GWARN("The size needed for items (%"G_GSIZE_FORMAT") is larger "
 | 
				
			||||||
 | 
					            "than the supplied buffer size (%"G_GSIZE_FORMAT")",
 | 
				
			||||||
 | 
					            num_items * item_size, buffer_size);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        GBinderFmq* self = g_slice_new0(GBinderFmq);
 | 
				
			||||||
 | 
					        gboolean configure_event_flag =
 | 
				
			||||||
 | 
					            (flags & GBINDER_FMQ_FLAG_CONFIGURE_EVENT_FLAG) != 0;
 | 
				
			||||||
 | 
					        gsize queue_size_bytes = num_items * item_size;
 | 
				
			||||||
 | 
					        gsize meta_data_size;
 | 
				
			||||||
 | 
					        gsize shmem_size;
 | 
				
			||||||
 | 
					        int shmem_fd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        meta_data_size = 2 * sizeof(guint64);
 | 
				
			||||||
 | 
					        if (configure_event_flag) {
 | 
				
			||||||
 | 
					            meta_data_size += sizeof(guint32);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Allocate shared memory */
 | 
				
			||||||
 | 
					        if (fd != -1) {
 | 
				
			||||||
 | 
					            /* User-supplied ringbuffer memory provided,
 | 
				
			||||||
 | 
					             * allocating memory only for meta data */
 | 
				
			||||||
 | 
					            shmem_size = (meta_data_size + getpagesize() - 1) &
 | 
				
			||||||
 | 
					                ~(getpagesize() - 1);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            /* Allocate ringbuffer, read counter and write counter */
 | 
				
			||||||
 | 
					            shmem_size = (G_ALIGN8(queue_size_bytes) +
 | 
				
			||||||
 | 
					                meta_data_size + getpagesize() - 1) & ~(getpagesize() - 1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        shmem_fd = syscall(__NR_memfd_create, "MessageQueue", MFD_CLOEXEC);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (shmem_fd >= 0 && ftruncate(shmem_fd, shmem_size) == 0) {
 | 
				
			||||||
 | 
					            GBinderFmqGrantorDescriptor* grantors;
 | 
				
			||||||
 | 
					            gsize num_fds = (fd != -1) ? 2 : 1;
 | 
				
			||||||
 | 
					            gsize fds_size = sizeof(GBinderFds) + sizeof(int) * num_fds;
 | 
				
			||||||
 | 
					            GBinderFds* fds = (GBinderFds*)g_malloc0(fds_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            fds->version = fds_size;
 | 
				
			||||||
 | 
					            fds->num_fds = num_fds;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            (((int*)((fds) + 1))[0]) = shmem_fd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (fd != -1) {
 | 
				
			||||||
 | 
					                /* Use user-supplied file descriptor for fd_index 1 */
 | 
				
			||||||
 | 
					                (((int*)((fds) + 1))[1]) = fd;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            grantors = gbinder_fmq_create_grantors(queue_size_bytes,
 | 
				
			||||||
 | 
					                num_fds, configure_event_flag);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* Fill FMQ descriptor */
 | 
				
			||||||
 | 
					            self->desc = g_new0(GBinderMQDescriptor, 1);
 | 
				
			||||||
 | 
					            self->desc->data.fds = fds;
 | 
				
			||||||
 | 
					            self->desc->quantum = item_size;
 | 
				
			||||||
 | 
					            self->desc->flags = type;
 | 
				
			||||||
 | 
					            self->desc->grantors.data.ptr = grantors;
 | 
				
			||||||
 | 
					            self->desc->grantors.count = configure_event_flag ?
 | 
				
			||||||
 | 
					                (EVENT_FLAG_PTR_POS + 1) : (DATA_PTR_POS + 1);
 | 
				
			||||||
 | 
					            self->desc->grantors.owns_buffer = TRUE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* Initialize memory pointers */
 | 
				
			||||||
 | 
					            if (type == GBINDER_FMQ_TYPE_SYNC_READ_WRITE) {
 | 
				
			||||||
 | 
					                self->read_ptr = gbinder_fmq_map_grantor_descriptor(self,
 | 
				
			||||||
 | 
					                    READ_PTR_POS);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                /*
 | 
				
			||||||
 | 
					                 * Unsynchronized write FMQs may have multiple readers and
 | 
				
			||||||
 | 
					                 * each reader would have their own read pointer counter.
 | 
				
			||||||
 | 
					                 */
 | 
				
			||||||
 | 
					                self->read_ptr = g_new0(guint64, 1);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!self->read_ptr) {
 | 
				
			||||||
 | 
					                GWARN("Read pointer is null");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self->write_ptr = gbinder_fmq_map_grantor_descriptor(self,
 | 
				
			||||||
 | 
					                WRITE_PTR_POS);
 | 
				
			||||||
 | 
					            if (!self->write_ptr) {
 | 
				
			||||||
 | 
					                GWARN("Write pointer is null");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!(flags & GBINDER_FMQ_FLAG_NO_RESET_POINTERS)) {
 | 
				
			||||||
 | 
					                __atomic_store_n(self->read_ptr, 0, __ATOMIC_RELEASE);
 | 
				
			||||||
 | 
					                __atomic_store_n(self->write_ptr, 0, __ATOMIC_RELEASE);
 | 
				
			||||||
 | 
					            } else if (type != GBINDER_FMQ_TYPE_SYNC_READ_WRITE) {
 | 
				
			||||||
 | 
					                /* Always reset the read pointer */
 | 
				
			||||||
 | 
					                __atomic_store_n(self->read_ptr, 0, __ATOMIC_RELEASE);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self->ring = gbinder_fmq_map_grantor_descriptor(self,
 | 
				
			||||||
 | 
					                DATA_PTR_POS);
 | 
				
			||||||
 | 
					            if (!self->ring) {
 | 
				
			||||||
 | 
					                GWARN("Ring buffer pointer is null");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (self->desc->grantors.count > EVENT_FLAG_PTR_POS) {
 | 
				
			||||||
 | 
					                self->event_flag_ptr = gbinder_fmq_map_grantor_descriptor(self,
 | 
				
			||||||
 | 
					                    EVENT_FLAG_PTR_POS);
 | 
				
			||||||
 | 
					                if (!self->event_flag_ptr) {
 | 
				
			||||||
 | 
					                    GWARN("Event flag pointer is null");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            g_atomic_int_set(&self->refcount, 1);
 | 
				
			||||||
 | 
					            return self;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        GWARN("Failed to allocate shared memory: %s", strerror(errno));
 | 
				
			||||||
 | 
					        gbinder_fmq_free(self);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderFmq*
 | 
				
			||||||
 | 
					gbinder_fmq_ref(
 | 
				
			||||||
 | 
					    GBinderFmq* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
 | 
					        GASSERT(self->refcount > 0);
 | 
				
			||||||
 | 
					        g_atomic_int_inc(&self->refcount);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return self;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_fmq_unref(
 | 
				
			||||||
 | 
					    GBinderFmq* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
 | 
					        GASSERT(self->refcount > 0);
 | 
				
			||||||
 | 
					        if (g_atomic_int_dec_and_test(&self->refcount)) {
 | 
				
			||||||
 | 
					            gbinder_fmq_free(self);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gsize
 | 
				
			||||||
 | 
					gbinder_fmq_available_to_read(
 | 
				
			||||||
 | 
					    GBinderFmq* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return G_LIKELY(self) ? (gbinder_fmq_available_to_read_bytes(self, FALSE) /
 | 
				
			||||||
 | 
					        self->desc->quantum) : 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gsize
 | 
				
			||||||
 | 
					gbinder_fmq_available_to_write(
 | 
				
			||||||
 | 
					    GBinderFmq* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return G_LIKELY(self) ? (gbinder_fmq_available_to_write_bytes(self, FALSE) /
 | 
				
			||||||
 | 
					        self->desc->quantum) : 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gsize
 | 
				
			||||||
 | 
					gbinder_fmq_available_to_read_contiguous(
 | 
				
			||||||
 | 
					    GBinderFmq* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return G_LIKELY(self) ? (gbinder_fmq_available_to_read_bytes(self, TRUE) /
 | 
				
			||||||
 | 
					        self->desc->quantum) : 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gsize
 | 
				
			||||||
 | 
					gbinder_fmq_available_to_write_contiguous(
 | 
				
			||||||
 | 
					    GBinderFmq* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return G_LIKELY(self) ? (gbinder_fmq_available_to_write_bytes(self, TRUE) /
 | 
				
			||||||
 | 
					        self->desc->quantum) : 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const void*
 | 
				
			||||||
 | 
					gbinder_fmq_begin_read(
 | 
				
			||||||
 | 
					    GBinderFmq* self,
 | 
				
			||||||
 | 
					    gsize items)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    void* ptr = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (G_LIKELY(self) && G_LIKELY(items > 0)) {
 | 
				
			||||||
 | 
					        gsize size = gbinder_fmq_get_grantor_descriptor(self,
 | 
				
			||||||
 | 
					            DATA_PTR_POS)->extent;
 | 
				
			||||||
 | 
					        gsize item_size = self->desc->quantum;
 | 
				
			||||||
 | 
					        gsize bytes_desired = items * item_size;
 | 
				
			||||||
 | 
					        guint64 write_ptr = __atomic_load_n(self->write_ptr, __ATOMIC_ACQUIRE);
 | 
				
			||||||
 | 
					        guint64 read_ptr = __atomic_load_n(self->read_ptr, __ATOMIC_RELAXED);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ((write_ptr % item_size) || (read_ptr % item_size)) {
 | 
				
			||||||
 | 
					            GWARN("Unable to write data because of misaligned pointer");
 | 
				
			||||||
 | 
					        } else if (write_ptr - read_ptr > size) {
 | 
				
			||||||
 | 
					            __atomic_store_n(self->read_ptr, write_ptr, __ATOMIC_RELEASE);
 | 
				
			||||||
 | 
					        } else if (write_ptr - read_ptr < bytes_desired) {
 | 
				
			||||||
 | 
					            /* Not enough data to read in FMQ. */
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            ptr = self->ring + (read_ptr % size);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void*
 | 
				
			||||||
 | 
					gbinder_fmq_begin_write(
 | 
				
			||||||
 | 
					    GBinderFmq* self,
 | 
				
			||||||
 | 
					    gsize items)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    void* ptr = NULL;
 | 
				
			||||||
 | 
					    if (G_LIKELY(self) && G_LIKELY(items > 0)) {
 | 
				
			||||||
 | 
					        const gsize item_size = self->desc->quantum;
 | 
				
			||||||
 | 
					        const gsize size = gbinder_fmq_get_grantor_descriptor(self,
 | 
				
			||||||
 | 
					            DATA_PTR_POS)->extent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ((self->desc->flags == GBINDER_FMQ_TYPE_SYNC_READ_WRITE &&
 | 
				
			||||||
 | 
					            (gbinder_fmq_available_to_write(self) < items)) ||
 | 
				
			||||||
 | 
					            items > size / item_size) {
 | 
				
			||||||
 | 
					            /* Incorrect parameters */
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            guint64 write_ptr = __atomic_load_n(self->write_ptr,
 | 
				
			||||||
 | 
					                __ATOMIC_RELAXED);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (write_ptr % item_size) {
 | 
				
			||||||
 | 
					                GWARN("The write pointer has become misaligned.");
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                ptr = self->ring + (write_ptr % size);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return ptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_fmq_end_read(
 | 
				
			||||||
 | 
					    GBinderFmq* self,
 | 
				
			||||||
 | 
					    gsize items)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (G_LIKELY(self) && G_LIKELY(items > 0)) {
 | 
				
			||||||
 | 
					        gsize size = gbinder_fmq_get_grantor_descriptor(self,
 | 
				
			||||||
 | 
					            DATA_PTR_POS)->extent;
 | 
				
			||||||
 | 
					        guint64 read_ptr = __atomic_load_n(self->read_ptr, __ATOMIC_RELAXED);
 | 
				
			||||||
 | 
					        guint64 write_ptr = __atomic_load_n(self->write_ptr, __ATOMIC_ACQUIRE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /*
 | 
				
			||||||
 | 
					         * If queue type is unsynchronized, it is possible that a write
 | 
				
			||||||
 | 
					         * overflow may have occurred.
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        if (write_ptr - read_ptr > size) {
 | 
				
			||||||
 | 
					            __atomic_store_n(self->read_ptr, write_ptr, __ATOMIC_RELEASE);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            read_ptr += items * self->desc->quantum;
 | 
				
			||||||
 | 
					            __atomic_store_n(self->read_ptr, read_ptr, __ATOMIC_RELEASE);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_fmq_end_write(
 | 
				
			||||||
 | 
					    GBinderFmq* self,
 | 
				
			||||||
 | 
					    gsize items)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (G_LIKELY(self) && G_LIKELY(items > 0)) {
 | 
				
			||||||
 | 
					        guint64 write_ptr = __atomic_load_n(self->write_ptr, __ATOMIC_RELAXED);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        write_ptr += items * self->desc->quantum;
 | 
				
			||||||
 | 
					        __atomic_store_n(self->write_ptr, write_ptr, __ATOMIC_RELEASE);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_fmq_read(
 | 
				
			||||||
 | 
					    GBinderFmq* self,
 | 
				
			||||||
 | 
					    void* data,
 | 
				
			||||||
 | 
					    gsize items)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (G_LIKELY(self) && G_LIKELY(data) && G_LIKELY(items > 0)) {
 | 
				
			||||||
 | 
					        const void* in_data = gbinder_fmq_begin_read(self, items);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (in_data) {
 | 
				
			||||||
 | 
					            /*
 | 
				
			||||||
 | 
					             * The number of messages that can be read contiguously without
 | 
				
			||||||
 | 
					             * wrapping around the ring buffer.
 | 
				
			||||||
 | 
					             */
 | 
				
			||||||
 | 
					            const gsize contiguous_messages =
 | 
				
			||||||
 | 
					                gbinder_fmq_available_to_read_contiguous(self);
 | 
				
			||||||
 | 
					            const gsize item_size = self->desc->quantum;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (contiguous_messages < items) {
 | 
				
			||||||
 | 
					                /* A wrap around is required */
 | 
				
			||||||
 | 
					                memcpy(data, in_data, contiguous_messages * item_size);
 | 
				
			||||||
 | 
					                memcpy((char*)data + contiguous_messages * item_size,
 | 
				
			||||||
 | 
					                    self->ring, (items - contiguous_messages) * item_size);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                /* A wrap around is not required */
 | 
				
			||||||
 | 
					                memcpy(data, in_data, items * item_size);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            gbinder_fmq_end_read(self, items);
 | 
				
			||||||
 | 
					            return TRUE;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return FALSE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_fmq_write(
 | 
				
			||||||
 | 
					    GBinderFmq* self,
 | 
				
			||||||
 | 
					    const void* data,
 | 
				
			||||||
 | 
					    gsize items)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (G_LIKELY(self) && G_LIKELY(data) && G_LIKELY(items > 0)) {
 | 
				
			||||||
 | 
					        void *out_data = gbinder_fmq_begin_write(self, items);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (out_data) {
 | 
				
			||||||
 | 
					            /*
 | 
				
			||||||
 | 
					             * The number of messages that can be written contiguously without
 | 
				
			||||||
 | 
					             * wrapping around the ring buffer.
 | 
				
			||||||
 | 
					             */
 | 
				
			||||||
 | 
					            const gsize contiguous_messages =
 | 
				
			||||||
 | 
					                gbinder_fmq_available_to_write_contiguous(self);
 | 
				
			||||||
 | 
					            const gsize item_size = self->desc->quantum;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (contiguous_messages < items) {
 | 
				
			||||||
 | 
					                /* A wrap around is required. */
 | 
				
			||||||
 | 
					                memcpy(out_data, data, contiguous_messages * item_size);
 | 
				
			||||||
 | 
					                memcpy(self->ring, (char *)data + contiguous_messages *
 | 
				
			||||||
 | 
					                    item_size / sizeof(char),
 | 
				
			||||||
 | 
					                    (items - contiguous_messages) * item_size);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                /* A wrap around is not required to write items */
 | 
				
			||||||
 | 
					                memcpy(out_data, data, items * item_size);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            gbinder_fmq_end_write(self, items);
 | 
				
			||||||
 | 
					            return TRUE;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return FALSE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					gbinder_fmq_wait_timeout(
 | 
				
			||||||
 | 
					    GBinderFmq* self,
 | 
				
			||||||
 | 
					    guint32 bit_mask,
 | 
				
			||||||
 | 
					    guint32* state,
 | 
				
			||||||
 | 
					    int timeout_ms)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (G_UNLIKELY(!state) || G_UNLIKELY(!self)) {
 | 
				
			||||||
 | 
					        return (-EINVAL);
 | 
				
			||||||
 | 
					    } else if (!self->event_flag_ptr) {
 | 
				
			||||||
 | 
					        return (-ENOSYS);
 | 
				
			||||||
 | 
					    } else if (!bit_mask) {
 | 
				
			||||||
 | 
					        return (-EINVAL);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        guint32 old_value = __atomic_fetch_and(self->event_flag_ptr, ~bit_mask,
 | 
				
			||||||
 | 
					            __ATOMIC_SEQ_CST);
 | 
				
			||||||
 | 
					        guint32 set_bits = old_value & bit_mask;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Check if any of the bits was already set */
 | 
				
			||||||
 | 
					        if (set_bits != 0) {
 | 
				
			||||||
 | 
					            *state = set_bits;
 | 
				
			||||||
 | 
					            return 0;
 | 
				
			||||||
 | 
					        } else if (!timeout_ms) {
 | 
				
			||||||
 | 
					            return (-ETIMEDOUT);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (timeout_ms > 0) {
 | 
				
			||||||
 | 
					                struct timespec deadline;
 | 
				
			||||||
 | 
					                const guint64 ms = 1000000;
 | 
				
			||||||
 | 
					                const guint64 sec = 1000 * ms;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                clock_gettime(CLOCK_MONOTONIC, &deadline);
 | 
				
			||||||
 | 
					                deadline.tv_sec += timeout_ms / 1000;
 | 
				
			||||||
 | 
					                deadline.tv_nsec += (timeout_ms % 1000) * ms;
 | 
				
			||||||
 | 
					                if (deadline.tv_nsec >= sec) {
 | 
				
			||||||
 | 
					                    deadline.tv_sec++;
 | 
				
			||||||
 | 
					                    deadline.tv_nsec -= sec;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                ret = syscall(__NR_futex, self->event_flag_ptr,
 | 
				
			||||||
 | 
					                    FUTEX_WAIT_BITSET, old_value, &deadline, NULL, bit_mask);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                ret = syscall(__NR_futex, self->event_flag_ptr,
 | 
				
			||||||
 | 
					                    FUTEX_WAIT_BITSET, old_value, NULL, NULL, bit_mask);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (ret == -1) {
 | 
				
			||||||
 | 
					                return errno ? (-errno) : -EFAULT;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                old_value = __atomic_fetch_and(self->event_flag_ptr, ~bit_mask,
 | 
				
			||||||
 | 
					                    __ATOMIC_SEQ_CST);
 | 
				
			||||||
 | 
					                *state = old_value & bit_mask;
 | 
				
			||||||
 | 
					                return (*state) ? 0 : (-EAGAIN);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					gbinder_fmq_wake(
 | 
				
			||||||
 | 
					    GBinderFmq* self,
 | 
				
			||||||
 | 
					    guint32 bit_mask)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int ret = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
 | 
					        if (!self->event_flag_ptr) {
 | 
				
			||||||
 | 
					            /* Event flag is not configured */
 | 
				
			||||||
 | 
					            ret = -ENOSYS;
 | 
				
			||||||
 | 
					        } else if (!bit_mask) {
 | 
				
			||||||
 | 
					            /* Ignore zero bit mask */
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            /* Set bit mask only if needed */
 | 
				
			||||||
 | 
					            guint32 old_value = __atomic_fetch_or(self->event_flag_ptr,
 | 
				
			||||||
 | 
					                bit_mask, __ATOMIC_SEQ_CST);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (~old_value & bit_mask) {
 | 
				
			||||||
 | 
					                ret = syscall(__NR_futex, self->event_flag_ptr,
 | 
				
			||||||
 | 
					                    FUTEX_WAKE_BITSET, G_MAXUINT32, NULL, NULL, bit_mask);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (ret == -1) {
 | 
				
			||||||
 | 
					                /* Report error code */
 | 
				
			||||||
 | 
					                ret = -errno;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        ret = -EINVAL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#else /* !GBINDER_FMQ_SUPPORTED */
 | 
				
			||||||
 | 
					#pragma message("Not compiling FMQ")
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Local Variables:
 | 
				
			||||||
 | 
					 * mode: C
 | 
				
			||||||
 | 
					 * c-basic-offset: 4
 | 
				
			||||||
 | 
					 * indent-tabs-mode: nil
 | 
				
			||||||
 | 
					 * End:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
							
								
								
									
										102
									
								
								src/gbinder_fmq_p.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								src/gbinder_fmq_p.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,102 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2021 Jolla Ltd.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   1. Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 | 
					 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
				
			||||||
 | 
					 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
				
			||||||
 | 
					 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
				
			||||||
 | 
					 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
				
			||||||
 | 
					 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
				
			||||||
 | 
					 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
				
			||||||
 | 
					 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
				
			||||||
 | 
					 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
				
			||||||
 | 
					 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GBINDER_FMQ_PRIVATE_H
 | 
				
			||||||
 | 
					#define GBINDER_FMQ_PRIVATE_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gbinder_fmq.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "gbinder_types_p.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* FMQ functionality requires __NR_memfd_create syscall */
 | 
				
			||||||
 | 
					#include <sys/syscall.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __NR_memfd_create
 | 
				
			||||||
 | 
					#  define GBINDER_FMQ_SUPPORTED 1
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#  define GBINDER_FMQ_SUPPORTED 0
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * From linux/memfd.h
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#ifndef MFD_CLOEXEC
 | 
				
			||||||
 | 
					#  define MFD_CLOEXEC 0x0001U
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * FMQ types
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef struct gbinder_fmq_grantor_descriptor {
 | 
				
			||||||
 | 
					    guint32 flags GBINDER_ALIGNED(4);
 | 
				
			||||||
 | 
					    guint32 fd_index GBINDER_ALIGNED(4);
 | 
				
			||||||
 | 
					    guint32 offset GBINDER_ALIGNED(4);
 | 
				
			||||||
 | 
					    guint64 extent GBINDER_ALIGNED(8);
 | 
				
			||||||
 | 
					} GBinderFmqGrantorDescriptor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					G_STATIC_ASSERT(G_STRUCT_OFFSET(GBinderFmqGrantorDescriptor, flags) == 0);
 | 
				
			||||||
 | 
					G_STATIC_ASSERT(G_STRUCT_OFFSET(GBinderFmqGrantorDescriptor, fd_index) == 4);
 | 
				
			||||||
 | 
					G_STATIC_ASSERT(G_STRUCT_OFFSET(GBinderFmqGrantorDescriptor, offset) == 8);
 | 
				
			||||||
 | 
					G_STATIC_ASSERT(G_STRUCT_OFFSET(GBinderFmqGrantorDescriptor, extent) == 16);
 | 
				
			||||||
 | 
					G_STATIC_ASSERT(sizeof(GBinderFmqGrantorDescriptor) == 24);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_mq_descriptor {
 | 
				
			||||||
 | 
					    GBinderHidlVec grantors;
 | 
				
			||||||
 | 
					    union {
 | 
				
			||||||
 | 
					        guint64 value;
 | 
				
			||||||
 | 
					        const GBinderFds* fds;
 | 
				
			||||||
 | 
					    } data;
 | 
				
			||||||
 | 
					    guint32 quantum;
 | 
				
			||||||
 | 
					    guint32 flags;
 | 
				
			||||||
 | 
					} GBinderMQDescriptor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define GBINDER_MQ_DESCRIPTOR_GRANTORS_OFFSET (0)
 | 
				
			||||||
 | 
					#define GBINDER_MQ_DESCRIPTOR_FDS_OFFSET (16)
 | 
				
			||||||
 | 
					G_STATIC_ASSERT(G_STRUCT_OFFSET(GBinderMQDescriptor, grantors) ==
 | 
				
			||||||
 | 
					    GBINDER_MQ_DESCRIPTOR_GRANTORS_OFFSET);
 | 
				
			||||||
 | 
					G_STATIC_ASSERT(G_STRUCT_OFFSET(GBinderMQDescriptor, data) ==
 | 
				
			||||||
 | 
					    GBINDER_MQ_DESCRIPTOR_FDS_OFFSET);
 | 
				
			||||||
 | 
					G_STATIC_ASSERT(sizeof(GBinderMQDescriptor) == 32);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderMQDescriptor*
 | 
				
			||||||
 | 
					gbinder_fmq_get_descriptor(
 | 
				
			||||||
 | 
					    const GBinderFmq* self)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* GBINDER_FMQ_PRIVATE_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Local Variables:
 | 
				
			||||||
 | 
					 * mode: C
 | 
				
			||||||
 | 
					 * c-basic-offset: 4
 | 
				
			||||||
 | 
					 * indent-tabs-mode: nil
 | 
				
			||||||
 | 
					 * End:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2020 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -36,6 +36,7 @@
 | 
				
			|||||||
#include "gbinder_types_p.h"
 | 
					#include "gbinder_types_p.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct gbinder_handler_functions {
 | 
					typedef struct gbinder_handler_functions {
 | 
				
			||||||
 | 
					    gboolean (*can_loop)(GBinderHandler* handler);
 | 
				
			||||||
    GBinderLocalReply* (*transact)(GBinderHandler* handler,
 | 
					    GBinderLocalReply* (*transact)(GBinderHandler* handler,
 | 
				
			||||||
        GBinderLocalObject* obj, GBinderRemoteRequest* req, guint code,
 | 
					        GBinderLocalObject* obj, GBinderRemoteRequest* req, guint code,
 | 
				
			||||||
        guint flags, int* status);
 | 
					        guint flags, int* status);
 | 
				
			||||||
@@ -47,6 +48,14 @@ struct gbinder_handler {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* Inline wrappers */
 | 
					/* Inline wrappers */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBINDER_INLINE_FUNC
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_handler_can_loop(
 | 
				
			||||||
 | 
					    GBinderHandler* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return self && self->f->can_loop && self->f->can_loop(self);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBINDER_INLINE_FUNC
 | 
					GBINDER_INLINE_FUNC
 | 
				
			||||||
GBinderLocalReply*
 | 
					GBinderLocalReply*
 | 
				
			||||||
gbinder_handler_transact(
 | 
					gbinder_handler_transact(
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,199 +0,0 @@
 | 
				
			|||||||
/*
 | 
					 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Redistribution and use in source and binary forms, with or without
 | 
					 | 
				
			||||||
 * modification, are permitted provided that the following conditions
 | 
					 | 
				
			||||||
 * are met:
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *   1. Redistributions of source code must retain the above copyright
 | 
					 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer.
 | 
					 | 
				
			||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 | 
				
			||||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
					 | 
				
			||||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
					 | 
				
			||||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
					 | 
				
			||||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
					 | 
				
			||||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
					 | 
				
			||||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
					 | 
				
			||||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
					 | 
				
			||||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
					 | 
				
			||||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "gbinder_servicemanager_p.h"
 | 
					 | 
				
			||||||
#include "gbinder_log.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <gbinder_client.h>
 | 
					 | 
				
			||||||
#include <gbinder_local_request.h>
 | 
					 | 
				
			||||||
#include <gbinder_remote_reply.h>
 | 
					 | 
				
			||||||
#include <gbinder_reader.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <errno.h>
 | 
					 | 
				
			||||||
#include <pthread.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef GBinderServiceManager GBinderHwServiceManager;
 | 
					 | 
				
			||||||
typedef GBinderServiceManagerClass GBinderHwServiceManagerClass;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
G_DEFINE_TYPE(GBinderHwServiceManager,
 | 
					 | 
				
			||||||
    gbinder_hwservicemanager,
 | 
					 | 
				
			||||||
    GBINDER_TYPE_SERVICEMANAGER)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum gbinder_hwservicemanager_calls {
 | 
					 | 
				
			||||||
    GET_TRANSACTION = GBINDER_FIRST_CALL_TRANSACTION,
 | 
					 | 
				
			||||||
    ADD_TRANSACTION,
 | 
					 | 
				
			||||||
    GET_TRANSPORT_TRANSACTION,
 | 
					 | 
				
			||||||
    LIST_TRANSACTION,
 | 
					 | 
				
			||||||
    LIST_BY_INTERFACE_TRANSACTION,
 | 
					 | 
				
			||||||
    REGISTER_FOR_NOTIFICATIONS_TRANSACTION,
 | 
					 | 
				
			||||||
    DEBUG_DUMP_TRANSACTION,
 | 
					 | 
				
			||||||
    REGISTER_PASSTHROUGH_CLIENT_TRANSACTION
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* As a special case, ServiceManager's handle is zero */
 | 
					 | 
				
			||||||
#define HWSERVICEMANAGER_HANDLE (0)
 | 
					 | 
				
			||||||
#define HWSERVICEMANAGER_IFACE  "android.hidl.manager@1.0::IServiceManager"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
GBinderServiceManager*
 | 
					 | 
				
			||||||
gbinder_hwservicemanager_new(
 | 
					 | 
				
			||||||
    const char* dev)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    return gbinder_servicemanager_new_with_type
 | 
					 | 
				
			||||||
        (gbinder_hwservicemanager_get_type(), dev);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static
 | 
					 | 
				
			||||||
char**
 | 
					 | 
				
			||||||
gbinder_hwservicemanager_list(
 | 
					 | 
				
			||||||
    GBinderHwServiceManager* self)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    GBinderLocalRequest* req = gbinder_client_new_request(self->client);
 | 
					 | 
				
			||||||
    GBinderRemoteReply* reply = gbinder_client_transact_sync_reply
 | 
					 | 
				
			||||||
        (self->client, LIST_TRANSACTION, req, NULL);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    gbinder_local_request_unref(req);
 | 
					 | 
				
			||||||
    if (reply) {
 | 
					 | 
				
			||||||
        GBinderReader reader;
 | 
					 | 
				
			||||||
        char** result = NULL;
 | 
					 | 
				
			||||||
        int status = -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        gbinder_remote_reply_init_reader(reply, &reader);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /* Read status */
 | 
					 | 
				
			||||||
        GVERIFY(gbinder_reader_read_int32(&reader, &status));
 | 
					 | 
				
			||||||
        GASSERT(status == GBINDER_STATUS_OK);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /* Followed by hidl_vec<string> */
 | 
					 | 
				
			||||||
        result = gbinder_reader_read_hidl_string_vec(&reader);
 | 
					 | 
				
			||||||
        gbinder_remote_reply_unref(reply);
 | 
					 | 
				
			||||||
        return result;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return NULL;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static
 | 
					 | 
				
			||||||
GBinderRemoteObject*
 | 
					 | 
				
			||||||
gbinder_hwservicemanager_get_service(
 | 
					 | 
				
			||||||
    GBinderServiceManager* self,
 | 
					 | 
				
			||||||
    const char* fqinstance,
 | 
					 | 
				
			||||||
    int* status)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    /* e.g. "android.hardware.radio@1.1::IRadio/slot1" */
 | 
					 | 
				
			||||||
    const char* sep = strchr(fqinstance, '/');
 | 
					 | 
				
			||||||
    GBinderRemoteObject* obj = NULL;
 | 
					 | 
				
			||||||
    if (sep) {
 | 
					 | 
				
			||||||
        GBinderRemoteReply* reply;
 | 
					 | 
				
			||||||
        GBinderLocalRequest* req = gbinder_client_new_request(self->client);
 | 
					 | 
				
			||||||
        char* fqname = g_strndup(fqinstance, sep - fqinstance);
 | 
					 | 
				
			||||||
        const char* name = sep + 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        gbinder_local_request_append_hidl_string(req, fqname);
 | 
					 | 
				
			||||||
        gbinder_local_request_append_hidl_string(req, name);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        reply = gbinder_client_transact_sync_reply(self->client,
 | 
					 | 
				
			||||||
            GET_TRANSACTION, req, status);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (reply) {
 | 
					 | 
				
			||||||
            GBinderReader reader;
 | 
					 | 
				
			||||||
            int status = -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            gbinder_remote_reply_init_reader(reply, &reader);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            /* Read status */
 | 
					 | 
				
			||||||
            GVERIFY(gbinder_reader_read_int32(&reader, &status));
 | 
					 | 
				
			||||||
            GASSERT(status == GBINDER_STATUS_OK);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            /* Read the object */
 | 
					 | 
				
			||||||
            obj = gbinder_reader_read_object(&reader);
 | 
					 | 
				
			||||||
            gbinder_remote_reply_unref(reply);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        gbinder_local_request_unref(req);
 | 
					 | 
				
			||||||
        g_free(fqname);
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        GERR("Invalid instance \"%s\"", fqinstance);
 | 
					 | 
				
			||||||
        if (status) *status = (-EINVAL);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return obj;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
gbinder_hwservicemanager_add_service(
 | 
					 | 
				
			||||||
    GBinderServiceManager* self,
 | 
					 | 
				
			||||||
    const char* name,
 | 
					 | 
				
			||||||
    GBinderLocalObject* obj)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    int status;
 | 
					 | 
				
			||||||
    GBinderRemoteReply* reply;
 | 
					 | 
				
			||||||
    GBinderLocalRequest* req = gbinder_client_new_request(self->client);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* add(string name, interface service) generates (bool success); */
 | 
					 | 
				
			||||||
    gbinder_local_request_append_hidl_string(req, name);
 | 
					 | 
				
			||||||
    gbinder_local_request_append_local_object(req, obj);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    reply = gbinder_client_transact_sync_reply(self->client,
 | 
					 | 
				
			||||||
        ADD_TRANSACTION, req, &status);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    gbinder_remote_reply_unref(reply);
 | 
					 | 
				
			||||||
    gbinder_local_request_unref(req);
 | 
					 | 
				
			||||||
    return status;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
gbinder_hwservicemanager_init(
 | 
					 | 
				
			||||||
    GBinderHwServiceManager* self)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
gbinder_hwservicemanager_class_init(
 | 
					 | 
				
			||||||
    GBinderHwServiceManagerClass* klass)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    klass->handle = HWSERVICEMANAGER_HANDLE;
 | 
					 | 
				
			||||||
    klass->iface = HWSERVICEMANAGER_IFACE;
 | 
					 | 
				
			||||||
    klass->default_device = GBINDER_DEFAULT_HWBINDER;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    klass->list = gbinder_hwservicemanager_list;
 | 
					 | 
				
			||||||
    klass->get_service = gbinder_hwservicemanager_get_service;
 | 
					 | 
				
			||||||
    klass->add_service = gbinder_hwservicemanager_add_service;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Local Variables:
 | 
					 | 
				
			||||||
 * mode: C
 | 
					 | 
				
			||||||
 * c-basic-offset: 4
 | 
					 | 
				
			||||||
 * indent-tabs-mode: nil
 | 
					 | 
				
			||||||
 * End:
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
							
								
								
									
										287
									
								
								src/gbinder_io.c
									
									
									
									
									
								
							
							
						
						
									
										287
									
								
								src/gbinder_io.c
									
									
									
									
									
								
							@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived from
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -35,6 +35,7 @@
 | 
				
			|||||||
#include "gbinder_local_object_p.h"
 | 
					#include "gbinder_local_object_p.h"
 | 
				
			||||||
#include "gbinder_remote_object_p.h"
 | 
					#include "gbinder_remote_object_p.h"
 | 
				
			||||||
#include "gbinder_object_registry.h"
 | 
					#include "gbinder_object_registry.h"
 | 
				
			||||||
 | 
					#include "gbinder_rpc_protocol.h"
 | 
				
			||||||
#include "gbinder_writer.h"
 | 
					#include "gbinder_writer.h"
 | 
				
			||||||
#include "gbinder_system.h"
 | 
					#include "gbinder_system.h"
 | 
				
			||||||
#include "gbinder_log.h"
 | 
					#include "gbinder_log.h"
 | 
				
			||||||
@@ -90,6 +91,53 @@ GBINDER_IO_FN(write_read)(
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Returns size of the object */
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					gsize
 | 
				
			||||||
 | 
					GBINDER_IO_FN(object_size)(
 | 
				
			||||||
 | 
					    const void* obj,
 | 
				
			||||||
 | 
					    const GBinderRpcProtocol* protocol)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (obj) {
 | 
				
			||||||
 | 
					        const struct binder_object_header* hdr = obj;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        switch (hdr->type) {
 | 
				
			||||||
 | 
					        case BINDER_TYPE_BINDER:
 | 
				
			||||||
 | 
					        case BINDER_TYPE_WEAK_BINDER:
 | 
				
			||||||
 | 
					        case BINDER_TYPE_HANDLE:
 | 
				
			||||||
 | 
					        case BINDER_TYPE_WEAK_HANDLE:
 | 
				
			||||||
 | 
					            return sizeof(struct flat_binder_object) +
 | 
				
			||||||
 | 
					                protocol->flat_binder_object_extra;
 | 
				
			||||||
 | 
					        case BINDER_TYPE_FD:
 | 
				
			||||||
 | 
					            return sizeof(struct binder_fd_object);
 | 
				
			||||||
 | 
					        case BINDER_TYPE_FDA:
 | 
				
			||||||
 | 
					            return sizeof(struct binder_fd_array_object);
 | 
				
			||||||
 | 
					        case BINDER_TYPE_PTR:
 | 
				
			||||||
 | 
					            return sizeof(struct binder_buffer_object);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Returns size of the object's extra data */
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					gsize
 | 
				
			||||||
 | 
					GBINDER_IO_FN(object_data_size)(
 | 
				
			||||||
 | 
					    const void* obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (obj) {
 | 
				
			||||||
 | 
					        const struct binder_object_header* hdr = obj;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        switch (hdr->type) {
 | 
				
			||||||
 | 
					        case BINDER_TYPE_PTR:
 | 
				
			||||||
 | 
					            return ((struct binder_buffer_object*)obj)->length;
 | 
				
			||||||
 | 
					        case BINDER_TYPE_FDA:
 | 
				
			||||||
 | 
					            return ((struct binder_fd_array_object*)obj)->num_fds * 4;
 | 
				
			||||||
 | 
					       }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Writes pointer to the buffer */
 | 
					/* Writes pointer to the buffer */
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
guint
 | 
					guint
 | 
				
			||||||
@@ -103,20 +151,41 @@ GBINDER_IO_FN(encode_pointer)(
 | 
				
			|||||||
    return sizeof(*dest);
 | 
					    return sizeof(*dest);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Encodes flat_buffer_object */
 | 
					/* Writes cookie to the buffer */
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					guint
 | 
				
			||||||
 | 
					GBINDER_IO_FN(encode_cookie)(
 | 
				
			||||||
 | 
					    void* out,
 | 
				
			||||||
 | 
					    guint64 cookie)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    binder_uintptr_t* dest = out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    *dest = (uintptr_t)cookie;
 | 
				
			||||||
 | 
					    return sizeof(*dest);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Encodes flat_binder_object */
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
guint
 | 
					guint
 | 
				
			||||||
GBINDER_IO_FN(encode_local_object)(
 | 
					GBINDER_IO_FN(encode_local_object)(
 | 
				
			||||||
    void* out,
 | 
					    void* out,
 | 
				
			||||||
    GBinderLocalObject* obj)
 | 
					    GBinderLocalObject* obj,
 | 
				
			||||||
 | 
					    const GBinderRpcProtocol* protocol)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    struct flat_binder_object* dest = out;
 | 
					    struct flat_binder_object* dest = out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    memset(dest, 0, sizeof(*dest));
 | 
					    memset(dest, 0, sizeof(*dest));
 | 
				
			||||||
    dest->hdr.type = BINDER_TYPE_BINDER;
 | 
					    dest->hdr.type = BINDER_TYPE_BINDER;
 | 
				
			||||||
    dest->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
 | 
					    if (obj) {
 | 
				
			||||||
    dest->binder = (uintptr_t)obj;
 | 
					        dest->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
 | 
				
			||||||
    return sizeof(*dest);
 | 
					        dest->binder = (uintptr_t)obj;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (protocol->finish_flatten_binder) {
 | 
				
			||||||
 | 
					        protocol->finish_flatten_binder(dest + 1, obj);
 | 
				
			||||||
 | 
					    } else if (protocol->flat_binder_object_extra) {
 | 
				
			||||||
 | 
					        memset(dest + 1, 0, protocol->flat_binder_object_extra);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return sizeof(*dest) + protocol->flat_binder_object_extra;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
@@ -138,6 +207,38 @@ GBINDER_IO_FN(encode_remote_object)(
 | 
				
			|||||||
    return sizeof(*dest);
 | 
					    return sizeof(*dest);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					guint
 | 
				
			||||||
 | 
					GBINDER_IO_FN(encode_fd_object)(
 | 
				
			||||||
 | 
					    void* out,
 | 
				
			||||||
 | 
					    int fd)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct binder_fd_object* dest = out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    memset(dest, 0, sizeof(*dest));
 | 
				
			||||||
 | 
					    dest->hdr.type = BINDER_TYPE_FD;
 | 
				
			||||||
 | 
					    dest->pad_flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
 | 
				
			||||||
 | 
					    dest->fd = fd;
 | 
				
			||||||
 | 
					    return sizeof(*dest);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					guint
 | 
				
			||||||
 | 
					GBINDER_IO_FN(encode_fda_object)(
 | 
				
			||||||
 | 
					    void* out,
 | 
				
			||||||
 | 
					    const GBinderFds *fds,
 | 
				
			||||||
 | 
					    const GBinderParent* parent)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct binder_fd_array_object* dest = out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    memset(dest, 0, sizeof(*dest));
 | 
				
			||||||
 | 
					    dest->hdr.type = BINDER_TYPE_FDA;
 | 
				
			||||||
 | 
					    dest->num_fds = fds->num_fds;
 | 
				
			||||||
 | 
					    dest->parent = parent->index;
 | 
				
			||||||
 | 
					    dest->parent_offset = parent->offset;
 | 
				
			||||||
 | 
					    return sizeof(*dest);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Encodes binder_buffer_object */
 | 
					/* Encodes binder_buffer_object */
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
guint
 | 
					guint
 | 
				
			||||||
@@ -163,7 +264,7 @@ GBINDER_IO_FN(encode_buffer_object)(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
guint
 | 
					guint
 | 
				
			||||||
GBINDER_IO_FN(encode_death_notification)(
 | 
					GBINDER_IO_FN(encode_handle_cookie)(
 | 
				
			||||||
    void* out,
 | 
					    void* out,
 | 
				
			||||||
    GBinderRemoteObject* obj)
 | 
					    GBinderRemoteObject* obj)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -175,7 +276,21 @@ GBINDER_IO_FN(encode_death_notification)(
 | 
				
			|||||||
    return sizeof(*dest);
 | 
					    return sizeof(*dest);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Encodes BC_TRANSACTION data */
 | 
					static
 | 
				
			||||||
 | 
					guint
 | 
				
			||||||
 | 
					GBINDER_IO_FN(encode_ptr_cookie)(
 | 
				
			||||||
 | 
					    void* out,
 | 
				
			||||||
 | 
					    GBinderLocalObject* obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct binder_ptr_cookie* dest = out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* We never send these cookies and don't expect them back */
 | 
				
			||||||
 | 
					    dest->ptr = (uintptr_t)obj;
 | 
				
			||||||
 | 
					    dest->cookie = 0;
 | 
				
			||||||
 | 
					    return sizeof(*dest);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Fills binder_transaction_data for BC_TRANSACTION/REPLY */
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
GBINDER_IO_FN(fill_transaction_data)(
 | 
					GBINDER_IO_FN(fill_transaction_data)(
 | 
				
			||||||
@@ -183,7 +298,7 @@ GBINDER_IO_FN(fill_transaction_data)(
 | 
				
			|||||||
    guint32 handle,
 | 
					    guint32 handle,
 | 
				
			||||||
    guint32 code,
 | 
					    guint32 code,
 | 
				
			||||||
    const GByteArray* payload,
 | 
					    const GByteArray* payload,
 | 
				
			||||||
    guint flags,
 | 
					    guint tx_flags,
 | 
				
			||||||
    GUtilIntArray* offsets,
 | 
					    GUtilIntArray* offsets,
 | 
				
			||||||
    void** offsets_buf)
 | 
					    void** offsets_buf)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -192,9 +307,7 @@ GBINDER_IO_FN(fill_transaction_data)(
 | 
				
			|||||||
    tr->code = code;
 | 
					    tr->code = code;
 | 
				
			||||||
    tr->data_size = payload->len;
 | 
					    tr->data_size = payload->len;
 | 
				
			||||||
    tr->data.ptr.buffer = (uintptr_t)payload->data;
 | 
					    tr->data.ptr.buffer = (uintptr_t)payload->data;
 | 
				
			||||||
    if (flags & GBINDER_TX_FLAG_ONEWAY) {
 | 
					    tr->flags = tx_flags;
 | 
				
			||||||
        tr->flags |= TF_ONE_WAY;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (offsets && offsets->count) {
 | 
					    if (offsets && offsets->count) {
 | 
				
			||||||
        guint i;
 | 
					        guint i;
 | 
				
			||||||
        binder_size_t* tx_offsets = g_new(binder_size_t, offsets->count);
 | 
					        binder_size_t* tx_offsets = g_new(binder_size_t, offsets->count);
 | 
				
			||||||
@@ -210,6 +323,7 @@ GBINDER_IO_FN(fill_transaction_data)(
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Encodes BC_TRANSACTION data */
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
guint
 | 
					guint
 | 
				
			||||||
GBINDER_IO_FN(encode_transaction)(
 | 
					GBINDER_IO_FN(encode_transaction)(
 | 
				
			||||||
@@ -223,7 +337,8 @@ GBINDER_IO_FN(encode_transaction)(
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    struct binder_transaction_data* tr = out;
 | 
					    struct binder_transaction_data* tr = out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GBINDER_IO_FN(fill_transaction_data)(tr, handle, code, payload, flags,
 | 
					    GBINDER_IO_FN(fill_transaction_data)(tr, handle, code, payload,
 | 
				
			||||||
 | 
					        (flags & GBINDER_TX_FLAG_ONEWAY) ? TF_ONE_WAY : TF_ACCEPT_FDS,
 | 
				
			||||||
        offsets, offsets_buf);
 | 
					        offsets, offsets_buf);
 | 
				
			||||||
    return sizeof(*tr);
 | 
					    return sizeof(*tr);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -244,13 +359,53 @@ GBINDER_IO_FN(encode_transaction_sg)(
 | 
				
			|||||||
    struct binder_transaction_data_sg* sg = out;
 | 
					    struct binder_transaction_data_sg* sg = out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GBINDER_IO_FN(fill_transaction_data)(&sg->transaction_data, handle, code,
 | 
					    GBINDER_IO_FN(fill_transaction_data)(&sg->transaction_data, handle, code,
 | 
				
			||||||
        payload, flags, offsets, offsets_buf);
 | 
					        payload, (flags & GBINDER_TX_FLAG_ONEWAY) ? TF_ONE_WAY : TF_ACCEPT_FDS,
 | 
				
			||||||
 | 
					        offsets, offsets_buf);
 | 
				
			||||||
    /* The driver seems to require buffers to be 8-byte aligned */
 | 
					    /* The driver seems to require buffers to be 8-byte aligned */
 | 
				
			||||||
    sg->buffers_size = G_ALIGN8(buffers_size);
 | 
					    sg->buffers_size = G_ALIGN8(buffers_size);
 | 
				
			||||||
    return sizeof(*sg);
 | 
					    return sizeof(*sg);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Encode BC_REPLY */
 | 
					/* Encodes BC_REPLY data */
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					guint
 | 
				
			||||||
 | 
					GBINDER_IO_FN(encode_reply)(
 | 
				
			||||||
 | 
					    void* out,
 | 
				
			||||||
 | 
					    guint32 handle,
 | 
				
			||||||
 | 
					    guint32 code,
 | 
				
			||||||
 | 
					    const GByteArray* payload,
 | 
				
			||||||
 | 
					    GUtilIntArray* offsets,
 | 
				
			||||||
 | 
					    void** offsets_buf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct binder_transaction_data* tr = out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    GBINDER_IO_FN(fill_transaction_data)(tr, handle, code, payload, 0,
 | 
				
			||||||
 | 
					        offsets, offsets_buf);
 | 
				
			||||||
 | 
					    return sizeof(*tr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Encodes BC_REPLY_SG data */
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					guint
 | 
				
			||||||
 | 
					GBINDER_IO_FN(encode_reply_sg)(
 | 
				
			||||||
 | 
					    void* out,
 | 
				
			||||||
 | 
					    guint32 handle,
 | 
				
			||||||
 | 
					    guint32 code,
 | 
				
			||||||
 | 
					    const GByteArray* payload,
 | 
				
			||||||
 | 
					    GUtilIntArray* offsets,
 | 
				
			||||||
 | 
					    void** offsets_buf,
 | 
				
			||||||
 | 
					    gsize buffers_size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct binder_transaction_data_sg* sg = out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    GBINDER_IO_FN(fill_transaction_data)(&sg->transaction_data, handle, code,
 | 
				
			||||||
 | 
					        payload, 0, offsets, offsets_buf);
 | 
				
			||||||
 | 
					    /* The driver seems to require buffers to be 8-byte aligned */
 | 
				
			||||||
 | 
					    sg->buffers_size = G_ALIGN8(buffers_size);
 | 
				
			||||||
 | 
					    return sizeof(*sg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Encode BC_REPLY with just status */
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
guint
 | 
					guint
 | 
				
			||||||
GBINDER_IO_FN(encode_status_reply)(
 | 
					GBINDER_IO_FN(encode_status_reply)(
 | 
				
			||||||
@@ -338,7 +493,7 @@ GBINDER_IO_FN(decode_cookie)(
 | 
				
			|||||||
/* Decode struct binder_ptr_cookie */
 | 
					/* Decode struct binder_ptr_cookie */
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
void*
 | 
					void*
 | 
				
			||||||
GBINDER_IO_FN(decode_binder_ptr_cookie)(
 | 
					GBINDER_IO_FN(decode_ptr_cookie)(
 | 
				
			||||||
    const void* data)
 | 
					    const void* data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const struct binder_ptr_cookie* ptr = data;
 | 
					    const struct binder_ptr_cookie* ptr = data;
 | 
				
			||||||
@@ -348,13 +503,33 @@ GBINDER_IO_FN(decode_binder_ptr_cookie)(
 | 
				
			|||||||
    return (void*)(uintptr_t)ptr->ptr;
 | 
					    return (void*)(uintptr_t)ptr->ptr;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					guint
 | 
				
			||||||
 | 
					GBINDER_IO_FN(decode_binder_handle)(
 | 
				
			||||||
 | 
					    const void* data,
 | 
				
			||||||
 | 
					    guint32* handle,
 | 
				
			||||||
 | 
					    const GBinderRpcProtocol* protocol)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const struct flat_binder_object* obj = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Caller guarantees that data points to an object */
 | 
				
			||||||
 | 
					    if (obj->hdr.type == BINDER_TYPE_HANDLE) {
 | 
				
			||||||
 | 
					        if (handle) {
 | 
				
			||||||
 | 
					            *handle = obj->handle;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return sizeof(*obj) + protocol->flat_binder_object_extra;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
guint
 | 
					guint
 | 
				
			||||||
GBINDER_IO_FN(decode_binder_object)(
 | 
					GBINDER_IO_FN(decode_binder_object)(
 | 
				
			||||||
    const void* data,
 | 
					    const void* data,
 | 
				
			||||||
    gsize size,
 | 
					    gsize size,
 | 
				
			||||||
    GBinderObjectRegistry* reg,
 | 
					    GBinderObjectRegistry* reg,
 | 
				
			||||||
    GBinderRemoteObject** out)
 | 
					    GBinderRemoteObject** out,
 | 
				
			||||||
 | 
					    const GBinderRpcProtocol* protocol)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const struct flat_binder_object* obj = data;
 | 
					    const struct flat_binder_object* obj = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -362,9 +537,22 @@ GBINDER_IO_FN(decode_binder_object)(
 | 
				
			|||||||
        switch (obj->hdr.type) {
 | 
					        switch (obj->hdr.type) {
 | 
				
			||||||
        case BINDER_TYPE_HANDLE:
 | 
					        case BINDER_TYPE_HANDLE:
 | 
				
			||||||
            if (out) {
 | 
					            if (out) {
 | 
				
			||||||
                *out = gbinder_object_registry_get_remote(reg, obj->handle);
 | 
					                *out = gbinder_object_registry_get_remote(reg, obj->handle,
 | 
				
			||||||
 | 
					                    REMOTE_REGISTRY_CAN_CREATE_AND_ACQUIRE);
 | 
				
			||||||
 | 
					                if (*out && protocol->finish_unflatten_binder) {
 | 
				
			||||||
 | 
					                    protocol->finish_unflatten_binder(obj + 1, *out);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return sizeof(*obj);
 | 
					            return sizeof(*obj) + protocol->flat_binder_object_extra;
 | 
				
			||||||
 | 
					        case BINDER_TYPE_BINDER:
 | 
				
			||||||
 | 
					            if (!obj->binder) {
 | 
				
			||||||
 | 
					                /* That's a NULL reference */
 | 
				
			||||||
 | 
					                if (out) {
 | 
				
			||||||
 | 
					                    *out = NULL;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return sizeof(*obj) + protocol->flat_binder_object_extra;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            /* fallthrough */
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
            GERR("Unsupported binder object type 0x%08x", obj->hdr.type);
 | 
					            GERR("Unsupported binder object type 0x%08x", obj->hdr.type);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
@@ -379,7 +567,7 @@ guint
 | 
				
			|||||||
GBINDER_IO_FN(decode_buffer_object)(
 | 
					GBINDER_IO_FN(decode_buffer_object)(
 | 
				
			||||||
    GBinderBuffer* buf,
 | 
					    GBinderBuffer* buf,
 | 
				
			||||||
    gsize offset,
 | 
					    gsize offset,
 | 
				
			||||||
    GBinderBuffer** out)
 | 
					    GBinderIoBufferObject* out)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const void* data = (guint8*)buf->data + offset;
 | 
					    const void* data = (guint8*)buf->data + offset;
 | 
				
			||||||
    const gsize size = (offset < buf->size) ? (buf->size - offset) : 0;
 | 
					    const gsize size = (offset < buf->size) ? (buf->size - offset) : 0;
 | 
				
			||||||
@@ -387,12 +575,36 @@ GBINDER_IO_FN(decode_buffer_object)(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if (size >= sizeof(*flat) && flat->hdr.type == BINDER_TYPE_PTR) {
 | 
					    if (size >= sizeof(*flat) && flat->hdr.type == BINDER_TYPE_PTR) {
 | 
				
			||||||
        if (out) {
 | 
					        if (out) {
 | 
				
			||||||
            *out = gbinder_buffer_new_with_parent(buf,
 | 
					            out->data = (void*)(uintptr_t)flat->buffer;
 | 
				
			||||||
                (void*)(uintptr_t)flat->buffer, flat->length);
 | 
					            out->size = (gsize)flat->length;
 | 
				
			||||||
 | 
					            out->parent_offset = (gsize)flat->parent_offset;
 | 
				
			||||||
 | 
					            out->has_parent = (flat->flags & BINDER_BUFFER_FLAG_HAS_PARENT) ?
 | 
				
			||||||
 | 
					                TRUE : FALSE;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return sizeof(*flat);
 | 
					        return sizeof(*flat);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (out) *out = NULL;
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					guint
 | 
				
			||||||
 | 
					GBINDER_IO_FN(decode_fd_object)(
 | 
				
			||||||
 | 
					    const void* data,
 | 
				
			||||||
 | 
					    gsize size,
 | 
				
			||||||
 | 
					    int* fd)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const struct flat_binder_object* obj = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (size >= sizeof(*obj)) {
 | 
				
			||||||
 | 
					        switch (obj->hdr.type) {
 | 
				
			||||||
 | 
					        case BINDER_TYPE_FD:
 | 
				
			||||||
 | 
					            if (fd) *fd = obj->handle;
 | 
				
			||||||
 | 
					            return sizeof(*obj);
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (fd) *fd = -1;
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -445,22 +657,33 @@ const GBinderIo GBINDER_IO_PREFIX = {
 | 
				
			|||||||
        .failed_reply = BR_FAILED_REPLY
 | 
					        .failed_reply = BR_FAILED_REPLY
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .object_size = GBINDER_IO_FN(object_size),
 | 
				
			||||||
 | 
					    .object_data_size = GBINDER_IO_FN(object_data_size),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Encoders */
 | 
					    /* Encoders */
 | 
				
			||||||
    .encode_pointer = GBINDER_IO_FN(encode_pointer),
 | 
					    .encode_pointer = GBINDER_IO_FN(encode_pointer),
 | 
				
			||||||
 | 
					    .encode_cookie = GBINDER_IO_FN(encode_cookie),
 | 
				
			||||||
    .encode_local_object = GBINDER_IO_FN(encode_local_object),
 | 
					    .encode_local_object = GBINDER_IO_FN(encode_local_object),
 | 
				
			||||||
    .encode_remote_object = GBINDER_IO_FN(encode_remote_object),
 | 
					    .encode_remote_object = GBINDER_IO_FN(encode_remote_object),
 | 
				
			||||||
 | 
					    .encode_fd_object = GBINDER_IO_FN(encode_fd_object),
 | 
				
			||||||
 | 
					    .encode_fda_object = GBINDER_IO_FN(encode_fda_object),
 | 
				
			||||||
    .encode_buffer_object = GBINDER_IO_FN(encode_buffer_object),
 | 
					    .encode_buffer_object = GBINDER_IO_FN(encode_buffer_object),
 | 
				
			||||||
    .encode_death_notification = GBINDER_IO_FN(encode_death_notification),
 | 
					    .encode_handle_cookie = GBINDER_IO_FN(encode_handle_cookie),
 | 
				
			||||||
 | 
					    .encode_ptr_cookie = GBINDER_IO_FN(encode_ptr_cookie),
 | 
				
			||||||
    .encode_transaction = GBINDER_IO_FN(encode_transaction),
 | 
					    .encode_transaction = GBINDER_IO_FN(encode_transaction),
 | 
				
			||||||
    .encode_transaction_sg = GBINDER_IO_FN(encode_transaction_sg),
 | 
					    .encode_transaction_sg = GBINDER_IO_FN(encode_transaction_sg),
 | 
				
			||||||
 | 
					    .encode_reply = GBINDER_IO_FN(encode_reply),
 | 
				
			||||||
 | 
					    .encode_reply_sg = GBINDER_IO_FN(encode_reply_sg),
 | 
				
			||||||
    .encode_status_reply = GBINDER_IO_FN(encode_status_reply),
 | 
					    .encode_status_reply = GBINDER_IO_FN(encode_status_reply),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Decoders */
 | 
					    /* Decoders */
 | 
				
			||||||
    .decode_transaction_data = GBINDER_IO_FN(decode_transaction_data),
 | 
					    .decode_transaction_data = GBINDER_IO_FN(decode_transaction_data),
 | 
				
			||||||
    .decode_cookie = GBINDER_IO_FN(decode_cookie),
 | 
					    .decode_cookie = GBINDER_IO_FN(decode_cookie),
 | 
				
			||||||
    .decode_binder_ptr_cookie = GBINDER_IO_FN(decode_binder_ptr_cookie),
 | 
					    .decode_ptr_cookie = GBINDER_IO_FN(decode_ptr_cookie),
 | 
				
			||||||
 | 
					    .decode_binder_handle = GBINDER_IO_FN(decode_binder_handle),
 | 
				
			||||||
    .decode_binder_object = GBINDER_IO_FN(decode_binder_object),
 | 
					    .decode_binder_object = GBINDER_IO_FN(decode_binder_object),
 | 
				
			||||||
    .decode_buffer_object = GBINDER_IO_FN(decode_buffer_object),
 | 
					    .decode_buffer_object = GBINDER_IO_FN(decode_buffer_object),
 | 
				
			||||||
 | 
					    .decode_fd_object = GBINDER_IO_FN(decode_fd_object),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* ioctl wrappers */
 | 
					    /* ioctl wrappers */
 | 
				
			||||||
    .write_read = GBINDER_IO_FN(write_read)
 | 
					    .write_read = GBINDER_IO_FN(write_read)
 | 
				
			||||||
@@ -470,10 +693,14 @@ const GBinderIo GBINDER_IO_PREFIX = {
 | 
				
			|||||||
G_STATIC_ASSERT(GBINDER_POINTER_SIZE <= GBINDER_MAX_POINTER_SIZE);
 | 
					G_STATIC_ASSERT(GBINDER_POINTER_SIZE <= GBINDER_MAX_POINTER_SIZE);
 | 
				
			||||||
G_STATIC_ASSERT(sizeof(struct flat_binder_object) <=
 | 
					G_STATIC_ASSERT(sizeof(struct flat_binder_object) <=
 | 
				
			||||||
    GBINDER_MAX_BINDER_OBJECT_SIZE);
 | 
					    GBINDER_MAX_BINDER_OBJECT_SIZE);
 | 
				
			||||||
 | 
					G_STATIC_ASSERT(sizeof(struct binder_fd_object) <=
 | 
				
			||||||
 | 
					    GBINDER_MAX_BUFFER_OBJECT_SIZE);
 | 
				
			||||||
 | 
					G_STATIC_ASSERT(sizeof(struct binder_fd_array_object) <=
 | 
				
			||||||
 | 
					    GBINDER_MAX_BUFFER_OBJECT_SIZE);
 | 
				
			||||||
G_STATIC_ASSERT(sizeof(struct binder_buffer_object) <=
 | 
					G_STATIC_ASSERT(sizeof(struct binder_buffer_object) <=
 | 
				
			||||||
    GBINDER_MAX_BUFFER_OBJECT_SIZE);
 | 
					    GBINDER_MAX_BUFFER_OBJECT_SIZE);
 | 
				
			||||||
G_STATIC_ASSERT(sizeof(struct binder_handle_cookie) <=
 | 
					G_STATIC_ASSERT(sizeof(struct binder_handle_cookie) <=
 | 
				
			||||||
    GBINDER_MAX_DEATH_NOTIFICATION_SIZE);
 | 
					    GBINDER_MAX_HANDLE_COOKIE_SIZE);
 | 
				
			||||||
G_STATIC_ASSERT(sizeof(struct binder_transaction_data) <=
 | 
					G_STATIC_ASSERT(sizeof(struct binder_transaction_data) <=
 | 
				
			||||||
    GBINDER_MAX_BC_TRANSACTION_SIZE);
 | 
					    GBINDER_MAX_BC_TRANSACTION_SIZE);
 | 
				
			||||||
G_STATIC_ASSERT(sizeof(struct binder_transaction_data_sg) <=
 | 
					G_STATIC_ASSERT(sizeof(struct binder_transaction_data_sg) <=
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived from
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -43,6 +43,13 @@ typedef struct gbinder_io_buf {
 | 
				
			|||||||
    gsize consumed;
 | 
					    gsize consumed;
 | 
				
			||||||
} GBinderIoBuf;
 | 
					} GBinderIoBuf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_io_buffer_object {
 | 
				
			||||||
 | 
					    void* data;
 | 
				
			||||||
 | 
					    gsize size;
 | 
				
			||||||
 | 
					    gsize parent_offset;
 | 
				
			||||||
 | 
					    gboolean has_parent;
 | 
				
			||||||
 | 
					} GBinderIoBufferObject;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct gbinder_io_tx_data {
 | 
					typedef struct gbinder_io_tx_data {
 | 
				
			||||||
    int status;
 | 
					    int status;
 | 
				
			||||||
    guint32 code;
 | 
					    guint32 code;
 | 
				
			||||||
@@ -118,59 +125,86 @@ struct gbinder_io {
 | 
				
			|||||||
        guint failed_reply;
 | 
					        guint failed_reply;
 | 
				
			||||||
    } br;
 | 
					    } br;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Size of the object and its extra data */
 | 
				
			||||||
 | 
					    gsize (*object_size)(const void* obj, const GBinderRpcProtocol* protocol);
 | 
				
			||||||
 | 
					    gsize (*object_data_size)(const void* obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Writes pointer to the buffer. The destination buffer must have
 | 
					    /* Writes pointer to the buffer. The destination buffer must have
 | 
				
			||||||
     * at least GBINDER_IO_MAX_POINTER_SIZE bytes available. The
 | 
					     * at least GBINDER_IO_MAX_POINTER_SIZE bytes available. The
 | 
				
			||||||
     * actual size is returned. */
 | 
					     * actual size is returned. */
 | 
				
			||||||
#define GBINDER_MAX_POINTER_SIZE (8)
 | 
					#define GBINDER_MAX_POINTER_SIZE (8)
 | 
				
			||||||
    guint (*encode_pointer)(void* out, const void* pointer);
 | 
					    guint (*encode_pointer)(void* out, const void* pointer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Writes cookie to the buffer. The destination buffer must have
 | 
				
			||||||
 | 
					     * at least GBINDER_IO_MAX_COOKIE_SIZE bytes available. The
 | 
				
			||||||
 | 
					     * actual size is returned. */
 | 
				
			||||||
 | 
					#define GBINDER_MAX_COOKIE_SIZE GBINDER_MAX_POINTER_SIZE
 | 
				
			||||||
 | 
					    guint (*encode_cookie)(void* out, guint64 cookie);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Encode flat_buffer_object */
 | 
					    /* Encode flat_buffer_object */
 | 
				
			||||||
#define GBINDER_MAX_BINDER_OBJECT_SIZE (24)
 | 
					#define GBINDER_MAX_BINDER_OBJECT_SIZE (28)
 | 
				
			||||||
    guint (*encode_local_object)(void* out, GBinderLocalObject* obj);
 | 
					    guint (*encode_local_object)(void* out, GBinderLocalObject* obj,
 | 
				
			||||||
 | 
					        const GBinderRpcProtocol* protocol);
 | 
				
			||||||
    guint (*encode_remote_object)(void* out, GBinderRemoteObject* obj);
 | 
					    guint (*encode_remote_object)(void* out, GBinderRemoteObject* obj);
 | 
				
			||||||
 | 
					    guint (*encode_fd_object)(void* out, int fd);
 | 
				
			||||||
 | 
					    guint (*encode_fda_object)(void* out, const GBinderFds *fds,
 | 
				
			||||||
 | 
					        const GBinderParent* parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Encode binder_buffer_object */
 | 
					    /* Encode binder_buffer_object */
 | 
				
			||||||
#define GBINDER_MAX_BUFFER_OBJECT_SIZE (40)
 | 
					#define GBINDER_MAX_BUFFER_OBJECT_SIZE (40)
 | 
				
			||||||
    guint (*encode_buffer_object)(void* out, const void* data, gsize size,
 | 
					    guint (*encode_buffer_object)(void* out, const void* data, gsize size,
 | 
				
			||||||
        const GBinderParent* parent);
 | 
					        const GBinderParent* parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Encode death notification */
 | 
					    /* Encode binder_handle_cookie */
 | 
				
			||||||
#define GBINDER_MAX_DEATH_NOTIFICATION_SIZE (12)
 | 
					#define GBINDER_MAX_HANDLE_COOKIE_SIZE (12)
 | 
				
			||||||
    guint (*encode_death_notification)(void* out, GBinderRemoteObject* obj);
 | 
					    guint (*encode_handle_cookie)(void* out, GBinderRemoteObject* obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Encode BC_TRANSACTION/REPLY data */
 | 
					    /* Encode binder_ptr_cookie */
 | 
				
			||||||
 | 
					#define GBINDER_MAX_PTR_COOKIE_SIZE (16)
 | 
				
			||||||
 | 
					    guint (*encode_ptr_cookie)(void* out, GBinderLocalObject* obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Encode BC_TRANSACTION/BC_TRANSACTION_SG data */
 | 
				
			||||||
#define GBINDER_MAX_BC_TRANSACTION_SIZE (64)
 | 
					#define GBINDER_MAX_BC_TRANSACTION_SIZE (64)
 | 
				
			||||||
    guint (*encode_transaction)(void* out, guint32 handle, guint32 code,
 | 
					    guint (*encode_transaction)(void* out, guint32 handle, guint32 code,
 | 
				
			||||||
        const GByteArray* data, guint flags /* See below */,
 | 
					        const GByteArray* data, guint flags /* See below */,
 | 
				
			||||||
        GUtilIntArray* offsets, void** offsets_buf);
 | 
					        GUtilIntArray* offsets, void** offsets_buf);
 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* Encode BC_TRANSACTION_SG/REPLY_SG data */
 | 
					 | 
				
			||||||
#define GBINDER_MAX_BC_TRANSACTION_SG_SIZE (72)
 | 
					#define GBINDER_MAX_BC_TRANSACTION_SG_SIZE (72)
 | 
				
			||||||
    guint (*encode_transaction_sg)(void* out, guint32 handle, guint32 code,
 | 
					    guint (*encode_transaction_sg)(void* out, guint32 handle, guint32 code,
 | 
				
			||||||
        const GByteArray* data, guint flags /* GBINDER_TX_FLAG_xxx */,
 | 
					        const GByteArray* data, guint flags /* GBINDER_TX_FLAG_xxx */,
 | 
				
			||||||
        GUtilIntArray* offsets, void** offsets_buf,
 | 
					        GUtilIntArray* offsets, void** offsets_buf,
 | 
				
			||||||
        gsize buffers_size);
 | 
					        gsize buffers_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Encode BC_REPLY/REPLY_SG data */
 | 
				
			||||||
 | 
					#define GBINDER_MAX_BC_REPLY_SIZE GBINDER_MAX_BC_TRANSACTION_SIZE
 | 
				
			||||||
 | 
					    guint (*encode_reply)(void* out, guint32 handle, guint32 code,
 | 
				
			||||||
 | 
					        const GByteArray* data, GUtilIntArray* offsets, void** offsets_buf);
 | 
				
			||||||
 | 
					#define GBINDER_MAX_BC_REPLY_SG_SIZE GBINDER_MAX_BC_TRANSACTION_SG_SIZE
 | 
				
			||||||
 | 
					    guint (*encode_reply_sg)(void* out, guint32 handle, guint32 code,
 | 
				
			||||||
 | 
					        const GByteArray* data, GUtilIntArray* offsets, void** offsets_buf,
 | 
				
			||||||
 | 
					        gsize buffers_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Encode BC_REPLY */
 | 
					    /* Encode BC_REPLY */
 | 
				
			||||||
    guint (*encode_status_reply)(void* out, gint32* status);
 | 
					    guint (*encode_status_reply)(void* out, gint32* status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Decoders */
 | 
					    /* Decoders */
 | 
				
			||||||
    void (*decode_transaction_data)(const void* data, GBinderIoTxData* tx);
 | 
					    void (*decode_transaction_data)(const void* data, GBinderIoTxData* tx);
 | 
				
			||||||
 | 
					    void* (*decode_ptr_cookie)(const void* data);
 | 
				
			||||||
#define GBINDER_MAX_PTR_COOKIE_SIZE (16)
 | 
					 | 
				
			||||||
    void* (*decode_binder_ptr_cookie)(const void* data);
 | 
					 | 
				
			||||||
    guint (*decode_cookie)(const void* data, guint64* cookie);
 | 
					    guint (*decode_cookie)(const void* data, guint64* cookie);
 | 
				
			||||||
 | 
					    guint (*decode_binder_handle)(const void* obj, guint32* handle,
 | 
				
			||||||
 | 
					        const GBinderRpcProtocol* protocol);
 | 
				
			||||||
    guint (*decode_binder_object)(const void* data, gsize size,
 | 
					    guint (*decode_binder_object)(const void* data, gsize size,
 | 
				
			||||||
       GBinderObjectRegistry* reg, GBinderRemoteObject** obj);
 | 
					        GBinderObjectRegistry* reg, GBinderRemoteObject** obj,
 | 
				
			||||||
 | 
					        const GBinderRpcProtocol* protocol);
 | 
				
			||||||
    guint (*decode_buffer_object)(GBinderBuffer* buf, gsize offset,
 | 
					    guint (*decode_buffer_object)(GBinderBuffer* buf, gsize offset,
 | 
				
			||||||
        GBinderBuffer** out);
 | 
					        GBinderIoBufferObject* out);
 | 
				
			||||||
 | 
					    guint (*decode_fd_object)(const void* data, gsize size, int* fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* ioctl wrappers */
 | 
					    /* ioctl wrappers */
 | 
				
			||||||
    int (*write_read)(int fd, GBinderIoBuf* write, GBinderIoBuf* read);
 | 
					    int (*write_read)(int fd, GBinderIoBuf* write, GBinderIoBuf* read);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern const GBinderIo gbinder_io_32;
 | 
					extern const GBinderIo gbinder_io_32 GBINDER_INTERNAL;
 | 
				
			||||||
extern const GBinderIo gbinder_io_64;
 | 
					extern const GBinderIo gbinder_io_64 GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* GBINDER_IO_H */
 | 
					#endif /* GBINDER_IO_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1652
									
								
								src/gbinder_ipc.c
									
									
									
									
									
								
							
							
						
						
									
										1652
									
								
								src/gbinder_ipc.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -42,7 +42,6 @@ struct gbinder_ipc {
 | 
				
			|||||||
    GObject object;
 | 
					    GObject object;
 | 
				
			||||||
    GBinderIpcPriv* priv;
 | 
					    GBinderIpcPriv* priv;
 | 
				
			||||||
    GBinderDriver* driver;
 | 
					    GBinderDriver* driver;
 | 
				
			||||||
    GUtilIdlePool* pool;
 | 
					 | 
				
			||||||
    const char* dev;
 | 
					    const char* dev;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -60,6 +59,12 @@ struct gbinder_ipc_tx {
 | 
				
			|||||||
    void* user_data;
 | 
					    void* user_data;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					(*GBinderIpcLocalObjectCheckFunc)(
 | 
				
			||||||
 | 
					    GBinderLocalObject* obj,
 | 
				
			||||||
 | 
					    void* user_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef
 | 
					typedef
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
(*GBinderIpcReplyFunc)(
 | 
					(*GBinderIpcReplyFunc)(
 | 
				
			||||||
@@ -68,53 +73,105 @@ void
 | 
				
			|||||||
    int status,
 | 
					    int status,
 | 
				
			||||||
    void* user_data);
 | 
					    void* user_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderIpc*
 | 
					typedef
 | 
				
			||||||
gbinder_ipc_new(
 | 
					 | 
				
			||||||
    const char* dev);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
GBinderIpc*
 | 
					 | 
				
			||||||
gbinder_ipc_ref(
 | 
					 | 
				
			||||||
    GBinderIpc* ipc);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
gbinder_ipc_unref(
 | 
					 | 
				
			||||||
    GBinderIpc* ipc);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
gbinder_ipc_looper_check(
 | 
					 | 
				
			||||||
   GBinderIpc* ipc);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
GBinderObjectRegistry*
 | 
					 | 
				
			||||||
gbinder_ipc_object_registry(
 | 
					 | 
				
			||||||
    GBinderIpc* ipc);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
GBinderLocalObject*
 | 
					 | 
				
			||||||
gbinder_ipc_new_local_object(
 | 
					 | 
				
			||||||
    GBinderIpc* ipc,
 | 
					 | 
				
			||||||
    const char* iface,
 | 
					 | 
				
			||||||
    GBinderLocalTransactFunc txproc,
 | 
					 | 
				
			||||||
    void* data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
GBinderRemoteObject*
 | 
					 | 
				
			||||||
gbinder_ipc_get_remote_object(
 | 
					 | 
				
			||||||
    GBinderIpc* ipc,
 | 
					 | 
				
			||||||
    guint32 handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
GBinderRemoteReply*
 | 
					GBinderRemoteReply*
 | 
				
			||||||
gbinder_ipc_transact_sync_reply(
 | 
					(*GBinderIpcSyncReplyFunc)(
 | 
				
			||||||
    GBinderIpc* ipc,
 | 
					    GBinderIpc* ipc,
 | 
				
			||||||
    guint32 handle,
 | 
					    guint32 handle,
 | 
				
			||||||
    guint32 code,
 | 
					    guint32 code,
 | 
				
			||||||
    GBinderLocalRequest* req,
 | 
					    GBinderLocalRequest* req,
 | 
				
			||||||
    int* status);
 | 
					    int* status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
gbinder_ipc_transact_sync_oneway(
 | 
					(*GBinderIpcSyncOnewayFunc)(
 | 
				
			||||||
    GBinderIpc* ipc,
 | 
					    GBinderIpc* ipc,
 | 
				
			||||||
    guint32 handle,
 | 
					    guint32 handle,
 | 
				
			||||||
    guint32 code,
 | 
					    guint32 code,
 | 
				
			||||||
    GBinderLocalRequest* req);
 | 
					    GBinderLocalRequest* req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gbinder_ipc_sync_api {
 | 
				
			||||||
 | 
					    GBinderIpcSyncReplyFunc sync_reply;
 | 
				
			||||||
 | 
					    GBinderIpcSyncOnewayFunc sync_oneway;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern const GBinderIpcSyncApi gbinder_ipc_sync_main GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					extern const GBinderIpcSyncApi gbinder_ipc_sync_worker GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderIpc*
 | 
				
			||||||
 | 
					gbinder_ipc_new(
 | 
				
			||||||
 | 
					    const char* dev,
 | 
				
			||||||
 | 
					    const char* protocol)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderIpc*
 | 
				
			||||||
 | 
					gbinder_ipc_ref(
 | 
				
			||||||
 | 
					    GBinderIpc* ipc)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_ipc_unref(
 | 
				
			||||||
 | 
					    GBinderIpc* ipc)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char*
 | 
				
			||||||
 | 
					gbinder_ipc_name(
 | 
				
			||||||
 | 
					    GBinderIpc* ipc)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_ipc_looper_check(
 | 
				
			||||||
 | 
					    GBinderIpc* ipc)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderObjectRegistry*
 | 
				
			||||||
 | 
					gbinder_ipc_object_registry(
 | 
				
			||||||
 | 
					    GBinderIpc* ipc)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const GBinderIo*
 | 
				
			||||||
 | 
					gbinder_ipc_io(
 | 
				
			||||||
 | 
					    GBinderIpc* ipc)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const GBinderRpcProtocol*
 | 
				
			||||||
 | 
					gbinder_ipc_protocol(
 | 
				
			||||||
 | 
					    GBinderIpc* ipc)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderLocalObject*
 | 
				
			||||||
 | 
					gbinder_ipc_find_local_object(
 | 
				
			||||||
 | 
					    GBinderIpc* ipc,
 | 
				
			||||||
 | 
					    GBinderIpcLocalObjectCheckFunc func,
 | 
				
			||||||
 | 
					    void* user_data)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL
 | 
				
			||||||
 | 
					    G_GNUC_WARN_UNUSED_RESULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_ipc_register_local_object(
 | 
				
			||||||
 | 
					    GBinderIpc* ipc,
 | 
				
			||||||
 | 
					    GBinderLocalObject* obj)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderRemoteObject*
 | 
				
			||||||
 | 
					gbinder_ipc_get_service_manager(
 | 
				
			||||||
 | 
					    GBinderIpc* ipc)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL
 | 
				
			||||||
 | 
					    G_GNUC_WARN_UNUSED_RESULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_ipc_invalidate_remote_handle(
 | 
				
			||||||
 | 
					    GBinderIpc* ipc,
 | 
				
			||||||
 | 
					    guint32 handle)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					gbinder_ipc_ping_sync(
 | 
				
			||||||
 | 
					    GBinderIpc* ipc,
 | 
				
			||||||
 | 
					    guint32 handle,
 | 
				
			||||||
 | 
					    const GBinderIpcSyncApi* api)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gulong
 | 
					gulong
 | 
				
			||||||
gbinder_ipc_transact(
 | 
					gbinder_ipc_transact(
 | 
				
			||||||
    GBinderIpc* ipc,
 | 
					    GBinderIpc* ipc,
 | 
				
			||||||
@@ -124,7 +181,8 @@ gbinder_ipc_transact(
 | 
				
			|||||||
    GBinderLocalRequest* req,
 | 
					    GBinderLocalRequest* req,
 | 
				
			||||||
    GBinderIpcReplyFunc func,
 | 
					    GBinderIpcReplyFunc func,
 | 
				
			||||||
    GDestroyNotify destroy,
 | 
					    GDestroyNotify destroy,
 | 
				
			||||||
    void* user_data);
 | 
					    void* user_data)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gulong
 | 
					gulong
 | 
				
			||||||
gbinder_ipc_transact_custom(
 | 
					gbinder_ipc_transact_custom(
 | 
				
			||||||
@@ -132,24 +190,48 @@ gbinder_ipc_transact_custom(
 | 
				
			|||||||
    GBinderIpcTxFunc exec,
 | 
					    GBinderIpcTxFunc exec,
 | 
				
			||||||
    GBinderIpcTxFunc done,
 | 
					    GBinderIpcTxFunc done,
 | 
				
			||||||
    GDestroyNotify destroy,
 | 
					    GDestroyNotify destroy,
 | 
				
			||||||
    void* user_data);
 | 
					    void* user_data)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_ipc_cancel(
 | 
					gbinder_ipc_cancel(
 | 
				
			||||||
    GBinderIpc* ipc,
 | 
					    GBinderIpc* ipc,
 | 
				
			||||||
    gulong id);
 | 
					    gulong id)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Internal for GBinderLocalObject */
 | 
					/* Internal for GBinderLocalObject */
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_ipc_local_object_disposed(
 | 
					gbinder_ipc_local_object_disposed(
 | 
				
			||||||
    GBinderIpc* self,
 | 
					    GBinderIpc* ipc,
 | 
				
			||||||
    GBinderLocalObject* obj);
 | 
					    GBinderLocalObject* obj)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_ipc_invalidate_local_object(
 | 
				
			||||||
 | 
					    GBinderIpc* ipc,
 | 
				
			||||||
 | 
					    GBinderLocalObject* obj)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Internal for GBinderRemoteObject */
 | 
					/* Internal for GBinderRemoteObject */
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_ipc_remote_object_disposed(
 | 
					gbinder_ipc_remote_object_disposed(
 | 
				
			||||||
    GBinderIpc* self,
 | 
					    GBinderIpc* ipc,
 | 
				
			||||||
    GBinderRemoteObject* obj);
 | 
					    GBinderRemoteObject* obj)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Needed by unit tests */
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_ipc_set_max_threads(
 | 
				
			||||||
 | 
					    GBinderIpc* ipc,
 | 
				
			||||||
 | 
					    gint max_threads)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Declared for unit tests */
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_ipc_exit(
 | 
				
			||||||
 | 
					    void)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL
 | 
				
			||||||
 | 
					    GBINDER_DESTRUCTOR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* GBINDER_IPC_H */
 | 
					#endif /* GBINDER_IPC_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -32,27 +32,44 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "gbinder_driver.h"
 | 
					#include "gbinder_driver.h"
 | 
				
			||||||
#include "gbinder_ipc.h"
 | 
					#include "gbinder_ipc.h"
 | 
				
			||||||
 | 
					#include "gbinder_buffer_p.h"
 | 
				
			||||||
#include "gbinder_local_object_p.h"
 | 
					#include "gbinder_local_object_p.h"
 | 
				
			||||||
#include "gbinder_local_reply_p.h"
 | 
					#include "gbinder_local_reply_p.h"
 | 
				
			||||||
#include "gbinder_remote_request.h"
 | 
					#include "gbinder_remote_request.h"
 | 
				
			||||||
 | 
					#include "gbinder_eventloop_p.h"
 | 
				
			||||||
#include "gbinder_writer.h"
 | 
					#include "gbinder_writer.h"
 | 
				
			||||||
#include "gbinder_log.h"
 | 
					#include "gbinder_log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gutil_strv.h>
 | 
				
			||||||
 | 
					#include <gutil_macros.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <errno.h>
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct gbinder_local_object_priv {
 | 
					struct gbinder_local_object_priv {
 | 
				
			||||||
    GMainContext* context;
 | 
					    char** ifaces;
 | 
				
			||||||
    char* iface;
 | 
					 | 
				
			||||||
    GBinderLocalTransactFunc txproc;
 | 
					    GBinderLocalTransactFunc txproc;
 | 
				
			||||||
    void* user_data;
 | 
					    void* user_data;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_local_object_acquire_data {
 | 
				
			||||||
 | 
					    GBinderLocalObject* object;
 | 
				
			||||||
 | 
					    GBinderBufferContentsList* bufs;
 | 
				
			||||||
 | 
					} GBinderLocalObjectAcquireData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
G_DEFINE_TYPE(GBinderLocalObject, gbinder_local_object, G_TYPE_OBJECT)
 | 
					G_DEFINE_TYPE(GBinderLocalObject, gbinder_local_object, G_TYPE_OBJECT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PARENT_CLASS gbinder_local_object_parent_class
 | 
				
			||||||
#define GBINDER_LOCAL_OBJECT_GET_CLASS(obj) \
 | 
					#define GBINDER_LOCAL_OBJECT_GET_CLASS(obj) \
 | 
				
			||||||
    G_TYPE_INSTANCE_GET_CLASS((obj), GBINDER_TYPE_LOCAL_OBJECT, \
 | 
					    G_TYPE_INSTANCE_GET_CLASS((obj), GBINDER_TYPE_LOCAL_OBJECT, \
 | 
				
			||||||
    GBinderLocalObjectClass)
 | 
					    GBinderLocalObjectClass)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef
 | 
				
			||||||
 | 
					GBinderLocalReply*
 | 
				
			||||||
 | 
					(*GBinderLocalObjectTxHandler)(
 | 
				
			||||||
 | 
					    GBinderLocalObject* self,
 | 
				
			||||||
 | 
					    GBinderRemoteRequest* req,
 | 
				
			||||||
 | 
					    int* status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum gbinder_local_object_signal {
 | 
					enum gbinder_local_object_signal {
 | 
				
			||||||
    SIGNAL_WEAK_REFS_CHANGED,
 | 
					    SIGNAL_WEAK_REFS_CHANGED,
 | 
				
			||||||
    SIGNAL_STRONG_REFS_CHANGED,
 | 
					    SIGNAL_STRONG_REFS_CHANGED,
 | 
				
			||||||
@@ -70,6 +87,15 @@ static const char hidl_base_interface[] = "android.hidl.base@1.0::IBase";
 | 
				
			|||||||
 * Implementation
 | 
					 * Implementation
 | 
				
			||||||
 *==========================================================================*/
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					GBinderLocalReply*
 | 
				
			||||||
 | 
					gbinder_local_object_create_reply(
 | 
				
			||||||
 | 
					    GBinderLocalObject* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return gbinder_local_reply_new(gbinder_local_object_io(self),
 | 
				
			||||||
 | 
					        gbinder_local_object_protocol(self));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
GBINDER_LOCAL_TRANSACTION_SUPPORT
 | 
					GBINDER_LOCAL_TRANSACTION_SUPPORT
 | 
				
			||||||
gbinder_local_object_default_can_handle_transaction(
 | 
					gbinder_local_object_default_can_handle_transaction(
 | 
				
			||||||
@@ -78,6 +104,9 @@ gbinder_local_object_default_can_handle_transaction(
 | 
				
			|||||||
    guint code)
 | 
					    guint code)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    switch (code) {
 | 
					    switch (code) {
 | 
				
			||||||
 | 
					    case GBINDER_PING_TRANSACTION:
 | 
				
			||||||
 | 
					    case GBINDER_INTERFACE_TRANSACTION:
 | 
				
			||||||
 | 
					        return GBINDER_LOCAL_TRANSACTION_LOOPER;
 | 
				
			||||||
    case HIDL_PING_TRANSACTION:
 | 
					    case HIDL_PING_TRANSACTION:
 | 
				
			||||||
    case HIDL_GET_DESCRIPTOR_TRANSACTION:
 | 
					    case HIDL_GET_DESCRIPTOR_TRANSACTION:
 | 
				
			||||||
    case HIDL_DESCRIPTOR_CHAIN_TRANSACTION:
 | 
					    case HIDL_DESCRIPTOR_CHAIN_TRANSACTION:
 | 
				
			||||||
@@ -110,6 +139,37 @@ gbinder_local_object_default_handle_transaction(
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					GBinderLocalReply*
 | 
				
			||||||
 | 
					gbinder_local_object_ping_transaction(
 | 
				
			||||||
 | 
					    GBinderLocalObject* self,
 | 
				
			||||||
 | 
					    GBinderRemoteRequest* req,
 | 
				
			||||||
 | 
					    int* status)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderLocalReply* reply = gbinder_local_object_create_reply(self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    GVERBOSE("  PING_TRANSACTION");
 | 
				
			||||||
 | 
					    gbinder_local_reply_append_int32(reply, GBINDER_STATUS_OK);
 | 
				
			||||||
 | 
					    *status = GBINDER_STATUS_OK;
 | 
				
			||||||
 | 
					    return reply;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					GBinderLocalReply*
 | 
				
			||||||
 | 
					gbinder_local_object_interface_transaction(
 | 
				
			||||||
 | 
					    GBinderLocalObject* self,
 | 
				
			||||||
 | 
					    GBinderRemoteRequest* req,
 | 
				
			||||||
 | 
					    int* status)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderLocalObjectPriv* priv = self->priv;
 | 
				
			||||||
 | 
					    GBinderLocalReply* reply = gbinder_local_object_create_reply(self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    GVERBOSE("  INTERFACE_TRANSACTION");
 | 
				
			||||||
 | 
					    gbinder_local_reply_append_string16(reply, priv->ifaces[0]);
 | 
				
			||||||
 | 
					    *status = GBINDER_STATUS_OK;
 | 
				
			||||||
 | 
					    return reply;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
GBinderLocalReply*
 | 
					GBinderLocalReply*
 | 
				
			||||||
gbinder_local_object_hidl_ping_transaction(
 | 
					gbinder_local_object_hidl_ping_transaction(
 | 
				
			||||||
@@ -118,14 +178,11 @@ gbinder_local_object_hidl_ping_transaction(
 | 
				
			|||||||
    int* status)
 | 
					    int* status)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /*android.hidl.base@1.0::IBase interfaceDescriptor() */
 | 
					    /*android.hidl.base@1.0::IBase interfaceDescriptor() */
 | 
				
			||||||
    const GBinderIo* io = gbinder_local_object_io(self);
 | 
					    GBinderLocalReply* reply = gbinder_local_object_create_reply(self);
 | 
				
			||||||
    GBinderLocalReply* reply = gbinder_local_reply_new(io);
 | 
					 | 
				
			||||||
    GBinderWriter writer;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GVERBOSE("  HIDL_PING_TRANSACTION \"%s\"",
 | 
					    GVERBOSE("  HIDL_PING_TRANSACTION \"%s\"",
 | 
				
			||||||
        gbinder_remote_request_interface(req));
 | 
					        gbinder_remote_request_interface(req));
 | 
				
			||||||
    gbinder_local_reply_init_writer(reply, &writer);
 | 
					    gbinder_local_reply_append_int32(reply, GBINDER_STATUS_OK);
 | 
				
			||||||
    gbinder_writer_append_int32(&writer, GBINDER_STATUS_OK);
 | 
					 | 
				
			||||||
    *status = GBINDER_STATUS_OK;
 | 
					    *status = GBINDER_STATUS_OK;
 | 
				
			||||||
    return reply;
 | 
					    return reply;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -138,16 +195,15 @@ gbinder_local_object_hidl_get_descriptor_transaction(
 | 
				
			|||||||
    int* status)
 | 
					    int* status)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /*android.hidl.base@1.0::IBase interfaceDescriptor() */
 | 
					    /*android.hidl.base@1.0::IBase interfaceDescriptor() */
 | 
				
			||||||
    const GBinderIo* io = gbinder_local_object_io(self);
 | 
					    GBinderLocalObjectPriv* priv = self->priv;
 | 
				
			||||||
    GBinderLocalReply* reply = gbinder_local_reply_new(io);
 | 
					    GBinderLocalReply* reply = gbinder_local_object_create_reply(self);
 | 
				
			||||||
    GBinderWriter writer;
 | 
					    GBinderWriter writer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GVERBOSE("  HIDL_GET_DESCRIPTOR_TRANSACTION \"%s\"",
 | 
					    GVERBOSE("  HIDL_GET_DESCRIPTOR_TRANSACTION \"%s\"",
 | 
				
			||||||
        gbinder_remote_request_interface(req));
 | 
					        gbinder_remote_request_interface(req));
 | 
				
			||||||
    gbinder_local_reply_init_writer(reply, &writer);
 | 
					    gbinder_local_reply_init_writer(reply, &writer);
 | 
				
			||||||
    gbinder_writer_append_int32(&writer, GBINDER_STATUS_OK);
 | 
					    gbinder_writer_append_int32(&writer, GBINDER_STATUS_OK);
 | 
				
			||||||
    gbinder_writer_append_hidl_string(&writer, self->iface ? self->iface :
 | 
					    gbinder_writer_append_hidl_string(&writer, priv->ifaces[0]);
 | 
				
			||||||
        hidl_base_interface);
 | 
					 | 
				
			||||||
    *status = GBINDER_STATUS_OK;
 | 
					    *status = GBINDER_STATUS_OK;
 | 
				
			||||||
    return reply;
 | 
					    return reply;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -160,20 +216,16 @@ gbinder_local_object_hidl_descriptor_chain_transaction(
 | 
				
			|||||||
    int* status)
 | 
					    int* status)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /*android.hidl.base@1.0::IBase interfaceChain() */
 | 
					    /*android.hidl.base@1.0::IBase interfaceChain() */
 | 
				
			||||||
    const GBinderIo* io = gbinder_local_object_io(self);
 | 
					    GBinderLocalReply* reply = gbinder_local_object_create_reply(self);
 | 
				
			||||||
    GBinderLocalReply* reply = gbinder_local_reply_new(io);
 | 
					 | 
				
			||||||
    GBinderWriter writer;
 | 
					    GBinderWriter writer;
 | 
				
			||||||
    const char* chain[2];
 | 
					 | 
				
			||||||
    int n = 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GVERBOSE("  HIDL_DESCRIPTOR_CHAIN_TRANSACTION \"%s\"",
 | 
					    GVERBOSE("  HIDL_DESCRIPTOR_CHAIN_TRANSACTION \"%s\"",
 | 
				
			||||||
        gbinder_remote_request_interface(req));
 | 
					        gbinder_remote_request_interface(req));
 | 
				
			||||||
    if (self->iface) chain[n++] = self->iface;
 | 
					 | 
				
			||||||
    chain[n++] = hidl_base_interface;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    gbinder_local_reply_init_writer(reply, &writer);
 | 
					    gbinder_local_reply_init_writer(reply, &writer);
 | 
				
			||||||
    gbinder_writer_append_int32(&writer, GBINDER_STATUS_OK);
 | 
					    gbinder_writer_append_int32(&writer, GBINDER_STATUS_OK);
 | 
				
			||||||
    gbinder_writer_append_hidl_string_vec(&writer, chain, n);
 | 
					    gbinder_writer_append_hidl_string_vec(&writer, (const char**)
 | 
				
			||||||
 | 
					        self->ifaces, -1);
 | 
				
			||||||
    *status = GBINDER_STATUS_OK;
 | 
					    *status = GBINDER_STATUS_OK;
 | 
				
			||||||
    return reply;
 | 
					    return reply;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -187,91 +239,142 @@ gbinder_local_object_default_handle_looper_transaction(
 | 
				
			|||||||
    guint flags,
 | 
					    guint flags,
 | 
				
			||||||
    int* status)
 | 
					    int* status)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    GBinderLocalObjectTxHandler handler = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch (code) {
 | 
					    switch (code) {
 | 
				
			||||||
 | 
					    case GBINDER_PING_TRANSACTION:
 | 
				
			||||||
 | 
					        handler = gbinder_local_object_ping_transaction;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case GBINDER_INTERFACE_TRANSACTION:
 | 
				
			||||||
 | 
					        handler = gbinder_local_object_interface_transaction;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
    case HIDL_PING_TRANSACTION:
 | 
					    case HIDL_PING_TRANSACTION:
 | 
				
			||||||
        GASSERT(!(flags & GBINDER_TX_FLAG_ONEWAY));
 | 
					        handler = gbinder_local_object_hidl_ping_transaction;
 | 
				
			||||||
        return gbinder_local_object_hidl_ping_transaction
 | 
					        break;
 | 
				
			||||||
            (self, req, status);
 | 
					 | 
				
			||||||
    case HIDL_GET_DESCRIPTOR_TRANSACTION:
 | 
					    case HIDL_GET_DESCRIPTOR_TRANSACTION:
 | 
				
			||||||
        GASSERT(!(flags & GBINDER_TX_FLAG_ONEWAY));
 | 
					        handler = gbinder_local_object_hidl_get_descriptor_transaction;
 | 
				
			||||||
        return gbinder_local_object_hidl_get_descriptor_transaction
 | 
					        break;
 | 
				
			||||||
            (self, req, status);
 | 
					 | 
				
			||||||
    case HIDL_DESCRIPTOR_CHAIN_TRANSACTION:
 | 
					    case HIDL_DESCRIPTOR_CHAIN_TRANSACTION:
 | 
				
			||||||
        GASSERT(!(flags & GBINDER_TX_FLAG_ONEWAY));
 | 
					        handler = gbinder_local_object_hidl_descriptor_chain_transaction;
 | 
				
			||||||
        return gbinder_local_object_hidl_descriptor_chain_transaction
 | 
					        break;
 | 
				
			||||||
            (self, req, status);
 | 
					 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
        if (status) *status = (-EBADMSG);
 | 
					        if (status) *status = (-EBADMSG);
 | 
				
			||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    GASSERT(!(flags & GBINDER_TX_FLAG_ONEWAY));
 | 
				
			||||||
 | 
					    return handler(self, req, status);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_local_object_default_drop(
 | 
				
			||||||
 | 
					    GBinderLocalObject* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderLocalObjectPriv* priv = self->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Clear the transaction callback */
 | 
				
			||||||
 | 
					    priv->txproc = NULL;
 | 
				
			||||||
 | 
					    priv->user_data = NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_local_object_handle_later(
 | 
					gbinder_local_object_handle_later(
 | 
				
			||||||
    GBinderLocalObject* self,
 | 
					    GBinderLocalObject* self,
 | 
				
			||||||
    GSourceFunc function)
 | 
					    GBinderEventLoopCallbackFunc function)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (G_LIKELY(self)) {
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
        GBinderLocalObjectPriv* priv = self->priv;
 | 
					        gbinder_idle_callback_invoke_later(function,
 | 
				
			||||||
 | 
					 | 
				
			||||||
        g_main_context_invoke_full(priv->context, G_PRIORITY_DEFAULT, function,
 | 
					 | 
				
			||||||
            gbinder_local_object_ref(self), g_object_unref);
 | 
					            gbinder_local_object_ref(self), g_object_unref);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
gboolean
 | 
					void
 | 
				
			||||||
gbinder_local_object_handle_increfs_proc(
 | 
					gbinder_local_object_increfs_proc(
 | 
				
			||||||
    gpointer local)
 | 
					    gpointer user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(local);
 | 
					    GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(user_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    self->weak_refs++;
 | 
					    self->weak_refs++;
 | 
				
			||||||
    g_signal_emit(self, gbinder_local_object_signals
 | 
					    g_signal_emit(self, gbinder_local_object_signals
 | 
				
			||||||
        [SIGNAL_WEAK_REFS_CHANGED], 0);
 | 
					        [SIGNAL_WEAK_REFS_CHANGED], 0);
 | 
				
			||||||
    return G_SOURCE_REMOVE;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
gboolean
 | 
					void
 | 
				
			||||||
gbinder_local_object_handle_decrefs_proc(
 | 
					gbinder_local_object_decrefs_proc(
 | 
				
			||||||
    gpointer local)
 | 
					    gpointer user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(local);
 | 
					    GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(user_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GASSERT(self->weak_refs > 0);
 | 
					    GASSERT(self->weak_refs > 0);
 | 
				
			||||||
    self->weak_refs--;
 | 
					    self->weak_refs--;
 | 
				
			||||||
    g_signal_emit(self, gbinder_local_object_signals
 | 
					    g_signal_emit(self, gbinder_local_object_signals
 | 
				
			||||||
        [SIGNAL_WEAK_REFS_CHANGED], 0);
 | 
					        [SIGNAL_WEAK_REFS_CHANGED], 0);
 | 
				
			||||||
    return G_SOURCE_REMOVE;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
gboolean
 | 
					void
 | 
				
			||||||
gbinder_local_object_handle_acquire_proc(
 | 
					gbinder_local_object_default_acquire(
 | 
				
			||||||
    gpointer local)
 | 
					    GBinderLocalObject* self)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(local);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    self->strong_refs++;
 | 
					    self->strong_refs++;
 | 
				
			||||||
 | 
					    gbinder_local_object_ref(self);
 | 
				
			||||||
 | 
					    GVERBOSE_("%p => %d", self, self->strong_refs);
 | 
				
			||||||
    g_signal_emit(self, gbinder_local_object_signals
 | 
					    g_signal_emit(self, gbinder_local_object_signals
 | 
				
			||||||
        [SIGNAL_STRONG_REFS_CHANGED], 0);
 | 
					        [SIGNAL_STRONG_REFS_CHANGED], 0);
 | 
				
			||||||
    return G_SOURCE_REMOVE;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
gboolean
 | 
					void
 | 
				
			||||||
gbinder_local_object_handle_release_proc(
 | 
					gbinder_local_object_acquire_proc(
 | 
				
			||||||
    gpointer local)
 | 
					    gpointer user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(local);
 | 
					    GBinderLocalObjectAcquireData* data = user_data;
 | 
				
			||||||
 | 
					    GBinderLocalObject* self = data->object;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    GBINDER_LOCAL_OBJECT_GET_CLASS(self)->acquire(self);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_local_object_acquire_done(
 | 
				
			||||||
 | 
					    gpointer user_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderLocalObjectAcquireData* data = user_data;
 | 
				
			||||||
 | 
					    GBinderLocalObject* self = data->object;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gbinder_driver_acquire_done(self->ipc->driver, self);
 | 
				
			||||||
 | 
					    gbinder_local_object_unref(self);
 | 
				
			||||||
 | 
					    gbinder_buffer_contents_list_free(data->bufs);
 | 
				
			||||||
 | 
					    return gutil_slice_free(data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_local_object_default_release(
 | 
				
			||||||
 | 
					    GBinderLocalObject* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
    GASSERT(self->strong_refs > 0);
 | 
					    GASSERT(self->strong_refs > 0);
 | 
				
			||||||
    self->strong_refs--;
 | 
					    if (self->strong_refs > 0) {
 | 
				
			||||||
    g_signal_emit(self, gbinder_local_object_signals
 | 
					        self->strong_refs--;
 | 
				
			||||||
        [SIGNAL_STRONG_REFS_CHANGED], 0);
 | 
					        GVERBOSE_("%p => %d", self, self->strong_refs);
 | 
				
			||||||
    return G_SOURCE_REMOVE;
 | 
					        g_signal_emit(self, gbinder_local_object_signals
 | 
				
			||||||
 | 
					            [SIGNAL_STRONG_REFS_CHANGED], 0);
 | 
				
			||||||
 | 
					        gbinder_local_object_unref(self);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_local_object_release_proc(
 | 
				
			||||||
 | 
					    gpointer obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    GBINDER_LOCAL_OBJECT_GET_CLASS(self)->release(self);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*==========================================================================*
 | 
					/*==========================================================================*
 | 
				
			||||||
@@ -281,23 +384,67 @@ gbinder_local_object_handle_release_proc(
 | 
				
			|||||||
GBinderLocalObject*
 | 
					GBinderLocalObject*
 | 
				
			||||||
gbinder_local_object_new(
 | 
					gbinder_local_object_new(
 | 
				
			||||||
    GBinderIpc* ipc,
 | 
					    GBinderIpc* ipc,
 | 
				
			||||||
    const char* iface,
 | 
					    const char* const* ifaces,
 | 
				
			||||||
 | 
					    GBinderLocalTransactFunc txproc,
 | 
				
			||||||
 | 
					    void* user_data) /* Since 1.0.30 */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return gbinder_local_object_new_with_type(GBINDER_TYPE_LOCAL_OBJECT,
 | 
				
			||||||
 | 
					        ipc, ifaces, txproc, user_data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderLocalObject*
 | 
				
			||||||
 | 
					gbinder_local_object_new_with_type(
 | 
				
			||||||
 | 
					    GType type,
 | 
				
			||||||
 | 
					    GBinderIpc* ipc,
 | 
				
			||||||
 | 
					    const char* const* ifaces,
 | 
				
			||||||
 | 
					    GBinderLocalTransactFunc txproc,
 | 
				
			||||||
 | 
					    void* arg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (G_LIKELY(ipc)) {
 | 
				
			||||||
 | 
					        GBinderLocalObject* obj = g_object_new(type, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gbinder_local_object_init_base(obj, ipc, ifaces, txproc, arg);
 | 
				
			||||||
 | 
					        gbinder_ipc_register_local_object(ipc, obj);
 | 
				
			||||||
 | 
					        return obj;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_local_object_init_base(
 | 
				
			||||||
 | 
					    GBinderLocalObject* self,
 | 
				
			||||||
 | 
					    GBinderIpc* ipc,
 | 
				
			||||||
 | 
					    const char* const* ifaces,
 | 
				
			||||||
    GBinderLocalTransactFunc txproc,
 | 
					    GBinderLocalTransactFunc txproc,
 | 
				
			||||||
    void* user_data)
 | 
					    void* user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /* Should only be called from gbinder_ipc_new_local_local_object() */
 | 
					    GBinderLocalObjectPriv* priv = self->priv;
 | 
				
			||||||
    if (G_LIKELY(ipc)) {
 | 
					    guint i = 0, n = gutil_strv_length((char**)ifaces);
 | 
				
			||||||
        GBinderLocalObject* self = g_object_new
 | 
					    gboolean append_base_interface;
 | 
				
			||||||
            (GBINDER_TYPE_LOCAL_OBJECT, NULL);
 | 
					 | 
				
			||||||
        GBinderLocalObjectPriv* priv = self->priv;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self->ipc = gbinder_ipc_ref(ipc);
 | 
					    if (g_strcmp0(gutil_strv_last((char**)ifaces), hidl_base_interface)) {
 | 
				
			||||||
        self->iface = priv->iface = g_strdup(iface);
 | 
					        append_base_interface = TRUE;
 | 
				
			||||||
        priv->txproc = txproc;
 | 
					        n++;
 | 
				
			||||||
        priv->user_data = user_data;
 | 
					    } else {
 | 
				
			||||||
        return self;
 | 
					        append_base_interface = FALSE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return NULL;
 | 
					
 | 
				
			||||||
 | 
					    priv->ifaces = g_new(char*, n + 1);
 | 
				
			||||||
 | 
					    if (ifaces) {
 | 
				
			||||||
 | 
					        while (*ifaces) {
 | 
				
			||||||
 | 
					            priv->ifaces[i++] = g_strdup(*ifaces++);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (append_base_interface) {
 | 
				
			||||||
 | 
					        priv->ifaces[i++] = g_strdup(hidl_base_interface);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    priv->ifaces[i] = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    self->ipc = gbinder_ipc_ref(ipc);
 | 
				
			||||||
 | 
					    self->ifaces = (const char**)priv->ifaces;
 | 
				
			||||||
 | 
					    self->stability = GBINDER_STABILITY_SYSTEM;
 | 
				
			||||||
 | 
					    priv->txproc = txproc;
 | 
				
			||||||
 | 
					    priv->user_data = user_data;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderLocalObject*
 | 
					GBinderLocalObject*
 | 
				
			||||||
@@ -326,11 +473,7 @@ gbinder_local_object_drop(
 | 
				
			|||||||
    GBinderLocalObject* self)
 | 
					    GBinderLocalObject* self)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (G_LIKELY(self)) {
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
        GBinderLocalObjectPriv* priv = self->priv;
 | 
					        GBINDER_LOCAL_OBJECT_GET_CLASS(self)->drop(self);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        /* Clear the transaction callback */
 | 
					 | 
				
			||||||
        priv->txproc = NULL;
 | 
					 | 
				
			||||||
        priv->user_data = NULL;
 | 
					 | 
				
			||||||
        g_object_unref(GBINDER_LOCAL_OBJECT(self));
 | 
					        g_object_unref(GBINDER_LOCAL_OBJECT(self));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -340,7 +483,7 @@ gbinder_local_object_new_reply(
 | 
				
			|||||||
    GBinderLocalObject* self)
 | 
					    GBinderLocalObject* self)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (G_LIKELY(self)) {
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
        return gbinder_local_reply_new(gbinder_local_object_io(self));
 | 
					        return gbinder_local_object_create_reply(self);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -424,32 +567,59 @@ void
 | 
				
			|||||||
gbinder_local_object_handle_increfs(
 | 
					gbinder_local_object_handle_increfs(
 | 
				
			||||||
    GBinderLocalObject* self)
 | 
					    GBinderLocalObject* self)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    gbinder_local_object_handle_later(self,
 | 
					    gbinder_local_object_handle_later(self, gbinder_local_object_increfs_proc);
 | 
				
			||||||
        gbinder_local_object_handle_increfs_proc);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_local_object_handle_decrefs(
 | 
					gbinder_local_object_handle_decrefs(
 | 
				
			||||||
    GBinderLocalObject* self)
 | 
					    GBinderLocalObject* self)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    gbinder_local_object_handle_later(self,
 | 
					    gbinder_local_object_handle_later(self, gbinder_local_object_decrefs_proc);
 | 
				
			||||||
        gbinder_local_object_handle_decrefs_proc);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_local_object_handle_acquire(
 | 
					gbinder_local_object_handle_acquire(
 | 
				
			||||||
    GBinderLocalObject* self)
 | 
					    GBinderLocalObject* self,
 | 
				
			||||||
 | 
					    GBinderBufferContentsList* bufs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    gbinder_local_object_handle_later(self,
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
        gbinder_local_object_handle_acquire_proc);
 | 
					        GBinderLocalObjectAcquireData* data =
 | 
				
			||||||
 | 
					            g_slice_new(GBinderLocalObjectAcquireData);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /*
 | 
				
			||||||
 | 
					         * This is a bit complicated :)
 | 
				
			||||||
 | 
					         * GBinderProxyObject derived from GBinderLocalObject acquires a
 | 
				
			||||||
 | 
					         * reference to the remote object in addition to performing the
 | 
				
			||||||
 | 
					         * default GBinderLocalObject action later on the main thread.
 | 
				
			||||||
 | 
					         * We must ensure that remote object doesn't go away before we
 | 
				
			||||||
 | 
					         * acquire our reference to it. One of the references to that
 | 
				
			||||||
 | 
					         * remote object (possibly the last one) may be associated with
 | 
				
			||||||
 | 
					         * the transaction buffer contained in GBinderBufferContentsList.
 | 
				
			||||||
 | 
					         * We don't know exactly which one we need, so we keep all those
 | 
				
			||||||
 | 
					         * buffers alive until we are done with BR_ACQUIRE.
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        data->object = gbinder_local_object_ref(self);
 | 
				
			||||||
 | 
					        data->bufs = gbinder_buffer_contents_list_dup(bufs);
 | 
				
			||||||
 | 
					        gbinder_idle_callback_invoke_later(gbinder_local_object_acquire_proc,
 | 
				
			||||||
 | 
					            data, gbinder_local_object_acquire_done);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_local_object_handle_release(
 | 
					gbinder_local_object_handle_release(
 | 
				
			||||||
    GBinderLocalObject* self)
 | 
					    GBinderLocalObject* self)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    gbinder_local_object_handle_later(self,
 | 
					    gbinder_local_object_handle_later(self, gbinder_local_object_release_proc);
 | 
				
			||||||
        gbinder_local_object_handle_release_proc);
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_local_object_set_stability(
 | 
				
			||||||
 | 
					    GBinderLocalObject* self,
 | 
				
			||||||
 | 
					    GBINDER_STABILITY_LEVEL stability) /* Since 1.1.40 */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
 | 
					        self->stability = stability;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*==========================================================================*
 | 
					/*==========================================================================*
 | 
				
			||||||
@@ -464,32 +634,33 @@ gbinder_local_object_init(
 | 
				
			|||||||
    GBinderLocalObjectPriv* priv = G_TYPE_INSTANCE_GET_PRIVATE(self,
 | 
					    GBinderLocalObjectPriv* priv = G_TYPE_INSTANCE_GET_PRIVATE(self,
 | 
				
			||||||
        GBINDER_TYPE_LOCAL_OBJECT, GBinderLocalObjectPriv);
 | 
					        GBINDER_TYPE_LOCAL_OBJECT, GBinderLocalObjectPriv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    priv->context = g_main_context_default();
 | 
					 | 
				
			||||||
    self->priv = priv;
 | 
					    self->priv = priv;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_local_object_dispose(
 | 
					gbinder_local_object_dispose(
 | 
				
			||||||
    GObject* local)
 | 
					    GObject* object)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(local);
 | 
					    GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(object);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    gbinder_ipc_local_object_disposed(self->ipc, self);
 | 
					    gbinder_ipc_local_object_disposed(self->ipc, self);
 | 
				
			||||||
    G_OBJECT_CLASS(gbinder_local_object_parent_class)->dispose(local);
 | 
					    G_OBJECT_CLASS(PARENT_CLASS)->dispose(object);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_local_object_finalize(
 | 
					gbinder_local_object_finalize(
 | 
				
			||||||
    GObject* local)
 | 
					    GObject* object)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(local);
 | 
					    GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(object);
 | 
				
			||||||
    GBinderLocalObjectPriv* priv = self->priv;
 | 
					    GBinderLocalObjectPriv* priv = self->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    GASSERT(!self->strong_refs);
 | 
				
			||||||
 | 
					    gbinder_ipc_invalidate_local_object(self->ipc, self);
 | 
				
			||||||
    gbinder_ipc_unref(self->ipc);
 | 
					    gbinder_ipc_unref(self->ipc);
 | 
				
			||||||
    g_free(priv->iface);
 | 
					    g_strfreev(priv->ifaces);
 | 
				
			||||||
    G_OBJECT_CLASS(gbinder_local_object_parent_class)->finalize(local);
 | 
					    G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
@@ -509,6 +680,9 @@ gbinder_local_object_class_init(
 | 
				
			|||||||
        gbinder_local_object_default_handle_looper_transaction;
 | 
					        gbinder_local_object_default_handle_looper_transaction;
 | 
				
			||||||
    klass->can_handle_transaction =
 | 
					    klass->can_handle_transaction =
 | 
				
			||||||
        gbinder_local_object_default_can_handle_transaction;
 | 
					        gbinder_local_object_default_can_handle_transaction;
 | 
				
			||||||
 | 
					    klass->acquire = gbinder_local_object_default_acquire;
 | 
				
			||||||
 | 
					    klass->release = gbinder_local_object_default_release;
 | 
				
			||||||
 | 
					    klass->drop = gbinder_local_object_default_drop;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    gbinder_local_object_signals[SIGNAL_WEAK_REFS_CHANGED] =
 | 
					    gbinder_local_object_signals[SIGNAL_WEAK_REFS_CHANGED] =
 | 
				
			||||||
        g_signal_new(SIGNAL_WEAK_REFS_CHANGED_NAME,
 | 
					        g_signal_new(SIGNAL_WEAK_REFS_CHANGED_NAME,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -40,8 +40,9 @@
 | 
				
			|||||||
#include <glib-object.h>
 | 
					#include <glib-object.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Some if this stuff may become public if we decide to allow the clients
 | 
					 * Some of this stuff may become public if we decide to allow the clients
 | 
				
			||||||
 * to derive their classes from GBinderLocalObject
 | 
					 * to derive their own classes from GBinderLocalObject. For now it's all
 | 
				
			||||||
 | 
					 * private.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef
 | 
					typedef
 | 
				
			||||||
@@ -55,9 +56,10 @@ struct gbinder_local_object {
 | 
				
			|||||||
    GObject object;
 | 
					    GObject object;
 | 
				
			||||||
    GBinderLocalObjectPriv* priv;
 | 
					    GBinderLocalObjectPriv* priv;
 | 
				
			||||||
    GBinderIpc* ipc;
 | 
					    GBinderIpc* ipc;
 | 
				
			||||||
    const char* iface;
 | 
					    const char* const* ifaces;
 | 
				
			||||||
    gint weak_refs;
 | 
					    gint weak_refs;
 | 
				
			||||||
    gint strong_refs;
 | 
					    gint strong_refs;
 | 
				
			||||||
 | 
					    GBINDER_STABILITY_LEVEL stability;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef enum gbinder_local_transaction_support {
 | 
					typedef enum gbinder_local_transaction_support {
 | 
				
			||||||
@@ -76,47 +78,68 @@ typedef struct gbinder_local_object_class {
 | 
				
			|||||||
    GBinderLocalReply* (*handle_looper_transaction)
 | 
					    GBinderLocalReply* (*handle_looper_transaction)
 | 
				
			||||||
        (GBinderLocalObject* self, GBinderRemoteRequest* req, guint code,
 | 
					        (GBinderLocalObject* self, GBinderRemoteRequest* req, guint code,
 | 
				
			||||||
            guint flags, int* status);
 | 
					            guint flags, int* status);
 | 
				
			||||||
 | 
					    void (*acquire)(GBinderLocalObject* self);
 | 
				
			||||||
 | 
					    void (*release)(GBinderLocalObject* self);
 | 
				
			||||||
 | 
					    void (*drop)(GBinderLocalObject* self);
 | 
				
			||||||
    /* Need to add some placeholders if this class becomes public */
 | 
					    /* Need to add some placeholders if this class becomes public */
 | 
				
			||||||
} GBinderLocalObjectClass;
 | 
					} GBinderLocalObjectClass;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GType gbinder_local_object_get_type(void);
 | 
					GType gbinder_local_object_get_type(void) GBINDER_INTERNAL;
 | 
				
			||||||
#define GBINDER_TYPE_LOCAL_OBJECT (gbinder_local_object_get_type())
 | 
					#define GBINDER_TYPE_LOCAL_OBJECT (gbinder_local_object_get_type())
 | 
				
			||||||
#define GBINDER_LOCAL_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
 | 
					#define GBINDER_LOCAL_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
 | 
				
			||||||
        GBINDER_TYPE_LOCAL_OBJECT, GBinderLocalObject))
 | 
					        GBINDER_TYPE_LOCAL_OBJECT, GBinderLocalObject))
 | 
				
			||||||
 | 
					#define GBINDER_LOCAL_OBJECT_CLASS(klass) G_TYPE_CHECK_CLASS_CAST((klass), \
 | 
				
			||||||
 | 
					        GBINDER_TYPE_LOCAL_OBJECT, GBinderLocalObjectClass)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define gbinder_local_object_dev(obj) (gbinder_driver_dev((obj)->ipc->driver))
 | 
					#define gbinder_local_object_dev(obj) (gbinder_driver_dev((obj)->ipc->driver))
 | 
				
			||||||
#define gbinder_local_object_io(obj) (gbinder_driver_io((obj)->ipc->driver))
 | 
					#define gbinder_local_object_io(obj) (gbinder_driver_io((obj)->ipc->driver))
 | 
				
			||||||
 | 
					#define gbinder_local_object_protocol(obj) \
 | 
				
			||||||
 | 
					    (gbinder_driver_protocol((obj)->ipc->driver))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Should only be called from gbinder_ipc_new_local_object() */
 | 
					 | 
				
			||||||
GBinderLocalObject*
 | 
					GBinderLocalObject*
 | 
				
			||||||
gbinder_local_object_new(
 | 
					gbinder_local_object_new_with_type(
 | 
				
			||||||
 | 
					    GType type,
 | 
				
			||||||
    GBinderIpc* ipc,
 | 
					    GBinderIpc* ipc,
 | 
				
			||||||
    const char* iface,
 | 
					    const char* const* ifaces,
 | 
				
			||||||
    GBinderLocalTransactFunc handler,
 | 
					    GBinderLocalTransactFunc txproc,
 | 
				
			||||||
    void* user_data);
 | 
					    void* user_data)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_local_object_init_base(
 | 
				
			||||||
 | 
					    GBinderLocalObject* self,
 | 
				
			||||||
 | 
					    GBinderIpc* ipc,
 | 
				
			||||||
 | 
					    const char* const* ifaces,
 | 
				
			||||||
 | 
					    GBinderLocalTransactFunc txproc,
 | 
				
			||||||
 | 
					    void* user_data)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gulong
 | 
					gulong
 | 
				
			||||||
gbinder_local_object_add_weak_refs_changed_handler(
 | 
					gbinder_local_object_add_weak_refs_changed_handler(
 | 
				
			||||||
    GBinderLocalObject* obj,
 | 
					    GBinderLocalObject* obj,
 | 
				
			||||||
    GBinderLocalObjectFunc func,
 | 
					    GBinderLocalObjectFunc func,
 | 
				
			||||||
    void* user_data);
 | 
					    void* user_data)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gulong
 | 
					gulong
 | 
				
			||||||
gbinder_local_object_add_strong_refs_changed_handler(
 | 
					gbinder_local_object_add_strong_refs_changed_handler(
 | 
				
			||||||
    GBinderLocalObject* obj,
 | 
					    GBinderLocalObject* obj,
 | 
				
			||||||
    GBinderLocalObjectFunc func,
 | 
					    GBinderLocalObjectFunc func,
 | 
				
			||||||
    void* user_data);
 | 
					    void* user_data)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_local_object_remove_handler(
 | 
					gbinder_local_object_remove_handler(
 | 
				
			||||||
    GBinderLocalObject* obj,
 | 
					    GBinderLocalObject* obj,
 | 
				
			||||||
    gulong id);
 | 
					    gulong id)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBINDER_LOCAL_TRANSACTION_SUPPORT
 | 
					GBINDER_LOCAL_TRANSACTION_SUPPORT
 | 
				
			||||||
gbinder_local_object_can_handle_transaction(
 | 
					gbinder_local_object_can_handle_transaction(
 | 
				
			||||||
    GBinderLocalObject* self,
 | 
					    GBinderLocalObject* self,
 | 
				
			||||||
    const char* iface,
 | 
					    const char* iface,
 | 
				
			||||||
    guint code);
 | 
					    guint code)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderLocalReply*
 | 
					GBinderLocalReply*
 | 
				
			||||||
gbinder_local_object_handle_transaction(
 | 
					gbinder_local_object_handle_transaction(
 | 
				
			||||||
@@ -124,7 +147,8 @@ gbinder_local_object_handle_transaction(
 | 
				
			|||||||
    GBinderRemoteRequest* req,
 | 
					    GBinderRemoteRequest* req,
 | 
				
			||||||
    guint code,
 | 
					    guint code,
 | 
				
			||||||
    guint flags,
 | 
					    guint flags,
 | 
				
			||||||
    int* status);
 | 
					    int* status)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderLocalReply*
 | 
					GBinderLocalReply*
 | 
				
			||||||
gbinder_local_object_handle_looper_transaction(
 | 
					gbinder_local_object_handle_looper_transaction(
 | 
				
			||||||
@@ -132,23 +156,29 @@ gbinder_local_object_handle_looper_transaction(
 | 
				
			|||||||
    GBinderRemoteRequest* req,
 | 
					    GBinderRemoteRequest* req,
 | 
				
			||||||
    guint code,
 | 
					    guint code,
 | 
				
			||||||
    guint flags,
 | 
					    guint flags,
 | 
				
			||||||
    int* status);
 | 
					    int* status)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_local_object_handle_increfs(
 | 
					gbinder_local_object_handle_increfs(
 | 
				
			||||||
    GBinderLocalObject* obj);
 | 
					    GBinderLocalObject* obj)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_local_object_handle_decrefs(
 | 
					gbinder_local_object_handle_decrefs(
 | 
				
			||||||
    GBinderLocalObject* obj);
 | 
					    GBinderLocalObject* obj)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_local_object_handle_acquire(
 | 
					gbinder_local_object_handle_acquire(
 | 
				
			||||||
    GBinderLocalObject* obj);
 | 
					    GBinderLocalObject* obj,
 | 
				
			||||||
 | 
					    GBinderBufferContentsList* bufs)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_local_object_handle_release(
 | 
					gbinder_local_object_handle_release(
 | 
				
			||||||
    GBinderLocalObject* obj);
 | 
					    GBinderLocalObject* obj)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* GBINDER_LOCAL_OBJECT_PRIVATE_H */
 | 
					#endif /* GBINDER_LOCAL_OBJECT_PRIVATE_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
				
			||||||
 * Contact: Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -33,6 +33,7 @@
 | 
				
			|||||||
#include "gbinder_local_reply_p.h"
 | 
					#include "gbinder_local_reply_p.h"
 | 
				
			||||||
#include "gbinder_output_data.h"
 | 
					#include "gbinder_output_data.h"
 | 
				
			||||||
#include "gbinder_writer_p.h"
 | 
					#include "gbinder_writer_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_buffer_p.h"
 | 
				
			||||||
#include "gbinder_log.h"
 | 
					#include "gbinder_log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <gutil_intarray.h>
 | 
					#include <gutil_intarray.h>
 | 
				
			||||||
@@ -42,6 +43,7 @@ struct gbinder_local_reply {
 | 
				
			|||||||
    gint refcount;
 | 
					    gint refcount;
 | 
				
			||||||
    GBinderWriterData data;
 | 
					    GBinderWriterData data;
 | 
				
			||||||
    GBinderOutputData out;
 | 
					    GBinderOutputData out;
 | 
				
			||||||
 | 
					    GBinderBufferContents* contents;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBINDER_INLINE_FUNC
 | 
					GBINDER_INLINE_FUNC
 | 
				
			||||||
@@ -70,10 +72,12 @@ gbinder_local_reply_output_buffers_size(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
GBinderLocalReply*
 | 
					GBinderLocalReply*
 | 
				
			||||||
gbinder_local_reply_new(
 | 
					gbinder_local_reply_new(
 | 
				
			||||||
    const GBinderIo* io)
 | 
					    const GBinderIo* io,
 | 
				
			||||||
 | 
					    const GBinderRpcProtocol* protocol)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GASSERT(io);
 | 
					    GASSERT(io);
 | 
				
			||||||
    if (io) {
 | 
					    GASSERT(protocol);
 | 
				
			||||||
 | 
					    if (io && protocol) {
 | 
				
			||||||
        GBinderLocalReply* self = g_slice_new0(GBinderLocalReply);
 | 
					        GBinderLocalReply* self = g_slice_new0(GBinderLocalReply);
 | 
				
			||||||
        GBinderWriterData* data = &self->data;
 | 
					        GBinderWriterData* data = &self->data;
 | 
				
			||||||
        GBinderOutputData* out = &self->out;
 | 
					        GBinderOutputData* out = &self->out;
 | 
				
			||||||
@@ -85,6 +89,7 @@ gbinder_local_reply_new(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        g_atomic_int_set(&self->refcount, 1);
 | 
					        g_atomic_int_set(&self->refcount, 1);
 | 
				
			||||||
        data->io = io;
 | 
					        data->io = io;
 | 
				
			||||||
 | 
					        data->protocol = protocol;
 | 
				
			||||||
        out->bytes = data->bytes = g_byte_array_new();
 | 
					        out->bytes = data->bytes = g_byte_array_new();
 | 
				
			||||||
        out->f = &local_reply_output_fn;
 | 
					        out->f = &local_reply_output_fn;
 | 
				
			||||||
        return self;
 | 
					        return self;
 | 
				
			||||||
@@ -92,6 +97,21 @@ gbinder_local_reply_new(
 | 
				
			|||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderLocalReply*
 | 
				
			||||||
 | 
					gbinder_local_reply_set_contents(
 | 
				
			||||||
 | 
					    GBinderLocalReply* self,
 | 
				
			||||||
 | 
					    GBinderBuffer* buffer,
 | 
				
			||||||
 | 
					    GBinderObjectConverter* convert)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (self) {
 | 
				
			||||||
 | 
					        gbinder_writer_data_set_contents(&self->data, buffer, convert);
 | 
				
			||||||
 | 
					        gbinder_buffer_contents_unref(self->contents);
 | 
				
			||||||
 | 
					        self->contents = gbinder_buffer_contents_ref
 | 
				
			||||||
 | 
					            (gbinder_buffer_contents(buffer));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return self;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_local_reply_free(
 | 
					gbinder_local_reply_free(
 | 
				
			||||||
@@ -102,7 +122,8 @@ gbinder_local_reply_free(
 | 
				
			|||||||
    gutil_int_array_free(data->offsets, TRUE);
 | 
					    gutil_int_array_free(data->offsets, TRUE);
 | 
				
			||||||
    g_byte_array_free(data->bytes, TRUE);
 | 
					    g_byte_array_free(data->bytes, TRUE);
 | 
				
			||||||
    gbinder_cleanup_free(data->cleanup);
 | 
					    gbinder_cleanup_free(data->cleanup);
 | 
				
			||||||
    g_slice_free(GBinderLocalReply, self);
 | 
					    gbinder_buffer_contents_unref(self->contents);
 | 
				
			||||||
 | 
					    gutil_slice_free(self);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderLocalReply*
 | 
					GBinderLocalReply*
 | 
				
			||||||
@@ -135,6 +156,13 @@ gbinder_local_reply_data(
 | 
				
			|||||||
    return G_LIKELY(self) ? &self->out :  NULL;
 | 
					    return G_LIKELY(self) ? &self->out :  NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderBufferContents*
 | 
				
			||||||
 | 
					gbinder_local_reply_contents(
 | 
				
			||||||
 | 
					    GBinderLocalReply* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return G_LIKELY(self) ? self->contents :  NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_local_reply_cleanup(
 | 
					gbinder_local_reply_cleanup(
 | 
				
			||||||
    GBinderLocalReply* self,
 | 
					    GBinderLocalReply* self,
 | 
				
			||||||
@@ -282,6 +310,17 @@ gbinder_local_reply_append_remote_object(
 | 
				
			|||||||
    return self;
 | 
					    return self;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderLocalReply*
 | 
				
			||||||
 | 
					gbinder_local_reply_append_fd(
 | 
				
			||||||
 | 
					    GBinderLocalReply* self,
 | 
				
			||||||
 | 
					    int fd) /* Since 1.1.14 */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
 | 
					        gbinder_writer_data_append_fd(&self->data, fd);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return self;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Local Variables:
 | 
					 * Local Variables:
 | 
				
			||||||
 * mode: C
 | 
					 * mode: C
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
				
			||||||
 * Contact: Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -39,11 +39,26 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
GBinderLocalReply*
 | 
					GBinderLocalReply*
 | 
				
			||||||
gbinder_local_reply_new(
 | 
					gbinder_local_reply_new(
 | 
				
			||||||
    const GBinderIo* io);
 | 
					    const GBinderIo* io,
 | 
				
			||||||
 | 
					    const GBinderRpcProtocol* protocol)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderOutputData*
 | 
					GBinderOutputData*
 | 
				
			||||||
gbinder_local_reply_data(
 | 
					gbinder_local_reply_data(
 | 
				
			||||||
    GBinderLocalReply* reply);
 | 
					    GBinderLocalReply* reply)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderBufferContents*
 | 
				
			||||||
 | 
					gbinder_local_reply_contents(
 | 
				
			||||||
 | 
					    GBinderLocalReply* reply)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderLocalReply*
 | 
				
			||||||
 | 
					gbinder_local_reply_set_contents(
 | 
				
			||||||
 | 
					    GBinderLocalReply* reply,
 | 
				
			||||||
 | 
					    GBinderBuffer* buffer,
 | 
				
			||||||
 | 
					    GBinderObjectConverter* convert)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* GBINDER_LOCAL_REPLY_PRIVATE_H */
 | 
					#endif /* GBINDER_LOCAL_REPLY_PRIVATE_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
				
			||||||
 * Contact: Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -31,8 +31,11 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "gbinder_local_request_p.h"
 | 
					#include "gbinder_local_request_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_rpc_protocol.h"
 | 
				
			||||||
#include "gbinder_output_data.h"
 | 
					#include "gbinder_output_data.h"
 | 
				
			||||||
#include "gbinder_writer_p.h"
 | 
					#include "gbinder_writer_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_buffer_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_io.h"
 | 
				
			||||||
#include "gbinder_log.h"
 | 
					#include "gbinder_log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <gutil_intarray.h>
 | 
					#include <gutil_intarray.h>
 | 
				
			||||||
@@ -71,10 +74,12 @@ gbinder_local_request_output_buffers_size(
 | 
				
			|||||||
GBinderLocalRequest*
 | 
					GBinderLocalRequest*
 | 
				
			||||||
gbinder_local_request_new(
 | 
					gbinder_local_request_new(
 | 
				
			||||||
    const GBinderIo* io,
 | 
					    const GBinderIo* io,
 | 
				
			||||||
 | 
					    const GBinderRpcProtocol* protocol,
 | 
				
			||||||
    GBytes* init)
 | 
					    GBytes* init)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GASSERT(io);
 | 
					    GASSERT(io);
 | 
				
			||||||
    if (io) {
 | 
					    GASSERT(protocol);
 | 
				
			||||||
 | 
					    if (io && protocol) {
 | 
				
			||||||
        GBinderLocalRequest* self = g_slice_new0(GBinderLocalRequest);
 | 
					        GBinderLocalRequest* self = g_slice_new0(GBinderLocalRequest);
 | 
				
			||||||
        GBinderWriterData* writer = &self->data;
 | 
					        GBinderWriterData* writer = &self->data;
 | 
				
			||||||
        GBinderOutputData* out = &self->out;
 | 
					        GBinderOutputData* out = &self->out;
 | 
				
			||||||
@@ -86,9 +91,11 @@ gbinder_local_request_new(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        g_atomic_int_set(&self->refcount, 1);
 | 
					        g_atomic_int_set(&self->refcount, 1);
 | 
				
			||||||
        writer->io = io;
 | 
					        writer->io = io;
 | 
				
			||||||
 | 
					        writer->protocol = protocol;
 | 
				
			||||||
        if (init) {
 | 
					        if (init) {
 | 
				
			||||||
            gsize size;
 | 
					            gsize size;
 | 
				
			||||||
            gconstpointer data = g_bytes_get_data(init, &size);
 | 
					            gconstpointer data = g_bytes_get_data(init, &size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            writer->bytes = g_byte_array_sized_new(size);
 | 
					            writer->bytes = g_byte_array_sized_new(size);
 | 
				
			||||||
            g_byte_array_append(writer->bytes, data, size);
 | 
					            g_byte_array_append(writer->bytes, data, size);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
@@ -101,6 +108,50 @@ gbinder_local_request_new(
 | 
				
			|||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderLocalRequest*
 | 
				
			||||||
 | 
					gbinder_local_request_new_iface(
 | 
				
			||||||
 | 
					    const GBinderIo* io,
 | 
				
			||||||
 | 
					    const GBinderRpcProtocol* protocol,
 | 
				
			||||||
 | 
					    const char* iface)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderLocalRequest* self = gbinder_local_request_new(io, protocol, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* gbinder_local_request_new() fails if protocol is NULL */
 | 
				
			||||||
 | 
					    if (self && G_LIKELY(iface)) {
 | 
				
			||||||
 | 
					        GBinderWriter writer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gbinder_local_request_init_writer(self, &writer);
 | 
				
			||||||
 | 
					        protocol->write_rpc_header(&writer, iface);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return self;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderLocalRequest*
 | 
				
			||||||
 | 
					gbinder_local_request_new_from_data(
 | 
				
			||||||
 | 
					    GBinderBuffer* buffer,
 | 
				
			||||||
 | 
					    GBinderObjectConverter* convert)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderLocalRequest* self = gbinder_local_request_new
 | 
				
			||||||
 | 
					        (gbinder_buffer_io(buffer), gbinder_buffer_protocol(buffer), NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (self) {
 | 
				
			||||||
 | 
					        gbinder_writer_data_append_contents(&self->data, buffer, 0, convert);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return self;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_local_request_append_contents(
 | 
				
			||||||
 | 
					    GBinderLocalRequest* self,
 | 
				
			||||||
 | 
					    GBinderBuffer* buffer,
 | 
				
			||||||
 | 
					    gsize off,
 | 
				
			||||||
 | 
					    GBinderObjectConverter* convert)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (self) {
 | 
				
			||||||
 | 
					        gbinder_writer_data_append_contents(&self->data, buffer, off, convert);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_local_request_free(
 | 
					gbinder_local_request_free(
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
				
			||||||
 * Contact: Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -40,11 +40,35 @@
 | 
				
			|||||||
GBinderLocalRequest*
 | 
					GBinderLocalRequest*
 | 
				
			||||||
gbinder_local_request_new(
 | 
					gbinder_local_request_new(
 | 
				
			||||||
    const GBinderIo* io,
 | 
					    const GBinderIo* io,
 | 
				
			||||||
    GBytes* init);
 | 
					    const GBinderRpcProtocol* protocol,
 | 
				
			||||||
 | 
					    GBytes* init)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderLocalRequest*
 | 
				
			||||||
 | 
					gbinder_local_request_new_iface(
 | 
				
			||||||
 | 
					    const GBinderIo* io,
 | 
				
			||||||
 | 
					    const GBinderRpcProtocol* protocol,
 | 
				
			||||||
 | 
					    const char* iface)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderLocalRequest*
 | 
				
			||||||
 | 
					gbinder_local_request_new_from_data(
 | 
				
			||||||
 | 
					    GBinderBuffer* buffer,
 | 
				
			||||||
 | 
					    GBinderObjectConverter* convert)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderOutputData*
 | 
					GBinderOutputData*
 | 
				
			||||||
gbinder_local_request_data(
 | 
					gbinder_local_request_data(
 | 
				
			||||||
    GBinderLocalRequest* req);
 | 
					    GBinderLocalRequest* req)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_local_request_append_contents(
 | 
				
			||||||
 | 
					    GBinderLocalRequest* req,
 | 
				
			||||||
 | 
					    GBinderBuffer* buffer,
 | 
				
			||||||
 | 
					    gsize offset,
 | 
				
			||||||
 | 
					    GBinderObjectConverter* convert)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* GBINDER_LOCAL_REQUEST_PRIVATE_H */
 | 
					#endif /* GBINDER_LOCAL_REQUEST_PRIVATE_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										62
									
								
								src/gbinder_log.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								src/gbinder_log.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2020 Jolla Ltd.
 | 
				
			||||||
 | 
					 * Copyright (C) 2020 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   1. Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 | 
					 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
				
			||||||
 | 
					 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
				
			||||||
 | 
					 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
				
			||||||
 | 
					 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
				
			||||||
 | 
					 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
				
			||||||
 | 
					 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
				
			||||||
 | 
					 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
				
			||||||
 | 
					 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
				
			||||||
 | 
					 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "gbinder_log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gutil_misc.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Log module */
 | 
				
			||||||
 | 
					GLOG_MODULE_DEFINE("gbinder");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Initializes the default log level at startup */
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_log_init(
 | 
				
			||||||
 | 
					    void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int level = GLOG_MODULE_NAME.level;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (gutil_parse_int(getenv("GBINDER_DEFAULT_LOG_LEVEL"), 0, &level) &&
 | 
				
			||||||
 | 
					        level >= GLOG_LEVEL_INHERIT && level <= GLOG_LEVEL_VERBOSE) {
 | 
				
			||||||
 | 
					        GINFO("Log level %d", level);
 | 
				
			||||||
 | 
					        GLOG_MODULE_NAME.level = level;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Local Variables:
 | 
				
			||||||
 | 
					 * mode: C
 | 
				
			||||||
 | 
					 * c-basic-offset: 4
 | 
				
			||||||
 | 
					 * indent-tabs-mode: nil
 | 
				
			||||||
 | 
					 * End:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2020 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -33,11 +33,21 @@
 | 
				
			|||||||
#ifndef GBINDER_LOG_H
 | 
					#ifndef GBINDER_LOG_H
 | 
				
			||||||
#define GBINDER_LOG_H
 | 
					#define GBINDER_LOG_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "gbinder_types.h"
 | 
					#include "gbinder_types_p.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define GLOG_MODULE_NAME GBINDER_LOG_MODULE
 | 
					#define GLOG_MODULE_NAME GBINDER_LOG_MODULE
 | 
				
			||||||
#include <gutil_log.h>
 | 
					#include <gutil_log.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DBG(fmt, ...) \
 | 
				
			||||||
 | 
					    gutil_log(GLOG_MODULE_CURRENT, GLOG_LEVEL_ALWAYS, "gbinder:"fmt, ##__VA_ARGS__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Declared for unit tests */
 | 
				
			||||||
 | 
					__attribute__((constructor))
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_log_init(
 | 
				
			||||||
 | 
					    void)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* GBINDER_LOG_H */
 | 
					#endif /* GBINDER_LOG_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										67
									
								
								src/gbinder_object_converter.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								src/gbinder_object_converter.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,67 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2021 Jolla Ltd.
 | 
				
			||||||
 | 
					 * Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   1. Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 | 
					 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
				
			||||||
 | 
					 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
				
			||||||
 | 
					 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
				
			||||||
 | 
					 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
				
			||||||
 | 
					 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
				
			||||||
 | 
					 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
				
			||||||
 | 
					 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
				
			||||||
 | 
					 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
				
			||||||
 | 
					 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GBINDER_OBJECT_CONVERTER_H
 | 
				
			||||||
 | 
					#define GBINDER_OBJECT_CONVERTER_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "gbinder_types_p.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_object_converter_functions {
 | 
				
			||||||
 | 
					    GBinderLocalObject* (*handle_to_local)(GBinderObjectConverter*, guint32);
 | 
				
			||||||
 | 
					} GBinderObjectConverterFunctions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gbinder_object_converter {
 | 
				
			||||||
 | 
					    const GBinderObjectConverterFunctions* f;
 | 
				
			||||||
 | 
					    const GBinderIo* io;
 | 
				
			||||||
 | 
					    const GBinderRpcProtocol* protocol;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Inline wrappers */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBINDER_INLINE_FUNC
 | 
				
			||||||
 | 
					GBinderLocalObject*
 | 
				
			||||||
 | 
					gbinder_object_converter_handle_to_local(
 | 
				
			||||||
 | 
					    GBinderObjectConverter* convert,
 | 
				
			||||||
 | 
					    guint32 handle)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return convert ? convert->f->handle_to_local(convert, handle) : NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* GBINDER_OBJECT_CONVERTER_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Local Variables:
 | 
				
			||||||
 | 
					 * mode: C
 | 
				
			||||||
 | 
					 * c-basic-offset: 4
 | 
				
			||||||
 | 
					 * indent-tabs-mode: nil
 | 
				
			||||||
 | 
					 * End:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -35,13 +35,19 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "gbinder_types_p.h"
 | 
					#include "gbinder_types_p.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef enum gbinder_remote_registry_create {
 | 
				
			||||||
 | 
					    REMOTE_REGISTRY_DONT_CREATE,
 | 
				
			||||||
 | 
					    REMOTE_REGISTRY_CAN_CREATE,
 | 
				
			||||||
 | 
					    REMOTE_REGISTRY_CAN_CREATE_AND_ACQUIRE
 | 
				
			||||||
 | 
					} REMOTE_REGISTRY_CREATE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct gbinder_object_registry_functions {
 | 
					typedef struct gbinder_object_registry_functions {
 | 
				
			||||||
    void (*ref)(GBinderObjectRegistry* reg);
 | 
					    void (*ref)(GBinderObjectRegistry* reg);
 | 
				
			||||||
    void (*unref)(GBinderObjectRegistry* reg);
 | 
					    void (*unref)(GBinderObjectRegistry* reg);
 | 
				
			||||||
    GBinderLocalObject* (*get_local)(GBinderObjectRegistry* reg,
 | 
					    GBinderLocalObject* (*get_local)(GBinderObjectRegistry* reg,
 | 
				
			||||||
        void* pointer);
 | 
					        void* pointer);
 | 
				
			||||||
    GBinderRemoteObject* (*get_remote)(GBinderObjectRegistry* reg,
 | 
					    GBinderRemoteObject* (*get_remote)(GBinderObjectRegistry* reg,
 | 
				
			||||||
        guint32 handle);
 | 
					        guint32 handle, REMOTE_REGISTRY_CREATE create);
 | 
				
			||||||
} GBinderObjectRegistryFunctions;
 | 
					} GBinderObjectRegistryFunctions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct gbinder_object_registry {
 | 
					struct gbinder_object_registry {
 | 
				
			||||||
@@ -81,9 +87,10 @@ GBINDER_INLINE_FUNC
 | 
				
			|||||||
GBinderRemoteObject*
 | 
					GBinderRemoteObject*
 | 
				
			||||||
gbinder_object_registry_get_remote(
 | 
					gbinder_object_registry_get_remote(
 | 
				
			||||||
    GBinderObjectRegistry* reg,
 | 
					    GBinderObjectRegistry* reg,
 | 
				
			||||||
    guint32 handle)
 | 
					    guint32 handle,
 | 
				
			||||||
 | 
					    REMOTE_REGISTRY_CREATE create)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return reg ? reg->f->get_remote(reg, handle) : NULL;
 | 
					    return reg ? reg->f->get_remote(reg, handle, create) : NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* GBINDER_OBJECT_REGISTRY_H */
 | 
					#endif /* GBINDER_OBJECT_REGISTRY_H */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2020 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										420
									
								
								src/gbinder_proxy_object.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										420
									
								
								src/gbinder_proxy_object.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,420 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2021-2022 Jolla Ltd.
 | 
				
			||||||
 | 
					 * Copyright (C) 2021-2023 Slava Monich <slava@monich.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   1. Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 | 
					 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
				
			||||||
 | 
					 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
				
			||||||
 | 
					 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
				
			||||||
 | 
					 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
				
			||||||
 | 
					 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
				
			||||||
 | 
					 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
				
			||||||
 | 
					 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
				
			||||||
 | 
					 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
				
			||||||
 | 
					 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "gbinder_proxy_object.h"
 | 
				
			||||||
 | 
					#include "gbinder_local_object_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_local_request.h"
 | 
				
			||||||
 | 
					#include "gbinder_local_reply.h"
 | 
				
			||||||
 | 
					#include "gbinder_remote_object_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_remote_request_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_remote_reply_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_object_converter.h"
 | 
				
			||||||
 | 
					#include "gbinder_object_registry.h"
 | 
				
			||||||
 | 
					#include "gbinder_driver.h"
 | 
				
			||||||
 | 
					#include "gbinder_ipc.h"
 | 
				
			||||||
 | 
					#include "gbinder_log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gutil_macros.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef GBinderLocalObjectClass GBinderProxyObjectClass;
 | 
				
			||||||
 | 
					typedef struct gbinder_proxy_tx GBinderProxyTx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gbinder_proxy_tx {
 | 
				
			||||||
 | 
					    GBinderProxyTx* next;
 | 
				
			||||||
 | 
					    GBinderRemoteRequest* req;
 | 
				
			||||||
 | 
					    GBinderProxyObject* proxy;
 | 
				
			||||||
 | 
					    gulong id;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gbinder_proxy_object_priv {
 | 
				
			||||||
 | 
					    gboolean acquired;
 | 
				
			||||||
 | 
					    gboolean dropped;
 | 
				
			||||||
 | 
					    GBinderProxyTx* tx;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					G_DEFINE_TYPE(GBinderProxyObject, gbinder_proxy_object, \
 | 
				
			||||||
 | 
					    GBINDER_TYPE_LOCAL_OBJECT)
 | 
				
			||||||
 | 
					#define GBINDER_IS_PROXY_OBJECT(obj) G_TYPE_CHECK_INSTANCE_TYPE(obj, \
 | 
				
			||||||
 | 
					    GBINDER_TYPE_PROXY_OBJECT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define THIS(obj) GBINDER_PROXY_OBJECT(obj)
 | 
				
			||||||
 | 
					#define THIS_TYPE GBINDER_TYPE_PROXY_OBJECT
 | 
				
			||||||
 | 
					#define PARENT_CLASS gbinder_proxy_object_parent_class
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*==========================================================================*
 | 
				
			||||||
 | 
					 * Converter
 | 
				
			||||||
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_proxy_object_converter {
 | 
				
			||||||
 | 
					    GBinderObjectConverter pub;
 | 
				
			||||||
 | 
					    GBinderIpc* remote;
 | 
				
			||||||
 | 
					    GBinderIpc* local;
 | 
				
			||||||
 | 
					} GBinderProxyObjectConverter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBINDER_INLINE_FUNC
 | 
				
			||||||
 | 
					GBinderProxyObjectConverter*
 | 
				
			||||||
 | 
					gbinder_proxy_object_converter_cast(
 | 
				
			||||||
 | 
					    GBinderObjectConverter* pub)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return G_CAST(pub, GBinderProxyObjectConverter, pub);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_proxy_object_converter_check(
 | 
				
			||||||
 | 
					    GBinderLocalObject* obj,
 | 
				
			||||||
 | 
					    void* remote)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (GBINDER_IS_PROXY_OBJECT(obj) && THIS(obj)->remote == remote) {
 | 
				
			||||||
 | 
					        /* Found matching proxy object */
 | 
				
			||||||
 | 
					        return TRUE;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    /* Keep looking */
 | 
				
			||||||
 | 
					    return FALSE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					GBinderLocalObject*
 | 
				
			||||||
 | 
					gbinder_proxy_object_converter_handle_to_local(
 | 
				
			||||||
 | 
					    GBinderObjectConverter* pub,
 | 
				
			||||||
 | 
					    guint32 handle)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderProxyObjectConverter* c = gbinder_proxy_object_converter_cast(pub);
 | 
				
			||||||
 | 
					    GBinderObjectRegistry* reg = gbinder_ipc_object_registry(c->remote);
 | 
				
			||||||
 | 
					    GBinderRemoteObject* remote = gbinder_object_registry_get_remote(reg,
 | 
				
			||||||
 | 
					        handle, REMOTE_REGISTRY_CAN_CREATE /* but don't acquire */);
 | 
				
			||||||
 | 
					    GBinderLocalObject* local = gbinder_ipc_find_local_object(c->local,
 | 
				
			||||||
 | 
					        gbinder_proxy_object_converter_check, remote);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!local && !remote->dead) {
 | 
				
			||||||
 | 
					        /* GBinderProxyObject will reference GBinderRemoteObject */
 | 
				
			||||||
 | 
					        local = &gbinder_proxy_object_new(c->local, remote)->parent;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Release the reference returned by gbinder_object_registry_get_remote */
 | 
				
			||||||
 | 
					    gbinder_remote_object_unref(remote);
 | 
				
			||||||
 | 
					    return local;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_proxy_object_converter_init(
 | 
				
			||||||
 | 
					    GBinderProxyObjectConverter* convert,
 | 
				
			||||||
 | 
					    GBinderProxyObject* proxy,
 | 
				
			||||||
 | 
					    GBinderIpc* remote,
 | 
				
			||||||
 | 
					    GBinderIpc* local)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static const GBinderObjectConverterFunctions gbinder_converter_fn = {
 | 
				
			||||||
 | 
					        .handle_to_local = gbinder_proxy_object_converter_handle_to_local
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    GBinderObjectConverter* pub = &convert->pub;
 | 
				
			||||||
 | 
					    GBinderIpc* dest = proxy->parent.ipc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    memset(convert, 0, sizeof(*convert));
 | 
				
			||||||
 | 
					    convert->remote = remote;
 | 
				
			||||||
 | 
					    convert->local = local;
 | 
				
			||||||
 | 
					    pub->f = &gbinder_converter_fn;
 | 
				
			||||||
 | 
					    pub->io = gbinder_ipc_io(dest);
 | 
				
			||||||
 | 
					    pub->protocol = gbinder_ipc_protocol(dest);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*==========================================================================*
 | 
				
			||||||
 | 
					 * Implementation
 | 
				
			||||||
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_proxy_tx_dequeue(
 | 
				
			||||||
 | 
					    GBinderProxyTx* tx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderProxyObject* proxy = tx->proxy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (proxy) {
 | 
				
			||||||
 | 
					        GBinderProxyObjectPriv* priv = proxy->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (priv->tx) {
 | 
				
			||||||
 | 
					            if (priv->tx == tx) {
 | 
				
			||||||
 | 
					                priv->tx = tx->next;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                GBinderProxyTx* prev = priv->tx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                while (prev->next) {
 | 
				
			||||||
 | 
					                    if (prev->next == tx) {
 | 
				
			||||||
 | 
					                        prev->next = tx->next;
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    prev = prev->next;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        tx->next = NULL;
 | 
				
			||||||
 | 
					        tx->proxy = NULL;
 | 
				
			||||||
 | 
					        g_object_unref(proxy);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_proxy_tx_reply(
 | 
				
			||||||
 | 
					    GBinderIpc* ipc,
 | 
				
			||||||
 | 
					    GBinderRemoteReply* reply,
 | 
				
			||||||
 | 
					    int status,
 | 
				
			||||||
 | 
					    void* user_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderProxyTx* tx = user_data;
 | 
				
			||||||
 | 
					    GBinderProxyObject* self = tx->proxy;
 | 
				
			||||||
 | 
					    GBinderProxyObjectConverter convert;
 | 
				
			||||||
 | 
					    GBinderLocalReply* fwd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * For proxy objects auto-created by the reply, the remote side (the
 | 
				
			||||||
 | 
					     * one sent the reply) will be the remote GBinderIpc and this object's
 | 
				
			||||||
 | 
					     * GBinderIpc will be the local, i.e. those proxies will work in the
 | 
				
			||||||
 | 
					     * same direction as the top level object. The direction gets inverted
 | 
				
			||||||
 | 
					     * twice.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    gbinder_proxy_object_converter_init(&convert, self, ipc, self->parent.ipc);
 | 
				
			||||||
 | 
					    fwd = gbinder_remote_reply_convert_to_local(reply, &convert.pub);
 | 
				
			||||||
 | 
					    tx->id = 0;
 | 
				
			||||||
 | 
					    gbinder_proxy_tx_dequeue(tx);
 | 
				
			||||||
 | 
					    gbinder_remote_request_complete(tx->req, fwd,
 | 
				
			||||||
 | 
					        (status > 0) ? (-EFAULT) : status);
 | 
				
			||||||
 | 
					    if (status == GBINDER_STATUS_DEAD_OBJECT) {
 | 
				
			||||||
 | 
					        /*
 | 
				
			||||||
 | 
					         * Some kernels sometimes don't bother sending us death notifications.
 | 
				
			||||||
 | 
					         * Let's also interpret BR_DEAD_REPLY as an obituary to make sure that
 | 
				
			||||||
 | 
					         * we don't keep dead remote objects around.
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        gbinder_remote_object_commit_suicide(self->remote);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    gbinder_local_reply_unref(fwd);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_proxy_tx_destroy(
 | 
				
			||||||
 | 
					    gpointer user_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderProxyTx* tx = user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gbinder_proxy_tx_dequeue(tx);
 | 
				
			||||||
 | 
					    gbinder_remote_request_unref(tx->req);
 | 
				
			||||||
 | 
					    gutil_slice_free(tx);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					GBinderLocalReply*
 | 
				
			||||||
 | 
					gbinder_proxy_object_handle_transaction(
 | 
				
			||||||
 | 
					    GBinderLocalObject* object,
 | 
				
			||||||
 | 
					    GBinderRemoteRequest* req,
 | 
				
			||||||
 | 
					    guint code,
 | 
				
			||||||
 | 
					    guint flags,
 | 
				
			||||||
 | 
					    int* status)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderProxyObject* self = THIS(object);
 | 
				
			||||||
 | 
					    GBinderProxyObjectPriv* priv = self->priv;
 | 
				
			||||||
 | 
					    GBinderRemoteObject* remote = self->remote;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!priv->dropped && !remote->dead) {
 | 
				
			||||||
 | 
					        GBinderLocalRequest* fwd;
 | 
				
			||||||
 | 
					        GBinderProxyTx* tx = g_slice_new0(GBinderProxyTx);
 | 
				
			||||||
 | 
					        GBinderProxyObjectConverter convert;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        g_object_ref(tx->proxy = self);
 | 
				
			||||||
 | 
					        tx->req = gbinder_remote_request_ref(req);
 | 
				
			||||||
 | 
					        tx->next = priv->tx;
 | 
				
			||||||
 | 
					        priv->tx = tx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Mark the incoming request as pending */
 | 
				
			||||||
 | 
					        gbinder_remote_request_block(req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /*
 | 
				
			||||||
 | 
					         * For auto-created proxy objects, this object's GBinderIpc will
 | 
				
			||||||
 | 
					         * become a remote, and the remote's GBinderIpc will become local
 | 
				
			||||||
 | 
					         * because they work in the opposite direction.
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        gbinder_proxy_object_converter_init(&convert, self, object->ipc,
 | 
				
			||||||
 | 
					            remote->ipc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Forward the transaction */
 | 
				
			||||||
 | 
					        fwd = gbinder_remote_request_convert_to_local(req, &convert.pub);
 | 
				
			||||||
 | 
					        tx->id = gbinder_ipc_transact(remote->ipc, remote->handle, code, flags,
 | 
				
			||||||
 | 
					            fwd, gbinder_proxy_tx_reply, gbinder_proxy_tx_destroy, tx);
 | 
				
			||||||
 | 
					        gbinder_local_request_unref(fwd);
 | 
				
			||||||
 | 
					        *status = GBINDER_STATUS_OK;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        GVERBOSE_("dropped: %d dead:%d", priv->dropped, remote->dead);
 | 
				
			||||||
 | 
					        *status = (-EBADMSG);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					GBINDER_LOCAL_TRANSACTION_SUPPORT
 | 
				
			||||||
 | 
					gbinder_proxy_object_can_handle_transaction(
 | 
				
			||||||
 | 
					    GBinderLocalObject* self,
 | 
				
			||||||
 | 
					    const char* iface,
 | 
				
			||||||
 | 
					    guint code)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /* Process all transactions on the main thread */
 | 
				
			||||||
 | 
					    return GBINDER_LOCAL_TRANSACTION_SUPPORTED;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_proxy_object_acquire(
 | 
				
			||||||
 | 
					    GBinderLocalObject* object)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderProxyObject* self = THIS(object);
 | 
				
			||||||
 | 
					    GBinderProxyObjectPriv* priv = self->priv;
 | 
				
			||||||
 | 
					    GBinderRemoteObject* remote = self->remote;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!remote->dead && !priv->dropped && !priv->acquired) {
 | 
				
			||||||
 | 
					        /* Not acquired yet */
 | 
				
			||||||
 | 
					        priv->acquired = TRUE;
 | 
				
			||||||
 | 
					        gbinder_driver_acquire(remote->ipc->driver, remote->handle);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    GBINDER_LOCAL_OBJECT_CLASS(PARENT_CLASS)->acquire(object);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_proxy_object_drop(
 | 
				
			||||||
 | 
					    GBinderLocalObject* object)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderProxyObject* self = THIS(object);
 | 
				
			||||||
 | 
					    GBinderProxyObjectPriv* priv = self->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    priv->dropped = TRUE;
 | 
				
			||||||
 | 
					    GBINDER_LOCAL_OBJECT_CLASS(PARENT_CLASS)->drop(object);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*==========================================================================*
 | 
				
			||||||
 | 
					 * Interface
 | 
				
			||||||
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderProxyObject*
 | 
				
			||||||
 | 
					gbinder_proxy_object_new(
 | 
				
			||||||
 | 
					    GBinderIpc* src,
 | 
				
			||||||
 | 
					    GBinderRemoteObject* remote)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (G_LIKELY(remote)) {
 | 
				
			||||||
 | 
					        /*
 | 
				
			||||||
 | 
					         * We don't need to specify the interface list because all
 | 
				
			||||||
 | 
					         * transactions (including HIDL_GET_DESCRIPTOR_TRANSACTION
 | 
				
			||||||
 | 
					         * and HIDL_DESCRIPTOR_CHAIN_TRANSACTION) are getting forwared
 | 
				
			||||||
 | 
					         * to the remote object.
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        GBinderLocalObject* object = gbinder_local_object_new_with_type
 | 
				
			||||||
 | 
					            (THIS_TYPE, src, NULL, NULL, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (object) {
 | 
				
			||||||
 | 
					            GBinderProxyObject* self = THIS(object);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            GDEBUG("Proxy %p %s => %u %s created", self, gbinder_ipc_name(src),
 | 
				
			||||||
 | 
					                remote->handle, gbinder_ipc_name(remote->ipc));
 | 
				
			||||||
 | 
					            self->remote = gbinder_remote_object_ref(remote);
 | 
				
			||||||
 | 
					            return self;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*==========================================================================*
 | 
				
			||||||
 | 
					 * Internals
 | 
				
			||||||
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_proxy_object_finalize(
 | 
				
			||||||
 | 
					    GObject* object)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderProxyObject* self = THIS(object);
 | 
				
			||||||
 | 
					    GBinderProxyObjectPriv* priv = self->priv;
 | 
				
			||||||
 | 
					    GBinderLocalObject* local = &self->parent;
 | 
				
			||||||
 | 
					    GBinderRemoteObject* remote = self->remote;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * gbinder_local_object_finalize() will also try to do the same thing
 | 
				
			||||||
 | 
					     * i.e. invalidate self but proxy objects need to do it before releasing
 | 
				
			||||||
 | 
					     * the handle, to leave no room for race conditions. That's not very good
 | 
				
			||||||
 | 
					     * because it grabs ipc-wide mutex but shouldn'd have much of an impact
 | 
				
			||||||
 | 
					     * on the performance because finalizing a proxy is not supposed to be a
 | 
				
			||||||
 | 
					     * frequent operation.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    gbinder_ipc_invalidate_local_object(local->ipc, local);
 | 
				
			||||||
 | 
					    if (priv->acquired) {
 | 
				
			||||||
 | 
					        gbinder_driver_release(remote->ipc->driver, remote->handle);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    GDEBUG("Proxy %p %s => %u %s gone", self,
 | 
				
			||||||
 | 
					        gbinder_ipc_name(self->parent.ipc), remote->handle,
 | 
				
			||||||
 | 
					        gbinder_ipc_name(remote->ipc));
 | 
				
			||||||
 | 
					    gbinder_remote_object_unref(remote);
 | 
				
			||||||
 | 
					    G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_proxy_object_init(
 | 
				
			||||||
 | 
					    GBinderProxyObject* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderProxyObjectPriv* priv = G_TYPE_INSTANCE_GET_PRIVATE(self,
 | 
				
			||||||
 | 
					        THIS_TYPE, GBinderProxyObjectPriv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    self->priv = priv;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_proxy_object_class_init(
 | 
				
			||||||
 | 
					    GBinderProxyObjectClass* klass)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GObjectClass* object_class = G_OBJECT_CLASS(klass);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_type_class_add_private(klass, sizeof(GBinderProxyObjectPriv));
 | 
				
			||||||
 | 
					    object_class->finalize = gbinder_proxy_object_finalize;
 | 
				
			||||||
 | 
					    klass->can_handle_transaction = gbinder_proxy_object_can_handle_transaction;
 | 
				
			||||||
 | 
					    klass->handle_transaction = gbinder_proxy_object_handle_transaction;
 | 
				
			||||||
 | 
					    klass->acquire = gbinder_proxy_object_acquire;
 | 
				
			||||||
 | 
					    klass->drop = gbinder_proxy_object_drop;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Local Variables:
 | 
				
			||||||
 | 
					 * mode: C
 | 
				
			||||||
 | 
					 * c-basic-offset: 4
 | 
				
			||||||
 | 
					 * indent-tabs-mode: nil
 | 
				
			||||||
 | 
					 * End:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
							
								
								
									
										66
									
								
								src/gbinder_proxy_object.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								src/gbinder_proxy_object.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2021 Jolla Ltd.
 | 
				
			||||||
 | 
					 * Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   1. Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 | 
					 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
				
			||||||
 | 
					 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
				
			||||||
 | 
					 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
				
			||||||
 | 
					 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
				
			||||||
 | 
					 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
				
			||||||
 | 
					 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
				
			||||||
 | 
					 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
				
			||||||
 | 
					 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
				
			||||||
 | 
					 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GBINDER_PROXY_OBJECT_H
 | 
				
			||||||
 | 
					#define GBINDER_PROXY_OBJECT_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "gbinder_local_object_p.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_proxy_object_priv GBinderProxyObjectPriv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gbinder_proxy_object {
 | 
				
			||||||
 | 
					    GBinderLocalObject parent;
 | 
				
			||||||
 | 
					    GBinderProxyObjectPriv* priv;
 | 
				
			||||||
 | 
					    GBinderRemoteObject* remote;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GType gbinder_proxy_object_get_type(void) GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					#define GBINDER_TYPE_PROXY_OBJECT gbinder_proxy_object_get_type()
 | 
				
			||||||
 | 
					#define GBINDER_PROXY_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
 | 
				
			||||||
 | 
					        GBINDER_TYPE_PROXY_OBJECT, GBinderProxyObject))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Registers with src and forwards all transactions to the remote */
 | 
				
			||||||
 | 
					GBinderProxyObject*
 | 
				
			||||||
 | 
					gbinder_proxy_object_new(
 | 
				
			||||||
 | 
					    GBinderIpc* src,
 | 
				
			||||||
 | 
					    GBinderRemoteObject* remote)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* GBINDER_PROXY_OBJECT_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Local Variables:
 | 
				
			||||||
 | 
					 * mode: C
 | 
				
			||||||
 | 
					 * c-basic-offset: 4
 | 
				
			||||||
 | 
					 * indent-tabs-mode: nil
 | 
				
			||||||
 | 
					 * End:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2024 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -38,6 +38,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <gutil_macros.h>
 | 
					#include <gutil_macros.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					#include <fcntl.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct gbinder_reader_priv {
 | 
					typedef struct gbinder_reader_priv {
 | 
				
			||||||
    const guint8* start;
 | 
					    const guint8* start;
 | 
				
			||||||
    const guint8* end;
 | 
					    const guint8* end;
 | 
				
			||||||
@@ -50,6 +53,8 @@ G_STATIC_ASSERT(sizeof(GBinderReader) >= sizeof(GBinderReaderPriv));
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static inline GBinderReaderPriv* gbinder_reader_cast(GBinderReader* reader)
 | 
					static inline GBinderReaderPriv* gbinder_reader_cast(GBinderReader* reader)
 | 
				
			||||||
    { return (GBinderReaderPriv*)reader; }
 | 
					    { return (GBinderReaderPriv*)reader; }
 | 
				
			||||||
 | 
					static inline const GBinderReaderPriv* gbinder_reader_cast_c
 | 
				
			||||||
 | 
					    (const GBinderReader* reader)  { return (GBinderReaderPriv*)reader; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_reader_init(
 | 
					gbinder_reader_init(
 | 
				
			||||||
@@ -81,11 +86,11 @@ gbinder_reader_init(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
gboolean
 | 
					gboolean
 | 
				
			||||||
gbinder_reader_at_end(
 | 
					gbinder_reader_at_end(
 | 
				
			||||||
    GBinderReader* reader)
 | 
					    const GBinderReader* reader)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GBinderReaderPriv* p = gbinder_reader_cast(reader);
 | 
					    const GBinderReaderPriv* p = gbinder_reader_cast_c(reader);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return p->ptr >= p->end;
 | 
					    return !p || p->ptr >= p->end;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
@@ -118,13 +123,74 @@ gboolean
 | 
				
			|||||||
gbinder_reader_read_bool(
 | 
					gbinder_reader_read_bool(
 | 
				
			||||||
    GBinderReader* reader,
 | 
					    GBinderReader* reader,
 | 
				
			||||||
    gboolean* value)
 | 
					    gboolean* value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * Android's libhwbinder writes bool as a single byte and pads it
 | 
				
			||||||
 | 
					     * with zeros, but libbinder writes bool as int32 in native byte
 | 
				
			||||||
 | 
					     * order. The latter becomes either [0x01, 0x00, 0x00, 0x00] or
 | 
				
			||||||
 | 
					     * [0x00, 0x00, 0x00, 0x01] depending on the byte order. Reading
 | 
				
			||||||
 | 
					     * uint32 and comparing it with zero works in either case.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    if (value) {
 | 
				
			||||||
 | 
					        guint32 padded;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (gbinder_reader_read_uint32(reader, &padded)) {
 | 
				
			||||||
 | 
					            *value = (padded != 0);
 | 
				
			||||||
 | 
					            return TRUE;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            return FALSE;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        return gbinder_reader_read_uint32(reader, NULL);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_reader_read_int8(
 | 
				
			||||||
 | 
					    GBinderReader* reader,
 | 
				
			||||||
 | 
					    gint8* value) /* Since 1.1.15 */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return gbinder_reader_read_uint8(reader, (guint8*)value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_reader_read_uint8(
 | 
				
			||||||
 | 
					    GBinderReader* reader,
 | 
				
			||||||
 | 
					    guint8* value) /* Since 1.1.15 */
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GBinderReaderPriv* p = gbinder_reader_cast(reader);
 | 
					    GBinderReaderPriv* p = gbinder_reader_cast(reader);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Boolean values are supposed to be padded to 4-byte boundary */
 | 
					    /* Primitive values are supposed to be padded to 4-byte boundary */
 | 
				
			||||||
    if (gbinder_reader_can_read(p, 4)) {
 | 
					    if (gbinder_reader_can_read(p, 4)) {
 | 
				
			||||||
        if (value) {
 | 
					        if (value) {
 | 
				
			||||||
            *value = (p->ptr[0] != 0);
 | 
					            *value = p->ptr[0];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        p->ptr += 4;
 | 
				
			||||||
 | 
					        return TRUE;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        return FALSE;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_reader_read_int16(
 | 
				
			||||||
 | 
					    GBinderReader* reader,
 | 
				
			||||||
 | 
					    gint16* value) /* Since 1.1.15 */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return gbinder_reader_read_uint16(reader, (guint16*)value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_reader_read_uint16(
 | 
				
			||||||
 | 
					    GBinderReader* reader,
 | 
				
			||||||
 | 
					    guint16* value) /* Since 1.1.15 */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderReaderPriv* p = gbinder_reader_cast(reader);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Primitive values are supposed to be padded to 4-byte boundary */
 | 
				
			||||||
 | 
					    if (gbinder_reader_can_read(p, 4)) {
 | 
				
			||||||
 | 
					        if (value) {
 | 
				
			||||||
 | 
					            *value = *(guint16*)p->ptr;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        p->ptr += 4;
 | 
					        p->ptr += 4;
 | 
				
			||||||
        return TRUE;
 | 
					        return TRUE;
 | 
				
			||||||
@@ -229,18 +295,70 @@ gbinder_reader_read_double(
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					inline
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_reader_can_read_object(
 | 
				
			||||||
 | 
					    GBinderReaderPriv* p)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const GBinderReaderData* data = p->data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return data && data->reg &&
 | 
				
			||||||
 | 
					        p->objects && p->objects[0] &&
 | 
				
			||||||
 | 
					        p->ptr == p->objects[0];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					gbinder_reader_read_fd(
 | 
				
			||||||
 | 
					    GBinderReader* reader) /* Since 1.0.18 */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderReaderPriv* p = gbinder_reader_cast(reader);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (gbinder_reader_can_read_object(p)) {
 | 
				
			||||||
 | 
					        int fd;
 | 
				
			||||||
 | 
					        const guint eaten = p->data->reg->io->decode_fd_object(p->ptr,
 | 
				
			||||||
 | 
					            gbinder_reader_bytes_remaining(reader), &fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (eaten) {
 | 
				
			||||||
 | 
					            GASSERT(fd >= 0);
 | 
				
			||||||
 | 
					            p->ptr += eaten;
 | 
				
			||||||
 | 
					            p->objects++;
 | 
				
			||||||
 | 
					            return fd;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return -1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					gbinder_reader_read_dup_fd(
 | 
				
			||||||
 | 
					    GBinderReader* reader) /* Since 1.0.18 */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const int fd = gbinder_reader_read_fd(reader);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (fd >= 0) {
 | 
				
			||||||
 | 
					        const int dupfd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (dupfd >= 0) {
 | 
				
			||||||
 | 
					            return dupfd;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            GWARN("Error dupping fd %d: %s", fd, strerror(errno));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return -1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gboolean
 | 
					gboolean
 | 
				
			||||||
gbinder_reader_read_nullable_object(
 | 
					gbinder_reader_read_nullable_object(
 | 
				
			||||||
    GBinderReader* reader,
 | 
					    GBinderReader* reader,
 | 
				
			||||||
    GBinderRemoteObject** out)
 | 
					    GBinderRemoteObject** out)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GBinderReaderPriv* p = gbinder_reader_cast(reader);
 | 
					    GBinderReaderPriv* p = gbinder_reader_cast(reader);
 | 
				
			||||||
    const GBinderReaderData* data = p->data;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (data && data->reg && p->objects && p->objects[0] &&
 | 
					    if (gbinder_reader_can_read_object(p)) {
 | 
				
			||||||
        p->ptr == p->objects[0]) {
 | 
					        const GBinderReaderData* data = p->data;
 | 
				
			||||||
        const guint eaten = data->reg->io->decode_binder_object(p->ptr,
 | 
					        const guint eaten = data->reg->io->decode_binder_object(p->ptr,
 | 
				
			||||||
            gbinder_reader_bytes_remaining(reader), data->reg, out);
 | 
					            gbinder_reader_bytes_remaining(reader), data->reg, out,
 | 
				
			||||||
 | 
					            gbinder_buffer_protocol(data->buffer));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (eaten) {
 | 
					        if (eaten) {
 | 
				
			||||||
            p->ptr += eaten;
 | 
					            p->ptr += eaten;
 | 
				
			||||||
@@ -264,15 +382,14 @@ gbinder_reader_read_object(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
gboolean
 | 
					gboolean
 | 
				
			||||||
gbinder_reader_read_buffer_impl(
 | 
					gbinder_reader_read_buffer_object(
 | 
				
			||||||
    GBinderReader* reader,
 | 
					    GBinderReader* reader,
 | 
				
			||||||
    GBinderBuffer** out)
 | 
					    GBinderIoBufferObject* out)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GBinderReaderPriv* p = gbinder_reader_cast(reader);
 | 
					    GBinderReaderPriv* p = gbinder_reader_cast(reader);
 | 
				
			||||||
    const GBinderReaderData* data = p->data;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (data && data->reg && p->objects && p->objects[0] &&
 | 
					    if (gbinder_reader_can_read_object(p)) {
 | 
				
			||||||
        p->ptr == p->objects[0]) {
 | 
					        const GBinderReaderData* data = p->data;
 | 
				
			||||||
        GBinderBuffer* buf = data->buffer;
 | 
					        GBinderBuffer* buf = data->buffer;
 | 
				
			||||||
        const GBinderIo* io = data->reg->io;
 | 
					        const GBinderIo* io = data->reg->io;
 | 
				
			||||||
        const gsize offset = p->ptr - (guint8*)buf->data;
 | 
					        const gsize offset = p->ptr - (guint8*)buf->data;
 | 
				
			||||||
@@ -284,7 +401,6 @@ gbinder_reader_read_buffer_impl(
 | 
				
			|||||||
            return TRUE;
 | 
					            return TRUE;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (out) *out = NULL;
 | 
					 | 
				
			||||||
    return FALSE;
 | 
					    return FALSE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -292,101 +408,212 @@ GBinderBuffer*
 | 
				
			|||||||
gbinder_reader_read_buffer(
 | 
					gbinder_reader_read_buffer(
 | 
				
			||||||
    GBinderReader* reader)
 | 
					    GBinderReader* reader)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GBinderBuffer* buf = NULL;
 | 
					    GBinderIoBufferObject obj;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    gbinder_reader_read_buffer_impl(reader, &buf);
 | 
					    if (gbinder_reader_read_buffer_object(reader, &obj)) {
 | 
				
			||||||
    return buf;
 | 
					        const GBinderReaderData* data = gbinder_reader_cast(reader)->data;
 | 
				
			||||||
 | 
					        GBinderBuffer* buf = data->buffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return gbinder_buffer_new_with_parent(buf, obj.data, obj.size);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gboolean
 | 
					gboolean
 | 
				
			||||||
gbinder_reader_skip_buffer(
 | 
					gbinder_reader_skip_buffer(
 | 
				
			||||||
    GBinderReader* reader)
 | 
					    GBinderReader* reader)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return gbinder_reader_read_buffer_impl(reader, NULL);
 | 
					    return gbinder_reader_read_buffer_object(reader, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This is supposed to be used to read aidl parcelables, and is not
 | 
				
			||||||
 | 
					 * guaranteed to work on any other kind of parcelable.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const void*
 | 
				
			||||||
 | 
					gbinder_reader_read_parcelable(
 | 
				
			||||||
 | 
					    GBinderReader* reader,
 | 
				
			||||||
 | 
					    gsize* size) /* Since 1.1.19 */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    guint32 non_null, payload_size = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (gbinder_reader_read_uint32(reader, &non_null) && non_null &&
 | 
				
			||||||
 | 
					        gbinder_reader_read_uint32(reader, &payload_size) &&
 | 
				
			||||||
 | 
					        payload_size >= sizeof(payload_size)) {
 | 
				
			||||||
 | 
					        GBinderReaderPriv* p = gbinder_reader_cast(reader);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        payload_size -= sizeof(payload_size);
 | 
				
			||||||
 | 
					        if (p->ptr + payload_size <= p->end) {
 | 
				
			||||||
 | 
					            const void* out = p->ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* Success */
 | 
				
			||||||
 | 
					            p->ptr += payload_size;
 | 
				
			||||||
 | 
					            if (size) {
 | 
				
			||||||
 | 
					                *size = payload_size;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return out;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (size) {
 | 
				
			||||||
 | 
					        *size = 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Helper for gbinder_reader_read_hidl_struct() macro */
 | 
				
			||||||
 | 
					const void*
 | 
				
			||||||
 | 
					gbinder_reader_read_hidl_struct1(
 | 
				
			||||||
 | 
					    GBinderReader* reader,
 | 
				
			||||||
 | 
					    gsize size) /* Since 1.0.9 */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderIoBufferObject obj;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (gbinder_reader_read_buffer_object(reader, &obj) && obj.size == size) {
 | 
				
			||||||
 | 
					        return obj.data;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Doesn't copy the data */
 | 
				
			||||||
 | 
					const void*
 | 
				
			||||||
 | 
					gbinder_reader_read_hidl_vec(
 | 
				
			||||||
 | 
					    GBinderReader* reader,
 | 
				
			||||||
 | 
					    gsize* count,
 | 
				
			||||||
 | 
					    gsize* elemsize)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderIoBufferObject obj;
 | 
				
			||||||
 | 
					    const void* out = NULL;
 | 
				
			||||||
 | 
					    gsize out_count = 0, out_elemsize = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (gbinder_reader_read_buffer_object(reader, &obj) &&
 | 
				
			||||||
 | 
					        obj.data && obj.size == sizeof(GBinderHidlVec)) {
 | 
				
			||||||
 | 
					        const GBinderHidlVec* vec = obj.data;
 | 
				
			||||||
 | 
					        const void* next = vec->data.ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (next) {
 | 
				
			||||||
 | 
					            if (gbinder_reader_read_buffer_object(reader, &obj) &&
 | 
				
			||||||
 | 
					                obj.data == next && ((!vec->count && !obj.size) ||
 | 
				
			||||||
 | 
					                (vec->count && obj.size && !(obj.size % vec->count)))) {
 | 
				
			||||||
 | 
					                out_elemsize = vec->count ? (obj.size / vec->count) : 0;
 | 
				
			||||||
 | 
					                out_count = vec->count;
 | 
				
			||||||
 | 
					                out = obj.data;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else if (!vec->count) {
 | 
				
			||||||
 | 
					            /* Any non-NULL pointer just to indicate success? */
 | 
				
			||||||
 | 
					            out = vec;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (elemsize) {
 | 
				
			||||||
 | 
					        *elemsize = out_elemsize;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (count) {
 | 
				
			||||||
 | 
					        *count = out_count;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return out;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Helper for gbinder_reader_read_hidl_struct_vec() macro */
 | 
				
			||||||
 | 
					const void*
 | 
				
			||||||
 | 
					gbinder_reader_read_hidl_vec1(
 | 
				
			||||||
 | 
					    GBinderReader* reader,
 | 
				
			||||||
 | 
					    gsize* count,
 | 
				
			||||||
 | 
					    guint expected_elem_size) /* Since 1.0.9 */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    gsize actual;
 | 
				
			||||||
 | 
					    const void* data = gbinder_reader_read_hidl_vec(reader, count, &actual);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Actual size will be zero for an empty array */
 | 
				
			||||||
 | 
					    return (data && (actual == expected_elem_size || !actual)) ? data : NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char*
 | 
				
			||||||
 | 
					gbinder_reader_read_hidl_string_c(
 | 
				
			||||||
 | 
					    GBinderReader* reader) /* Since 1.0.23 */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderIoBufferObject obj;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (gbinder_reader_read_buffer_object(reader, &obj) &&
 | 
				
			||||||
 | 
					        obj.data && obj.size == sizeof(GBinderHidlString)) {
 | 
				
			||||||
 | 
					        const GBinderHidlString* str = obj.data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (gbinder_reader_read_buffer_object(reader, &obj) &&
 | 
				
			||||||
 | 
					            obj.has_parent &&
 | 
				
			||||||
 | 
					            obj.parent_offset == GBINDER_HIDL_STRING_BUFFER_OFFSET &&
 | 
				
			||||||
 | 
					            obj.data == str->data.str &&
 | 
				
			||||||
 | 
					            obj.size == str->len + 1 &&
 | 
				
			||||||
 | 
					            str->data.str[str->len] == 0) {
 | 
				
			||||||
 | 
					            return str->data.str;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
char*
 | 
					char*
 | 
				
			||||||
gbinder_reader_read_hidl_string(
 | 
					gbinder_reader_read_hidl_string(
 | 
				
			||||||
    GBinderReader* reader)
 | 
					    GBinderReader* reader)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GBinderBuffer* buf = gbinder_reader_read_buffer(reader);
 | 
					    /* This function should've been called gbinder_reader_dup_hidl_string */
 | 
				
			||||||
    char* str = NULL;
 | 
					    return g_strdup(gbinder_reader_read_hidl_string_c(reader));
 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (buf && buf->size == sizeof(HidlString)) {
 | 
					 | 
				
			||||||
        const HidlString* s = buf->data;
 | 
					 | 
				
			||||||
        GBinderBuffer* sbuf = gbinder_reader_read_buffer(reader);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (sbuf && sbuf->size == s->len + 1 &&
 | 
					 | 
				
			||||||
            sbuf->data == s->data.str &&
 | 
					 | 
				
			||||||
            s->data.str[s->len] == 0) {
 | 
					 | 
				
			||||||
            str = g_strdup(s->data.str);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        gbinder_buffer_free(sbuf);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    gbinder_buffer_free(buf);
 | 
					 | 
				
			||||||
    return str;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
char**
 | 
					char**
 | 
				
			||||||
gbinder_reader_read_hidl_string_vec(
 | 
					gbinder_reader_read_hidl_string_vec(
 | 
				
			||||||
    GBinderReader* reader)
 | 
					    GBinderReader* reader)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GBinderBuffer* buf = gbinder_reader_read_buffer(reader);
 | 
					    GBinderIoBufferObject obj;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* First buffer contains hidl_vector */
 | 
					    /* First buffer contains hidl_vector */
 | 
				
			||||||
    if (buf && buf->size == sizeof(HidlVec)) {
 | 
					    if (gbinder_reader_read_buffer_object(reader, &obj) &&
 | 
				
			||||||
        HidlVec* vec = buf->data;
 | 
					        obj.data && obj.size == sizeof(GBinderHidlVec)) {
 | 
				
			||||||
 | 
					        GBinderHidlVec* vec = obj.data;
 | 
				
			||||||
        const guint n = vec->count;
 | 
					        const guint n = vec->count;
 | 
				
			||||||
        const void* next = vec->data.ptr;
 | 
					        const void* next = vec->data.ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gbinder_buffer_free(buf);
 | 
					 | 
				
			||||||
        if (!next && !n) {
 | 
					        if (!next && !n) {
 | 
				
			||||||
            char** out = g_new(char*, 1);
 | 
					            /* Should this be considered an error? */
 | 
				
			||||||
 | 
					            return g_new0(char*, 1);
 | 
				
			||||||
 | 
					        } else if (gbinder_reader_read_buffer_object(reader, &obj) &&
 | 
				
			||||||
 | 
					                   /* The second buffer (if any) contains n hidl_string's */
 | 
				
			||||||
 | 
					                   obj.parent_offset == GBINDER_HIDL_VEC_BUFFER_OFFSET &&
 | 
				
			||||||
 | 
					                   obj.has_parent &&
 | 
				
			||||||
 | 
					                   obj.data == next &&
 | 
				
			||||||
 | 
					                   obj.size == (sizeof(GBinderHidlString) * n)) {
 | 
				
			||||||
 | 
					            const GBinderHidlString* strings = obj.data;
 | 
				
			||||||
 | 
					            GPtrArray* list = g_ptr_array_sized_new(n + 1);
 | 
				
			||||||
 | 
					            guint i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            out[0] = NULL;
 | 
					            /* Now we expect n buffers containing the actual data */
 | 
				
			||||||
            return out;
 | 
					            for (i = 0; i < n &&
 | 
				
			||||||
        } else {
 | 
					                gbinder_reader_read_buffer_object(reader, &obj); i++) {
 | 
				
			||||||
            /* The second buffer (if any) contains n hidl_string's */
 | 
					                const GBinderHidlString* s = strings + i;
 | 
				
			||||||
            buf = gbinder_reader_read_buffer(reader);
 | 
					                const gsize expected_offset = (i * sizeof(*s)) +
 | 
				
			||||||
            if (buf && buf->data == next && buf->size == sizeof(HidlString)*n) {
 | 
					                    GBINDER_HIDL_STRING_BUFFER_OFFSET;
 | 
				
			||||||
                const HidlString* strings = buf->data;
 | 
					                if (obj.has_parent &&
 | 
				
			||||||
                GBinderBuffer* sbuf;
 | 
					                    obj.parent_offset == expected_offset &&
 | 
				
			||||||
                GPtrArray* list = g_ptr_array_new();
 | 
					                    obj.data == s->data.str &&
 | 
				
			||||||
                guint i;
 | 
					                    obj.size == s->len + 1 &&
 | 
				
			||||||
 | 
					                    s->data.str[s->len] == 0) {
 | 
				
			||||||
 | 
					                    char* name = g_strdup(s->data.str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                /* Now we expect n buffers containing the actual data */
 | 
					                    g_ptr_array_add(list, name);
 | 
				
			||||||
                for (i=0; i<n &&
 | 
					                    GVERBOSE_("%u. %s", i + 1, name);
 | 
				
			||||||
                    (sbuf = gbinder_reader_read_buffer(reader)); i++) {
 | 
					                } else {
 | 
				
			||||||
                    const HidlString* s = strings + i;
 | 
					                    GWARN("Unexpected hidl_string buffer %p/%u vs %p/%u",
 | 
				
			||||||
                    if (sbuf->size == s->len + 1 &&
 | 
					                        obj.data, (guint)obj.size, s->data.str, s->len);
 | 
				
			||||||
                        sbuf->data == s->data.str &&
 | 
					                    break;
 | 
				
			||||||
                        s->data.str[s->len] == 0) {
 | 
					 | 
				
			||||||
                        char* name = g_strdup(s->data.str);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        g_ptr_array_add(list, name);
 | 
					 | 
				
			||||||
                        GVERBOSE_("%u. %s", i + 1, name);
 | 
					 | 
				
			||||||
                        gbinder_buffer_free(sbuf);
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        GWARN("Unexpected hidl_string buffer %p/%u vs %p/%u",
 | 
					 | 
				
			||||||
                            sbuf->data, (guint)sbuf->size, s->data.str, s->len);
 | 
					 | 
				
			||||||
                        gbinder_buffer_free(sbuf);
 | 
					 | 
				
			||||||
                        break;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					 | 
				
			||||||
                if (i == n) {
 | 
					 | 
				
			||||||
                    gbinder_buffer_free(buf);
 | 
					 | 
				
			||||||
                    g_ptr_array_add(list, NULL);
 | 
					 | 
				
			||||||
                    return (char**)g_ptr_array_free(list, FALSE);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                g_ptr_array_set_free_func(list, g_free);
 | 
					 | 
				
			||||||
                g_ptr_array_free(list, TRUE);
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (i == n) {
 | 
				
			||||||
 | 
					                g_ptr_array_add(list, NULL);
 | 
				
			||||||
 | 
					                return (char**)g_ptr_array_free(list, FALSE);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            g_ptr_array_set_free_func(list, g_free);
 | 
				
			||||||
 | 
					            g_ptr_array_free(list, TRUE);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    GWARN("Invalid hidl_vec<string>");
 | 
					    GWARN("Invalid hidl_vec<string>");
 | 
				
			||||||
    gbinder_buffer_free(buf);
 | 
					 | 
				
			||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -418,6 +645,24 @@ gboolean
 | 
				
			|||||||
gbinder_reader_read_nullable_string16(
 | 
					gbinder_reader_read_nullable_string16(
 | 
				
			||||||
    GBinderReader* reader,
 | 
					    GBinderReader* reader,
 | 
				
			||||||
    char** out)
 | 
					    char** out)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const gunichar2* str;
 | 
				
			||||||
 | 
					    gsize len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (gbinder_reader_read_nullable_string16_utf16(reader, &str, &len)) {
 | 
				
			||||||
 | 
					        if (out) {
 | 
				
			||||||
 | 
					            *out = str ? g_utf16_to_utf8(str, len, NULL, NULL, NULL) : NULL;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return TRUE;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return FALSE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_reader_read_nullable_string16_utf16(
 | 
				
			||||||
 | 
					    GBinderReader* reader,
 | 
				
			||||||
 | 
					    const gunichar2** out,
 | 
				
			||||||
 | 
					    gsize* out_len) /* Since 1.0.17 */
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GBinderReaderPriv* p = gbinder_reader_cast(reader);
 | 
					    GBinderReaderPriv* p = gbinder_reader_cast(reader);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -431,15 +676,21 @@ gbinder_reader_read_nullable_string16(
 | 
				
			|||||||
            if (out) {
 | 
					            if (out) {
 | 
				
			||||||
                *out = NULL;
 | 
					                *out = NULL;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            if (out_len) {
 | 
				
			||||||
 | 
					                *out_len = 0;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            return TRUE;
 | 
					            return TRUE;
 | 
				
			||||||
        } else if (len >= 0) {
 | 
					        } else if (len >= 0) {
 | 
				
			||||||
            const guint32 padded_len = G_ALIGN4((len+1)*2);
 | 
					            const guint32 padded_len = G_ALIGN4((len + 1)*2);
 | 
				
			||||||
            const gunichar2* utf16 = (const gunichar2*)(p->ptr + 4);
 | 
					            const gunichar2* utf16 = (gunichar2*)(p->ptr + 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ((p->ptr + padded_len + 4) <= p->end) {
 | 
					            if ((p->ptr + padded_len + 4) <= p->end) {
 | 
				
			||||||
                p->ptr += padded_len + 4;
 | 
					                p->ptr += padded_len + 4;
 | 
				
			||||||
                if (out) {
 | 
					                if (out) {
 | 
				
			||||||
                    *out = g_utf16_to_utf8(utf16, len, NULL, NULL, NULL);
 | 
					                    *out = utf16;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                if (out_len) {
 | 
				
			||||||
 | 
					                    *out_len = len;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                return TRUE;
 | 
					                return TRUE;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -448,6 +699,21 @@ gbinder_reader_read_nullable_string16(
 | 
				
			|||||||
    return FALSE;
 | 
					    return FALSE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const gunichar2*
 | 
				
			||||||
 | 
					gbinder_reader_read_string16_utf16(
 | 
				
			||||||
 | 
					    GBinderReader* reader,
 | 
				
			||||||
 | 
					    gsize* len) /* Since 1.0.26 */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const gunichar2* str;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * Use gbinder_reader_read_nullable_string16_utf16 to distinguish
 | 
				
			||||||
 | 
					     * NULL string from a parsing failure.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    return gbinder_reader_read_nullable_string16_utf16(reader, &str, len) ?
 | 
				
			||||||
 | 
					        str : NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
char*
 | 
					char*
 | 
				
			||||||
gbinder_reader_read_string16(
 | 
					gbinder_reader_read_string16(
 | 
				
			||||||
    GBinderReader* reader)
 | 
					    GBinderReader* reader)
 | 
				
			||||||
@@ -484,22 +750,86 @@ gbinder_reader_skip_string16(
 | 
				
			|||||||
    return FALSE;
 | 
					    return FALSE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gsize
 | 
					const void*
 | 
				
			||||||
gbinder_reader_bytes_read(
 | 
					gbinder_reader_read_byte_array(
 | 
				
			||||||
    GBinderReader* reader)
 | 
					    GBinderReader* reader,
 | 
				
			||||||
 | 
					    gsize* len) /* Since 1.0.12 */
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GBinderReaderPriv* p = gbinder_reader_cast(reader);
 | 
					    GBinderReaderPriv* p = gbinder_reader_cast(reader);
 | 
				
			||||||
 | 
					    const void* data = NULL;
 | 
				
			||||||
 | 
					    const gint32* ptr;
 | 
				
			||||||
 | 
					    *len = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return p->ptr - p->start;
 | 
					    if (gbinder_reader_can_read(p, sizeof(*ptr))) {
 | 
				
			||||||
 | 
					        ptr = (void*)p->ptr;
 | 
				
			||||||
 | 
					        if (*ptr <= 0) {
 | 
				
			||||||
 | 
					            p->ptr += sizeof(*ptr);
 | 
				
			||||||
 | 
					            /* Any non-NULL pointer just to indicate success */
 | 
				
			||||||
 | 
					            data = p->start;
 | 
				
			||||||
 | 
					        } else if (gbinder_reader_can_read(p, sizeof(*ptr) + *ptr)) {
 | 
				
			||||||
 | 
					            *len = (gsize)*ptr;
 | 
				
			||||||
 | 
					            p->ptr += sizeof(*ptr);
 | 
				
			||||||
 | 
					            data = p->ptr;
 | 
				
			||||||
 | 
					            /* Android aligns byte array reads and writes to 4 bytes */
 | 
				
			||||||
 | 
					            p->ptr += G_ALIGN4(*len);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return data;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const void*
 | 
				
			||||||
 | 
					gbinder_reader_get_data(
 | 
				
			||||||
 | 
					    const GBinderReader* reader,
 | 
				
			||||||
 | 
					    gsize* size) /* Since 1.1.14 */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const GBinderReaderPriv* p = gbinder_reader_cast_c(reader);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (p) {
 | 
				
			||||||
 | 
					        const GBinderReaderData* data = p->data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (data && data->buffer) {
 | 
				
			||||||
 | 
					            if (size) {
 | 
				
			||||||
 | 
					                *size = data->buffer->size;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return data->buffer->data;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* No data */
 | 
				
			||||||
 | 
					    if (size) {
 | 
				
			||||||
 | 
					        *size = 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gsize
 | 
				
			||||||
 | 
					gbinder_reader_bytes_read(
 | 
				
			||||||
 | 
					    const GBinderReader* reader)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const GBinderReaderPriv* p = gbinder_reader_cast_c(reader);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return p ? (p->ptr - p->start) : 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gsize
 | 
					gsize
 | 
				
			||||||
gbinder_reader_bytes_remaining(
 | 
					gbinder_reader_bytes_remaining(
 | 
				
			||||||
    GBinderReader* reader)
 | 
					    const GBinderReader* reader)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GBinderReaderPriv* p = gbinder_reader_cast(reader);
 | 
					    const GBinderReaderPriv* p = gbinder_reader_cast_c(reader);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return p->end - p->ptr;
 | 
					    return p ? (p->end - p->ptr) : 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_reader_copy(
 | 
				
			||||||
 | 
					    GBinderReader* dest,
 | 
				
			||||||
 | 
					    const GBinderReader* src)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (src) {
 | 
				
			||||||
 | 
					        memcpy(dest, src, sizeof(*dest));
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        memset(dest, 0, sizeof(*dest));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2020 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -48,7 +48,8 @@ gbinder_reader_init(
 | 
				
			|||||||
    GBinderReader* reader,
 | 
					    GBinderReader* reader,
 | 
				
			||||||
    GBinderReaderData* data,
 | 
					    GBinderReaderData* data,
 | 
				
			||||||
    gsize offset,
 | 
					    gsize offset,
 | 
				
			||||||
    gsize len);
 | 
					    gsize len)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* GBINDER_READER_PRIVATE_H */
 | 
					#endif /* GBINDER_READER_PRIVATE_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2023 Slava Monich <slava@monich.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -33,19 +33,21 @@
 | 
				
			|||||||
#include "gbinder_driver.h"
 | 
					#include "gbinder_driver.h"
 | 
				
			||||||
#include "gbinder_ipc.h"
 | 
					#include "gbinder_ipc.h"
 | 
				
			||||||
#include "gbinder_remote_object_p.h"
 | 
					#include "gbinder_remote_object_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_servicemanager_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_eventloop_p.h"
 | 
				
			||||||
#include "gbinder_log.h"
 | 
					#include "gbinder_log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct gbinder_remote_object_priv {
 | 
					struct gbinder_remote_object_priv {
 | 
				
			||||||
    GMainContext* context;
 | 
					    gboolean acquired;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef GObjectClass GBinderRemoteObjectClass;
 | 
					typedef GObjectClass GBinderRemoteObjectClass;
 | 
				
			||||||
 | 
					GType gbinder_remote_object_get_type(void) GBINDER_INTERNAL;
 | 
				
			||||||
G_DEFINE_TYPE(GBinderRemoteObject, gbinder_remote_object, G_TYPE_OBJECT)
 | 
					G_DEFINE_TYPE(GBinderRemoteObject, gbinder_remote_object, G_TYPE_OBJECT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GType gbinder_remote_object_get_type(void);
 | 
					#define PARENT_CLASS gbinder_remote_object_parent_class
 | 
				
			||||||
#define GBINDER_TYPE_REMOTE_OBJECT (gbinder_remote_object_get_type())
 | 
					#define THIS_TYPE (gbinder_remote_object_get_type())
 | 
				
			||||||
#define GBINDER_REMOTE_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
 | 
					#define THIS(obj) G_TYPE_CHECK_INSTANCE_CAST(obj,THIS_TYPE,GBinderRemoteObject)
 | 
				
			||||||
        GBINDER_TYPE_REMOTE_OBJECT, GBinderRemoteObject))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum gbinder_remote_object_signal {
 | 
					enum gbinder_remote_object_signal {
 | 
				
			||||||
    SIGNAL_DEATH,
 | 
					    SIGNAL_DEATH,
 | 
				
			||||||
@@ -62,21 +64,100 @@ static guint gbinder_remote_object_signals[SIGNAL_COUNT] = { 0 };
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_remote_object_died_on_main_thread(
 | 
					gbinder_remote_object_handle_death_on_main_thread(
 | 
				
			||||||
    GBinderRemoteObject* self)
 | 
					    gpointer user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GASSERT(!self->dead);
 | 
					    GBinderRemoteObject* self = THIS(user_data);
 | 
				
			||||||
    self->dead = TRUE;
 | 
					
 | 
				
			||||||
    g_signal_emit(self, gbinder_remote_object_signals[SIGNAL_DEATH], 0);
 | 
					    if (!self->dead) {
 | 
				
			||||||
 | 
					        GBinderIpc* ipc = self->ipc;
 | 
				
			||||||
 | 
					        GBinderDriver* driver = ipc->driver;
 | 
				
			||||||
 | 
					        GBinderRemoteObjectPriv* priv = self->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self->dead = TRUE;
 | 
				
			||||||
 | 
					        if (priv->acquired) {
 | 
				
			||||||
 | 
					            priv->acquired = FALSE;
 | 
				
			||||||
 | 
					            /* Release the dead node */
 | 
				
			||||||
 | 
					            gbinder_driver_release(driver, self->handle);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        /* ServiceManager always has the same handle, and can be reanimated. */
 | 
				
			||||||
 | 
					        if (self->handle != GBINDER_SERVICEMANAGER_HANDLE) {
 | 
				
			||||||
 | 
					            gbinder_ipc_invalidate_remote_handle(ipc, self->handle);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        gbinder_driver_dead_binder_done(driver, self);
 | 
				
			||||||
 | 
					        g_signal_emit(self, gbinder_remote_object_signals[SIGNAL_DEATH], 0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					/*==========================================================================*
 | 
				
			||||||
 | 
					 * Internal interface
 | 
				
			||||||
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gboolean
 | 
					gboolean
 | 
				
			||||||
gbinder_remote_object_died_handle(
 | 
					gbinder_remote_object_reanimate(
 | 
				
			||||||
    gpointer self)
 | 
					    GBinderRemoteObject* self)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    gbinder_remote_object_died_on_main_thread(GBINDER_REMOTE_OBJECT(self));
 | 
					    /*
 | 
				
			||||||
    return G_SOURCE_REMOVE;
 | 
					     * Don't try to reanimate those who hasn't died yet. Reanimation is
 | 
				
			||||||
 | 
					     * kind of a special case and should only be used for servicemanager
 | 
				
			||||||
 | 
					     * objects.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    if (self->dead) {
 | 
				
			||||||
 | 
					        GBinderIpc* ipc = self->ipc;
 | 
				
			||||||
 | 
					        guint32 handle = self->handle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Kick the horse */
 | 
				
			||||||
 | 
					        GASSERT(self->handle == GBINDER_SERVICEMANAGER_HANDLE);
 | 
				
			||||||
 | 
					        if (gbinder_ipc_ping_sync(ipc, handle, &gbinder_ipc_sync_main) == 0) {
 | 
				
			||||||
 | 
					            GBinderRemoteObjectPriv* priv = self->priv;
 | 
				
			||||||
 | 
					            GBinderDriver* driver = ipc->driver;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* Wow, it's alive! */
 | 
				
			||||||
 | 
					            self->dead = FALSE;
 | 
				
			||||||
 | 
					            priv->acquired = TRUE;
 | 
				
			||||||
 | 
					            gbinder_ipc_looper_check(ipc); /* For death notifications */
 | 
				
			||||||
 | 
					            gbinder_driver_acquire(driver, handle);
 | 
				
			||||||
 | 
					            gbinder_driver_request_death_notification(driver, self);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return !self->dead;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_remote_object_handle_death_notification(
 | 
				
			||||||
 | 
					    GBinderRemoteObject* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /* This function is invoked from the looper thread, the caller has
 | 
				
			||||||
 | 
					     * checked the object pointer */
 | 
				
			||||||
 | 
					    GVERBOSE_("%p %u", self, self->handle);
 | 
				
			||||||
 | 
					    gbinder_idle_callback_invoke_later
 | 
				
			||||||
 | 
					        (gbinder_remote_object_handle_death_on_main_thread,
 | 
				
			||||||
 | 
					            gbinder_remote_object_ref(self), g_object_unref);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_remote_object_commit_suicide(
 | 
				
			||||||
 | 
					    GBinderRemoteObject* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /* This function is only invoked by GBinderProxyObject in context of
 | 
				
			||||||
 | 
					     * the main thread, the object pointer is checked by the caller */
 | 
				
			||||||
 | 
					    if (!self->dead) {
 | 
				
			||||||
 | 
					        GBinderIpc* ipc = self->ipc;
 | 
				
			||||||
 | 
					        GBinderDriver* driver = ipc->driver;
 | 
				
			||||||
 | 
					        GBinderRemoteObjectPriv* priv = self->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self->dead = TRUE;
 | 
				
			||||||
 | 
					        gbinder_driver_clear_death_notification(driver, self);
 | 
				
			||||||
 | 
					        if (priv->acquired) {
 | 
				
			||||||
 | 
					            priv->acquired = FALSE;
 | 
				
			||||||
 | 
					            /* Release the dead node */
 | 
				
			||||||
 | 
					            gbinder_driver_release(driver, self->handle);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        GVERBOSE_("%p %u", self, self->handle);
 | 
				
			||||||
 | 
					        gbinder_ipc_invalidate_remote_handle(self->ipc, self->handle);
 | 
				
			||||||
 | 
					        /* Don't submit BC_DEAD_BINDER_DONE because this is a suicide */
 | 
				
			||||||
 | 
					        g_signal_emit(self, gbinder_remote_object_signals[SIGNAL_DEATH], 0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*==========================================================================*
 | 
					/*==========================================================================*
 | 
				
			||||||
@@ -86,15 +167,32 @@ gbinder_remote_object_died_handle(
 | 
				
			|||||||
GBinderRemoteObject*
 | 
					GBinderRemoteObject*
 | 
				
			||||||
gbinder_remote_object_new(
 | 
					gbinder_remote_object_new(
 | 
				
			||||||
    GBinderIpc* ipc,
 | 
					    GBinderIpc* ipc,
 | 
				
			||||||
    guint32 handle)
 | 
					    guint32 handle,
 | 
				
			||||||
 | 
					    REMOTE_OBJECT_CREATE create)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (G_LIKELY(ipc) && gbinder_driver_acquire(ipc->driver, handle)) {
 | 
					    if (G_LIKELY(ipc)) {
 | 
				
			||||||
        GBinderRemoteObject* self = g_object_new
 | 
					        GBinderRemoteObject* self = g_object_new(THIS_TYPE, NULL);
 | 
				
			||||||
            (GBINDER_TYPE_REMOTE_OBJECT, NULL);
 | 
					        GBinderRemoteObjectPriv* priv = self->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self->ipc = gbinder_ipc_ref(ipc);
 | 
					        self->ipc = gbinder_ipc_ref(ipc);
 | 
				
			||||||
        self->handle = handle;
 | 
					        self->handle = handle;
 | 
				
			||||||
        gbinder_driver_request_death_notification(ipc->driver, self);
 | 
					        switch (create) {
 | 
				
			||||||
 | 
					        case REMOTE_OBJECT_CREATE_DEAD:
 | 
				
			||||||
 | 
					            self->dead = TRUE;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case REMOTE_OBJECT_CREATE_ACQUIRED:
 | 
				
			||||||
 | 
					            priv->acquired = TRUE;
 | 
				
			||||||
 | 
					            /* fallthrough */
 | 
				
			||||||
 | 
					        case REMOTE_OBJECT_CREATE_ALIVE:
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (!self->dead) {
 | 
				
			||||||
 | 
					            gbinder_ipc_looper_check(self->ipc); /* For death notifications */
 | 
				
			||||||
 | 
					            if (priv->acquired) {
 | 
				
			||||||
 | 
					                gbinder_driver_acquire(ipc->driver, handle);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            gbinder_driver_request_death_notification(ipc->driver, self);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        return self;
 | 
					        return self;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
@@ -105,7 +203,7 @@ gbinder_remote_object_ref(
 | 
				
			|||||||
    GBinderRemoteObject* self)
 | 
					    GBinderRemoteObject* self)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (G_LIKELY(self)) {
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
        g_object_ref(GBINDER_REMOTE_OBJECT(self));
 | 
					        g_object_ref(THIS(self));
 | 
				
			||||||
        return self;
 | 
					        return self;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
@@ -117,10 +215,17 @@ gbinder_remote_object_unref(
 | 
				
			|||||||
    GBinderRemoteObject* self)
 | 
					    GBinderRemoteObject* self)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (G_LIKELY(self)) {
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
        g_object_unref(GBINDER_REMOTE_OBJECT(self));
 | 
					        g_object_unref(THIS(self));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderIpc*
 | 
				
			||||||
 | 
					gbinder_remote_object_ipc(
 | 
				
			||||||
 | 
					    GBinderRemoteObject* self) /* Since 1.0.30 */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return G_LIKELY(self) ? self->ipc : NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gboolean
 | 
					gboolean
 | 
				
			||||||
gbinder_remote_object_is_dead(
 | 
					gbinder_remote_object_is_dead(
 | 
				
			||||||
    GBinderRemoteObject* self)
 | 
					    GBinderRemoteObject* self)
 | 
				
			||||||
@@ -152,18 +257,6 @@ gbinder_remote_object_remove_handler(
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					 | 
				
			||||||
gbinder_remote_object_handle_death_notification(
 | 
					 | 
				
			||||||
    GBinderRemoteObject* self)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    /* This function is invoked from the looper thread, the caller has
 | 
					 | 
				
			||||||
     * checked the object pointer */
 | 
					 | 
				
			||||||
    GVERBOSE_("%p %u", self, self->handle);
 | 
					 | 
				
			||||||
    g_main_context_invoke_full(self->priv->context, G_PRIORITY_DEFAULT,
 | 
					 | 
				
			||||||
        gbinder_remote_object_died_handle, gbinder_remote_object_ref(self),
 | 
					 | 
				
			||||||
        g_object_unref);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*==========================================================================*
 | 
					/*==========================================================================*
 | 
				
			||||||
 * Internals
 | 
					 * Internals
 | 
				
			||||||
 *==========================================================================*/
 | 
					 *==========================================================================*/
 | 
				
			||||||
@@ -174,36 +267,41 @@ gbinder_remote_object_init(
 | 
				
			|||||||
    GBinderRemoteObject* self)
 | 
					    GBinderRemoteObject* self)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GBinderRemoteObjectPriv* priv = G_TYPE_INSTANCE_GET_PRIVATE(self,
 | 
					    GBinderRemoteObjectPriv* priv = G_TYPE_INSTANCE_GET_PRIVATE(self,
 | 
				
			||||||
        GBINDER_TYPE_REMOTE_OBJECT, GBinderRemoteObjectPriv);
 | 
					        THIS_TYPE, GBinderRemoteObjectPriv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    priv->context = g_main_context_default();
 | 
					 | 
				
			||||||
    self->priv = priv;
 | 
					    self->priv = priv;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_remote_object_dispose(
 | 
					gbinder_remote_object_dispose(
 | 
				
			||||||
    GObject* remote)
 | 
					    GObject* object)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GBinderRemoteObject* self = GBINDER_REMOTE_OBJECT(remote);
 | 
					    GBinderRemoteObject* self = THIS(object);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    gbinder_ipc_remote_object_disposed(self->ipc, self);
 | 
					    gbinder_ipc_remote_object_disposed(self->ipc, self);
 | 
				
			||||||
    G_OBJECT_CLASS(gbinder_remote_object_parent_class)->dispose(remote);
 | 
					    G_OBJECT_CLASS(PARENT_CLASS)->dispose(object);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_remote_object_finalize(
 | 
					gbinder_remote_object_finalize(
 | 
				
			||||||
    GObject* remote)
 | 
					    GObject* object)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GBinderRemoteObject* self = GBINDER_REMOTE_OBJECT(remote);
 | 
					    GBinderRemoteObject* self = THIS(object);
 | 
				
			||||||
 | 
					    GBinderRemoteObjectPriv* priv = self->priv;
 | 
				
			||||||
    GBinderIpc* ipc = self->ipc;
 | 
					    GBinderIpc* ipc = self->ipc;
 | 
				
			||||||
    GBinderDriver* driver = ipc->driver;
 | 
					    GBinderDriver* driver = ipc->driver;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    gbinder_driver_clear_death_notification(driver, self);
 | 
					    gbinder_ipc_invalidate_remote_handle(ipc, self->handle);
 | 
				
			||||||
    gbinder_driver_release(driver, self->handle);
 | 
					    if (!self->dead) {
 | 
				
			||||||
 | 
					        gbinder_driver_clear_death_notification(driver, self);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (priv->acquired) {
 | 
				
			||||||
 | 
					        gbinder_driver_release(driver, self->handle);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    gbinder_ipc_unref(ipc);
 | 
					    gbinder_ipc_unref(ipc);
 | 
				
			||||||
    G_OBJECT_CLASS(gbinder_remote_object_parent_class)->finalize(remote);
 | 
					    G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -51,14 +51,33 @@ struct gbinder_remote_object {
 | 
				
			|||||||
#define gbinder_remote_object_dev(obj) (gbinder_driver_dev((obj)->ipc->driver))
 | 
					#define gbinder_remote_object_dev(obj) (gbinder_driver_dev((obj)->ipc->driver))
 | 
				
			||||||
#define gbinder_remote_object_io(obj) (gbinder_driver_io((obj)->ipc->driver))
 | 
					#define gbinder_remote_object_io(obj) (gbinder_driver_io((obj)->ipc->driver))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef enum gbinder_remote_object_create {
 | 
				
			||||||
 | 
					    REMOTE_OBJECT_CREATE_DEAD,
 | 
				
			||||||
 | 
					    REMOTE_OBJECT_CREATE_ALIVE,
 | 
				
			||||||
 | 
					    REMOTE_OBJECT_CREATE_ACQUIRED
 | 
				
			||||||
 | 
					} REMOTE_OBJECT_CREATE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderRemoteObject*
 | 
					GBinderRemoteObject*
 | 
				
			||||||
gbinder_remote_object_new(
 | 
					gbinder_remote_object_new(
 | 
				
			||||||
    GBinderIpc* ipc,
 | 
					    GBinderIpc* ipc,
 | 
				
			||||||
    guint32 handle);
 | 
					    guint32 handle,
 | 
				
			||||||
 | 
					    REMOTE_OBJECT_CREATE create)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_remote_object_reanimate(
 | 
				
			||||||
 | 
					    GBinderRemoteObject* obj)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_remote_object_handle_death_notification(
 | 
					gbinder_remote_object_handle_death_notification(
 | 
				
			||||||
    GBinderRemoteObject* obj);
 | 
					    GBinderRemoteObject* obj)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_remote_object_commit_suicide(
 | 
				
			||||||
 | 
					    GBinderRemoteObject* self)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* GBINDER_REMOTE_OBJECT_PRIVATE_H */
 | 
					#endif /* GBINDER_REMOTE_OBJECT_PRIVATE_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -31,9 +31,10 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "gbinder_remote_reply_p.h"
 | 
					#include "gbinder_remote_reply_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_local_reply_p.h"
 | 
				
			||||||
#include "gbinder_reader_p.h"
 | 
					#include "gbinder_reader_p.h"
 | 
				
			||||||
#include "gbinder_object_registry.h"
 | 
					#include "gbinder_object_registry.h"
 | 
				
			||||||
#include "gbinder_buffer.h"
 | 
					#include "gbinder_buffer_p.h"
 | 
				
			||||||
#include "gbinder_log.h"
 | 
					#include "gbinder_log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <gutil_macros.h>
 | 
					#include <gutil_macros.h>
 | 
				
			||||||
@@ -64,27 +65,20 @@ gbinder_remote_reply_free(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    gbinder_object_registry_unref(data->reg);
 | 
					    gbinder_object_registry_unref(data->reg);
 | 
				
			||||||
    gbinder_buffer_free(data->buffer);
 | 
					    gbinder_buffer_free(data->buffer);
 | 
				
			||||||
    g_free(data->objects);
 | 
					 | 
				
			||||||
    g_slice_free(GBinderRemoteReply, self);
 | 
					    g_slice_free(GBinderRemoteReply, self);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_remote_reply_set_data(
 | 
					gbinder_remote_reply_set_data(
 | 
				
			||||||
    GBinderRemoteReply* self,
 | 
					    GBinderRemoteReply* self,
 | 
				
			||||||
    GBinderBuffer* buffer,
 | 
					    GBinderBuffer* buffer)
 | 
				
			||||||
    void** objects)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (G_LIKELY(self)) {
 | 
					    /* The caller checks the pointer for NULL */
 | 
				
			||||||
        GBinderReaderData* data = &self->data;
 | 
					    GBinderReaderData* data = &self->data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        g_free(data->objects);
 | 
					    gbinder_buffer_free(data->buffer);
 | 
				
			||||||
        gbinder_buffer_free(data->buffer);
 | 
					    data->buffer = buffer;
 | 
				
			||||||
        data->buffer = buffer;
 | 
					    data->objects = gbinder_buffer_objects(buffer);
 | 
				
			||||||
        data->objects = objects;
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        gbinder_buffer_free(buffer);
 | 
					 | 
				
			||||||
        g_free(objects);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderRemoteReply*
 | 
					GBinderRemoteReply*
 | 
				
			||||||
@@ -117,6 +111,31 @@ gbinder_remote_reply_is_empty(
 | 
				
			|||||||
    return !self || !self->data.buffer || !self->data.buffer->size;
 | 
					    return !self || !self->data.buffer || !self->data.buffer->size;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderLocalReply*
 | 
				
			||||||
 | 
					gbinder_remote_reply_copy_to_local(
 | 
				
			||||||
 | 
					    GBinderRemoteReply* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return gbinder_remote_reply_convert_to_local(self, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderLocalReply*
 | 
				
			||||||
 | 
					gbinder_remote_reply_convert_to_local(
 | 
				
			||||||
 | 
					    GBinderRemoteReply* self,
 | 
				
			||||||
 | 
					    GBinderObjectConverter* convert)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
 | 
					        GBinderReaderData* d = &self->data;
 | 
				
			||||||
 | 
					        GBinderObjectRegistry* reg = d->reg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (reg) {
 | 
				
			||||||
 | 
					            return gbinder_local_reply_set_contents(gbinder_local_reply_new
 | 
				
			||||||
 | 
					                (reg->io, gbinder_buffer_protocol(d->buffer)),
 | 
				
			||||||
 | 
					                    d->buffer, convert);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
inline
 | 
					inline
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -39,17 +39,25 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
GBinderRemoteReply*
 | 
					GBinderRemoteReply*
 | 
				
			||||||
gbinder_remote_reply_new(
 | 
					gbinder_remote_reply_new(
 | 
				
			||||||
    GBinderObjectRegistry* reg);
 | 
					    GBinderObjectRegistry* reg)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderLocalReply*
 | 
				
			||||||
 | 
					gbinder_remote_reply_convert_to_local(
 | 
				
			||||||
 | 
					    GBinderRemoteReply* reply,
 | 
				
			||||||
 | 
					    GBinderObjectConverter* convert)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_remote_reply_set_data(
 | 
					gbinder_remote_reply_set_data(
 | 
				
			||||||
    GBinderRemoteReply* reply,
 | 
					    GBinderRemoteReply* reply,
 | 
				
			||||||
    GBinderBuffer* buffer,
 | 
					    GBinderBuffer* buffer)
 | 
				
			||||||
    void** objects);
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gboolean
 | 
					gboolean
 | 
				
			||||||
gbinder_remote_reply_is_empty(
 | 
					gbinder_remote_reply_is_empty(
 | 
				
			||||||
    GBinderRemoteReply* reply);
 | 
					    GBinderRemoteReply* reply)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* GBINDER_REMOTE_REPLY_PRIVATE_H */
 | 
					#endif /* GBINDER_REMOTE_REPLY_PRIVATE_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -33,13 +33,19 @@
 | 
				
			|||||||
#include "gbinder_remote_request_p.h"
 | 
					#include "gbinder_remote_request_p.h"
 | 
				
			||||||
#include "gbinder_reader_p.h"
 | 
					#include "gbinder_reader_p.h"
 | 
				
			||||||
#include "gbinder_rpc_protocol.h"
 | 
					#include "gbinder_rpc_protocol.h"
 | 
				
			||||||
 | 
					#include "gbinder_local_request_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_object_converter.h"
 | 
				
			||||||
#include "gbinder_object_registry.h"
 | 
					#include "gbinder_object_registry.h"
 | 
				
			||||||
#include "gbinder_buffer.h"
 | 
					#include "gbinder_buffer_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_driver.h"
 | 
				
			||||||
#include "gbinder_log.h"
 | 
					#include "gbinder_log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <gutil_macros.h>
 | 
					#include <gutil_macros.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct gbinder_remote_request {
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_remote_request_priv {
 | 
				
			||||||
 | 
					    GBinderRemoteRequest pub;
 | 
				
			||||||
    gint refcount;
 | 
					    gint refcount;
 | 
				
			||||||
    pid_t pid;
 | 
					    pid_t pid;
 | 
				
			||||||
    uid_t euid;
 | 
					    uid_t euid;
 | 
				
			||||||
@@ -48,7 +54,11 @@ struct gbinder_remote_request {
 | 
				
			|||||||
    char* iface2;
 | 
					    char* iface2;
 | 
				
			||||||
    gsize header_size;
 | 
					    gsize header_size;
 | 
				
			||||||
    GBinderReaderData data;
 | 
					    GBinderReaderData data;
 | 
				
			||||||
};
 | 
					} GBinderRemoteRequestPriv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBINDER_INLINE_FUNC GBinderRemoteRequestPriv*
 | 
				
			||||||
 | 
					gbinder_remote_request_cast(GBinderRemoteRequest* pub)
 | 
				
			||||||
 | 
					    { return G_LIKELY(pub) ? G_CAST(pub,GBinderRemoteRequestPriv,pub) : NULL; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderRemoteRequest*
 | 
					GBinderRemoteRequest*
 | 
				
			||||||
gbinder_remote_request_new(
 | 
					gbinder_remote_request_new(
 | 
				
			||||||
@@ -57,7 +67,7 @@ gbinder_remote_request_new(
 | 
				
			|||||||
    pid_t pid,
 | 
					    pid_t pid,
 | 
				
			||||||
    uid_t euid)
 | 
					    uid_t euid)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GBinderRemoteRequest* self = g_slice_new0(GBinderRemoteRequest);
 | 
					    GBinderRemoteRequestPriv* self = g_slice_new0(GBinderRemoteRequestPriv);
 | 
				
			||||||
    GBinderReaderData* data = &self->data;
 | 
					    GBinderReaderData* data = &self->data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    g_atomic_int_set(&self->refcount, 1);
 | 
					    g_atomic_int_set(&self->refcount, 1);
 | 
				
			||||||
@@ -65,28 +75,73 @@ gbinder_remote_request_new(
 | 
				
			|||||||
    self->euid = euid;
 | 
					    self->euid = euid;
 | 
				
			||||||
    self->protocol = protocol;
 | 
					    self->protocol = protocol;
 | 
				
			||||||
    data->reg = gbinder_object_registry_ref(reg);
 | 
					    data->reg = gbinder_object_registry_ref(reg);
 | 
				
			||||||
    return self;
 | 
					    return &self->pub;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderLocalRequest*
 | 
				
			||||||
 | 
					gbinder_remote_request_copy_to_local(
 | 
				
			||||||
 | 
					    GBinderRemoteRequest* req)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
 | 
					        GBinderReaderData* d = &self->data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return gbinder_local_request_new_from_data(d->buffer, NULL);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderLocalRequest*
 | 
				
			||||||
 | 
					gbinder_remote_request_convert_to_local(
 | 
				
			||||||
 | 
					    GBinderRemoteRequest* req,
 | 
				
			||||||
 | 
					    GBinderObjectConverter* convert)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
 | 
					        GBinderReaderData* data = &self->data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!convert || convert->protocol == self->protocol) {
 | 
				
			||||||
 | 
					            /* The same protocol, the same format of RPC header */
 | 
				
			||||||
 | 
					            return gbinder_local_request_new_from_data(data->buffer, convert);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            /* Need to translate to another format */
 | 
				
			||||||
 | 
					            GBinderLocalRequest* local = gbinder_local_request_new_iface
 | 
				
			||||||
 | 
					                (convert->io, convert->protocol, self->iface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            gbinder_local_request_append_contents(local, data->buffer,
 | 
				
			||||||
 | 
					                self->header_size, convert);
 | 
				
			||||||
 | 
					            return local;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_remote_request_free(
 | 
					gbinder_remote_request_free(
 | 
				
			||||||
    GBinderRemoteRequest* self)
 | 
					    GBinderRemoteRequestPriv* self)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GBinderReaderData* data = &self->data;
 | 
					    GBinderReaderData* data = &self->data;
 | 
				
			||||||
 | 
					    GBinderRemoteRequest* req = &self->pub;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    GASSERT(!req->tx);
 | 
				
			||||||
 | 
					    if (req->tx) {
 | 
				
			||||||
 | 
					        GWARN("Request is dropped without completing the transaction");
 | 
				
			||||||
 | 
					        gbinder_remote_request_complete(req, NULL, -ECANCELED);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    gbinder_object_registry_unref(data->reg);
 | 
					    gbinder_object_registry_unref(data->reg);
 | 
				
			||||||
    gbinder_buffer_free(data->buffer);
 | 
					    gbinder_buffer_free(data->buffer);
 | 
				
			||||||
    g_free(data->objects);
 | 
					 | 
				
			||||||
    g_free(self->iface2);
 | 
					    g_free(self->iface2);
 | 
				
			||||||
    g_slice_free(GBinderRemoteRequest, self);
 | 
					    g_slice_free(GBinderRemoteRequestPriv, self);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
inline
 | 
					inline
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_remote_request_init_reader2(
 | 
					gbinder_remote_request_init_reader2(
 | 
				
			||||||
    GBinderRemoteRequest* self,
 | 
					    GBinderRemoteRequestPriv* self,
 | 
				
			||||||
    GBinderReader* p)
 | 
					    GBinderReader* p)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /* The caller has already checked the request for NULL */
 | 
					    /* The caller has already checked the request for NULL */
 | 
				
			||||||
@@ -103,53 +158,60 @@ gbinder_remote_request_init_reader2(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_remote_request_set_data(
 | 
					gbinder_remote_request_set_data(
 | 
				
			||||||
    GBinderRemoteRequest* self,
 | 
					    GBinderRemoteRequest* req,
 | 
				
			||||||
    GBinderBuffer* buffer,
 | 
					    guint32 txcode,
 | 
				
			||||||
    void** objects)
 | 
					    GBinderBuffer* buffer)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (G_LIKELY(self)) {
 | 
					    /* The caller never passes NULL req */
 | 
				
			||||||
        GBinderReaderData* data = &self->data;
 | 
					    GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
 | 
				
			||||||
        GBinderReader reader;
 | 
					    GBinderReaderData* data = &self->data;
 | 
				
			||||||
 | 
					    GBinderReader reader;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        g_free(self->iface2);
 | 
					    g_free(self->iface2);
 | 
				
			||||||
        g_free(data->objects);
 | 
					    gbinder_buffer_free(data->buffer);
 | 
				
			||||||
        gbinder_buffer_free(data->buffer);
 | 
					    data->buffer = buffer;
 | 
				
			||||||
        data->buffer = buffer;
 | 
					    data->objects = gbinder_buffer_objects(buffer);
 | 
				
			||||||
        data->objects = objects;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Parse RPC header */
 | 
					    /* Parse RPC header */
 | 
				
			||||||
        self->header_size = 0;
 | 
					    gbinder_remote_request_init_reader2(self, &reader);
 | 
				
			||||||
        gbinder_remote_request_init_reader2(self, &reader);
 | 
					    self->iface = self->protocol->read_rpc_header(&reader, txcode,
 | 
				
			||||||
        self->iface = self->protocol->read_rpc_header(&reader, &self->iface2);
 | 
					        &self->iface2);
 | 
				
			||||||
 | 
					    if (self->iface) {
 | 
				
			||||||
        self->header_size = gbinder_reader_bytes_read(&reader);
 | 
					        self->header_size = gbinder_reader_bytes_read(&reader);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        gbinder_buffer_free(buffer);
 | 
					        /* No RPC header */
 | 
				
			||||||
        g_free(objects);
 | 
					        self->header_size = 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const char*
 | 
					const char*
 | 
				
			||||||
gbinder_remote_request_interface(
 | 
					gbinder_remote_request_interface(
 | 
				
			||||||
    GBinderRemoteRequest* self)
 | 
					    GBinderRemoteRequest* req)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return G_LIKELY(self) ? self->iface : NULL;
 | 
					    return G_LIKELY(self) ? self->iface : NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderRemoteRequest*
 | 
					GBinderRemoteRequest*
 | 
				
			||||||
gbinder_remote_request_ref(
 | 
					gbinder_remote_request_ref(
 | 
				
			||||||
    GBinderRemoteRequest* self)
 | 
					    GBinderRemoteRequest* req)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (G_LIKELY(self)) {
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
        GASSERT(self->refcount > 0);
 | 
					        GASSERT(self->refcount > 0);
 | 
				
			||||||
        g_atomic_int_inc(&self->refcount);
 | 
					        g_atomic_int_inc(&self->refcount);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return self;
 | 
					    return req;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_remote_request_unref(
 | 
					gbinder_remote_request_unref(
 | 
				
			||||||
    GBinderRemoteRequest* self)
 | 
					    GBinderRemoteRequest* req)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (G_LIKELY(self)) {
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
        GASSERT(self->refcount > 0);
 | 
					        GASSERT(self->refcount > 0);
 | 
				
			||||||
        if (g_atomic_int_dec_and_test(&self->refcount)) {
 | 
					        if (g_atomic_int_dec_and_test(&self->refcount)) {
 | 
				
			||||||
@@ -160,9 +222,11 @@ gbinder_remote_request_unref(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_remote_request_init_reader(
 | 
					gbinder_remote_request_init_reader(
 | 
				
			||||||
    GBinderRemoteRequest* self,
 | 
					    GBinderRemoteRequest* req,
 | 
				
			||||||
    GBinderReader* reader)
 | 
					    GBinderReader* reader)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (G_LIKELY(self)) {
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
        gbinder_remote_request_init_reader2(self, reader);
 | 
					        gbinder_remote_request_init_reader2(self, reader);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
@@ -172,15 +236,19 @@ gbinder_remote_request_init_reader(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
pid_t
 | 
					pid_t
 | 
				
			||||||
gbinder_remote_request_sender_pid(
 | 
					gbinder_remote_request_sender_pid(
 | 
				
			||||||
    GBinderRemoteRequest* self)
 | 
					    GBinderRemoteRequest* req)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return G_LIKELY(self) ? self->pid : (uid_t)(-1);
 | 
					    return G_LIKELY(self) ? self->pid : (uid_t)(-1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uid_t
 | 
					uid_t
 | 
				
			||||||
gbinder_remote_request_sender_euid(
 | 
					gbinder_remote_request_sender_euid(
 | 
				
			||||||
    GBinderRemoteRequest* self)
 | 
					    GBinderRemoteRequest* req)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return G_LIKELY(self) ? self->euid : (uid_t)(-1);
 | 
					    return G_LIKELY(self) ? self->euid : (uid_t)(-1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -194,9 +262,11 @@ gbinder_remote_request_read_int32(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
gboolean
 | 
					gboolean
 | 
				
			||||||
gbinder_remote_request_read_uint32(
 | 
					gbinder_remote_request_read_uint32(
 | 
				
			||||||
    GBinderRemoteRequest* self,
 | 
					    GBinderRemoteRequest* req,
 | 
				
			||||||
    guint32* value)
 | 
					    guint32* value)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (G_LIKELY(self)) {
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
        GBinderReader reader;
 | 
					        GBinderReader reader;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -216,9 +286,11 @@ gbinder_remote_request_read_int64(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
gboolean
 | 
					gboolean
 | 
				
			||||||
gbinder_remote_request_read_uint64(
 | 
					gbinder_remote_request_read_uint64(
 | 
				
			||||||
    GBinderRemoteRequest* self,
 | 
					    GBinderRemoteRequest* req,
 | 
				
			||||||
    guint64* value)
 | 
					    guint64* value)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (G_LIKELY(self)) {
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
        GBinderReader reader;
 | 
					        GBinderReader reader;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -230,8 +302,10 @@ gbinder_remote_request_read_uint64(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const char*
 | 
					const char*
 | 
				
			||||||
gbinder_remote_request_read_string8(
 | 
					gbinder_remote_request_read_string8(
 | 
				
			||||||
    GBinderRemoteRequest* self)
 | 
					    GBinderRemoteRequest* req)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (G_LIKELY(self)) {
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
        GBinderReader reader;
 | 
					        GBinderReader reader;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -243,8 +317,10 @@ gbinder_remote_request_read_string8(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
char*
 | 
					char*
 | 
				
			||||||
gbinder_remote_request_read_string16(
 | 
					gbinder_remote_request_read_string16(
 | 
				
			||||||
    GBinderRemoteRequest* self)
 | 
					    GBinderRemoteRequest* req)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (G_LIKELY(self)) {
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
        GBinderReader reader;
 | 
					        GBinderReader reader;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -256,8 +332,10 @@ gbinder_remote_request_read_string16(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
GBinderRemoteObject*
 | 
					GBinderRemoteObject*
 | 
				
			||||||
gbinder_remote_request_read_object(
 | 
					gbinder_remote_request_read_object(
 | 
				
			||||||
    GBinderRemoteRequest* self)
 | 
					    GBinderRemoteRequest* req)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (G_LIKELY(self)) {
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
        GBinderReader reader;
 | 
					        GBinderReader reader;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -37,18 +37,30 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "gbinder_types_p.h"
 | 
					#include "gbinder_types_p.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gbinder_remote_request {
 | 
				
			||||||
 | 
					    GBinderIpcLooperTx* tx;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderRemoteRequest*
 | 
					GBinderRemoteRequest*
 | 
				
			||||||
gbinder_remote_request_new(
 | 
					gbinder_remote_request_new(
 | 
				
			||||||
    GBinderObjectRegistry* reg,
 | 
					    GBinderObjectRegistry* reg,
 | 
				
			||||||
    const GBinderRpcProtocol* protocol,
 | 
					    const GBinderRpcProtocol* protocol,
 | 
				
			||||||
    pid_t pid,
 | 
					    pid_t pid,
 | 
				
			||||||
    uid_t euid);
 | 
					    uid_t euid)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_remote_request_set_data(
 | 
					gbinder_remote_request_set_data(
 | 
				
			||||||
    GBinderRemoteRequest* request,
 | 
					    GBinderRemoteRequest* request,
 | 
				
			||||||
    GBinderBuffer* buffer,
 | 
					    guint txcode,
 | 
				
			||||||
    void** objects);
 | 
					    GBinderBuffer* buffer)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderLocalRequest*
 | 
				
			||||||
 | 
					gbinder_remote_request_convert_to_local(
 | 
				
			||||||
 | 
					    GBinderRemoteRequest* req,
 | 
				
			||||||
 | 
					    GBinderObjectConverter* convert)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* GBINDER_REMOTE_REQUEST_PRIVATE_H */
 | 
					#endif /* GBINDER_REMOTE_REQUEST_PRIVATE_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -33,6 +33,18 @@
 | 
				
			|||||||
#include "gbinder_rpc_protocol.h"
 | 
					#include "gbinder_rpc_protocol.h"
 | 
				
			||||||
#include "gbinder_reader.h"
 | 
					#include "gbinder_reader.h"
 | 
				
			||||||
#include "gbinder_writer.h"
 | 
					#include "gbinder_writer.h"
 | 
				
			||||||
 | 
					#include "gbinder_config.h"
 | 
				
			||||||
 | 
					#include "gbinder_log.h"
 | 
				
			||||||
 | 
					#include "gbinder_local_object_p.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define STRICT_MODE_PENALTY_GATHER (0x40 << 16)
 | 
				
			||||||
 | 
					#define BINDER_RPC_FLAGS (STRICT_MODE_PENALTY_GATHER)
 | 
				
			||||||
 | 
					#define UNSET_WORK_SOURCE (-1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define BINDER_VND_HEADER GBINDER_FOURCC('V', 'N', 'D', 'R')
 | 
				
			||||||
 | 
					#define BINDER_SYS_HEADER GBINDER_FOURCC('S', 'Y', 'S', 'T')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*==========================================================================*
 | 
					/*==========================================================================*
 | 
				
			||||||
 * GBinderIpcProtocol callbacks (see Parcel::writeInterfaceToken in Android)
 | 
					 * GBinderIpcProtocol callbacks (see Parcel::writeInterfaceToken in Android)
 | 
				
			||||||
@@ -40,19 +52,47 @@
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 *   platform/system/libhwbinder/Parcel.cpp
 | 
					 *   platform/system/libhwbinder/Parcel.cpp
 | 
				
			||||||
 *   platform/frameworks/native/libs/binder/Parcel.cpp
 | 
					 *   platform/frameworks/native/libs/binder/Parcel.cpp
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * which mutate from version to version. Specific device => protocol
 | 
				
			||||||
 | 
					 * mapping can be optionally configured in /etc/gbinder.conf file.
 | 
				
			||||||
 | 
					 * The default protocol configuration looks like this:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   [Protocol]
 | 
				
			||||||
 | 
					 *   Default = aidl
 | 
				
			||||||
 | 
					 *   /dev/binder = aidl
 | 
				
			||||||
 | 
					 *   /dev/hwbinder = hidl
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 *==========================================================================*/
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CONF_GROUP GBINDER_CONFIG_GROUP_PROTOCOL
 | 
				
			||||||
 | 
					#define CONF_DEFAULT GBINDER_CONFIG_VALUE_DEFAULT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static GHashTable* gbinder_rpc_protocol_map = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Default protocol for those binder devices which which haven't been
 | 
				
			||||||
 | 
					 * explicitely mapped.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define DEFAULT_PROTOCOL gbinder_rpc_protocol_aidl
 | 
				
			||||||
 | 
					static const GBinderRpcProtocol DEFAULT_PROTOCOL;
 | 
				
			||||||
 | 
					static const GBinderRpcProtocol* gbinder_rpc_protocol_default =
 | 
				
			||||||
 | 
					    &DEFAULT_PROTOCOL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*==========================================================================*
 | 
					/*==========================================================================*
 | 
				
			||||||
 * /dev/binder
 | 
					 * The original AIDL protocol.
 | 
				
			||||||
 *==========================================================================*/
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* No idea what that is... */
 | 
					 | 
				
			||||||
#define STRICT_MODE_PENALTY_GATHER (0x40 << 16)
 | 
					 | 
				
			||||||
#define BINDER_RPC_FLAGS (STRICT_MODE_PENALTY_GATHER)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_rpc_protocol_binder_write_rpc_header(
 | 
					gbinder_rpc_protocol_aidl_write_ping(
 | 
				
			||||||
 | 
					    GBinderWriter* writer)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /* No payload */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_rpc_protocol_aidl_write_rpc_header(
 | 
				
			||||||
    GBinderWriter* writer,
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
    const char* iface)
 | 
					    const char* iface)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -67,11 +107,15 @@ gbinder_rpc_protocol_binder_write_rpc_header(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
const char*
 | 
					const char*
 | 
				
			||||||
gbinder_rpc_protocol_binder_read_rpc_header(
 | 
					gbinder_rpc_protocol_aidl_read_rpc_header(
 | 
				
			||||||
    GBinderReader* reader,
 | 
					    GBinderReader* reader,
 | 
				
			||||||
 | 
					    guint32 txcode,
 | 
				
			||||||
    char** iface)
 | 
					    char** iface)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (gbinder_reader_read_int32(reader, NULL)) {
 | 
					    if (txcode > GBINDER_TRANSACTION(0,0,0)) {
 | 
				
			||||||
 | 
					        /* Internal transaction e.g. GBINDER_DUMP_TRANSACTION etc. */
 | 
				
			||||||
 | 
					        *iface = NULL;
 | 
				
			||||||
 | 
					    } else if (gbinder_reader_read_int32(reader, NULL)) {
 | 
				
			||||||
        *iface = gbinder_reader_read_string16(reader);
 | 
					        *iface = gbinder_reader_read_string16(reader);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        *iface = NULL;
 | 
					        *iface = NULL;
 | 
				
			||||||
@@ -79,13 +123,166 @@ gbinder_rpc_protocol_binder_read_rpc_header(
 | 
				
			|||||||
    return *iface;
 | 
					    return *iface;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const GBinderRpcProtocol gbinder_rpc_protocol_aidl = {
 | 
				
			||||||
 | 
					    .name = "aidl",
 | 
				
			||||||
 | 
					    .ping_tx = GBINDER_PING_TRANSACTION,
 | 
				
			||||||
 | 
					    .write_ping = gbinder_rpc_protocol_aidl_write_ping,
 | 
				
			||||||
 | 
					    .write_rpc_header = gbinder_rpc_protocol_aidl_write_rpc_header,
 | 
				
			||||||
 | 
					    .read_rpc_header = gbinder_rpc_protocol_aidl_read_rpc_header
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*==========================================================================*
 | 
					/*==========================================================================*
 | 
				
			||||||
 * /dev/hwbinder
 | 
					 * AIDL protocol appeared in Android 10 (API level 29)
 | 
				
			||||||
 *==========================================================================*/
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_rpc_protocol_hwbinder_write_rpc_header(
 | 
					gbinder_rpc_protocol_aidl2_write_rpc_header(
 | 
				
			||||||
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
 | 
					    const char* iface)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * writeInt32(IPCThreadState::self()->getStrictModePolicy() |
 | 
				
			||||||
 | 
					     *               STRICT_MODE_PENALTY_GATHER);
 | 
				
			||||||
 | 
					     * writeInt32(IPCThreadState::kUnsetWorkSource);
 | 
				
			||||||
 | 
					     * writeString16(interface);
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    gbinder_writer_append_int32(writer, BINDER_RPC_FLAGS);
 | 
				
			||||||
 | 
					    gbinder_writer_append_int32(writer, UNSET_WORK_SOURCE);
 | 
				
			||||||
 | 
					    gbinder_writer_append_string16(writer, iface);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					const char*
 | 
				
			||||||
 | 
					gbinder_rpc_protocol_aidl2_read_rpc_header(
 | 
				
			||||||
 | 
					    GBinderReader* reader,
 | 
				
			||||||
 | 
					    guint32 txcode,
 | 
				
			||||||
 | 
					    char** iface)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (txcode > GBINDER_TRANSACTION(0,0,0)) {
 | 
				
			||||||
 | 
					        /* Internal transaction e.g. GBINDER_DUMP_TRANSACTION etc. */
 | 
				
			||||||
 | 
					        *iface = NULL;
 | 
				
			||||||
 | 
					    } else if (gbinder_reader_read_int32(reader, NULL) /* flags */ &&
 | 
				
			||||||
 | 
					        gbinder_reader_read_int32(reader, NULL) /* work source */) {
 | 
				
			||||||
 | 
					        *iface = gbinder_reader_read_string16(reader);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        *iface = NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return *iface;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const GBinderRpcProtocol gbinder_rpc_protocol_aidl2 = {
 | 
				
			||||||
 | 
					    .name = "aidl2",
 | 
				
			||||||
 | 
					    .ping_tx = GBINDER_PING_TRANSACTION,
 | 
				
			||||||
 | 
					    .write_ping = gbinder_rpc_protocol_aidl_write_ping, /* no payload */
 | 
				
			||||||
 | 
					    .write_rpc_header = gbinder_rpc_protocol_aidl2_write_rpc_header,
 | 
				
			||||||
 | 
					    .read_rpc_header = gbinder_rpc_protocol_aidl2_read_rpc_header
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*==========================================================================*
 | 
				
			||||||
 | 
					 * AIDL protocol appeared in Android 11 (API level 30)
 | 
				
			||||||
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_rpc_protocol_aidl3_write_rpc_header(
 | 
				
			||||||
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
 | 
					    const char* iface)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    gbinder_writer_append_int32(writer, BINDER_RPC_FLAGS);
 | 
				
			||||||
 | 
					    gbinder_writer_append_int32(writer, UNSET_WORK_SOURCE);
 | 
				
			||||||
 | 
					    gbinder_writer_append_int32(writer, BINDER_SYS_HEADER);
 | 
				
			||||||
 | 
					    gbinder_writer_append_string16(writer, iface);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					const char*
 | 
				
			||||||
 | 
					gbinder_rpc_protocol_aidl3_read_rpc_header(
 | 
				
			||||||
 | 
					    GBinderReader* reader,
 | 
				
			||||||
 | 
					    guint32 txcode,
 | 
				
			||||||
 | 
					    char** iface)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (txcode > GBINDER_TRANSACTION(0,0,0)) {
 | 
				
			||||||
 | 
					        *iface = NULL;
 | 
				
			||||||
 | 
					    } else if (gbinder_reader_read_int32(reader, NULL) /* flags */ &&
 | 
				
			||||||
 | 
					        gbinder_reader_read_int32(reader, NULL) /* work source */ &&
 | 
				
			||||||
 | 
					        gbinder_reader_read_int32(reader, NULL) /* sys header */) {
 | 
				
			||||||
 | 
					        *iface = gbinder_reader_read_string16(reader);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        *iface = NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return *iface;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_rpc_protocol_aidl3_finish_flatten_binder(
 | 
				
			||||||
 | 
					    void* out,
 | 
				
			||||||
 | 
					    GBinderLocalObject* obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (G_LIKELY(obj)) {
 | 
				
			||||||
 | 
					        *(guint32*)out = obj->stability;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        *(guint32*)out = GBINDER_STABILITY_UNDECLARED;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const GBinderRpcProtocol gbinder_rpc_protocol_aidl3 = {
 | 
				
			||||||
 | 
					    .name = "aidl3",
 | 
				
			||||||
 | 
					    .ping_tx = GBINDER_PING_TRANSACTION,
 | 
				
			||||||
 | 
					    .write_ping = gbinder_rpc_protocol_aidl_write_ping, /* no payload */
 | 
				
			||||||
 | 
					    .write_rpc_header = gbinder_rpc_protocol_aidl3_write_rpc_header,
 | 
				
			||||||
 | 
					    .read_rpc_header = gbinder_rpc_protocol_aidl3_read_rpc_header,
 | 
				
			||||||
 | 
					    .flat_binder_object_extra = 4,
 | 
				
			||||||
 | 
					    .finish_flatten_binder = gbinder_rpc_protocol_aidl3_finish_flatten_binder
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*==========================================================================*
 | 
				
			||||||
 | 
					 * AIDL protocol appeared in Android 12 (API level 31), but reverted in
 | 
				
			||||||
 | 
					 * Android 13 (API level 33).
 | 
				
			||||||
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define BINDER_WIRE_FORMAT_VERSION_AIDL4 1
 | 
				
			||||||
 | 
					struct stability_category {
 | 
				
			||||||
 | 
					    guint8 binder_wire_format_version;
 | 
				
			||||||
 | 
					    guint8 reserved[2];
 | 
				
			||||||
 | 
					    guint8 stability_level;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					G_STATIC_ASSERT(sizeof(struct stability_category) == sizeof(guint32));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_rpc_protocol_aidl4_finish_flatten_binder(
 | 
				
			||||||
 | 
					    void* out,
 | 
				
			||||||
 | 
					    GBinderLocalObject* obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct stability_category cat = {
 | 
				
			||||||
 | 
					        .binder_wire_format_version = BINDER_WIRE_FORMAT_VERSION_AIDL4,
 | 
				
			||||||
 | 
					        .reserved = { 0, 0, },
 | 
				
			||||||
 | 
					        .stability_level = obj ? obj->stability : GBINDER_STABILITY_UNDECLARED,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    memcpy(out, &cat, sizeof(cat));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const GBinderRpcProtocol gbinder_rpc_protocol_aidl4 = {
 | 
				
			||||||
 | 
					    .name = "aidl4",
 | 
				
			||||||
 | 
					    .ping_tx = GBINDER_PING_TRANSACTION,
 | 
				
			||||||
 | 
					    .write_ping = gbinder_rpc_protocol_aidl_write_ping, /* no payload */
 | 
				
			||||||
 | 
					    .write_rpc_header = gbinder_rpc_protocol_aidl3_write_rpc_header,
 | 
				
			||||||
 | 
					    .read_rpc_header = gbinder_rpc_protocol_aidl3_read_rpc_header,
 | 
				
			||||||
 | 
					    .flat_binder_object_extra = 4,
 | 
				
			||||||
 | 
					    .finish_flatten_binder = gbinder_rpc_protocol_aidl4_finish_flatten_binder
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*==========================================================================*
 | 
				
			||||||
 | 
					 * The original /dev/hwbinder protocol.
 | 
				
			||||||
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_rpc_protocol_hidl_write_rpc_header(
 | 
				
			||||||
    GBinderWriter* writer,
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
    const char* iface)
 | 
					    const char* iface)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -95,16 +292,110 @@ gbinder_rpc_protocol_hwbinder_write_rpc_header(
 | 
				
			|||||||
    gbinder_writer_append_string8(writer, iface);
 | 
					    gbinder_writer_append_string8(writer, iface);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_rpc_protocol_hidl_write_ping(
 | 
				
			||||||
 | 
					    GBinderWriter* writer)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    gbinder_rpc_protocol_hidl_write_rpc_header(writer,
 | 
				
			||||||
 | 
					        "android.hidl.base@1.0::IBase");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
const char*
 | 
					const char*
 | 
				
			||||||
gbinder_rpc_protocol_hwbinder_read_rpc_header(
 | 
					gbinder_rpc_protocol_hidl_read_rpc_header(
 | 
				
			||||||
    GBinderReader* reader,
 | 
					    GBinderReader* reader,
 | 
				
			||||||
 | 
					    guint32 txcode,
 | 
				
			||||||
    char** iface)
 | 
					    char** iface)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    *iface = NULL;
 | 
					    *iface = NULL;
 | 
				
			||||||
    return gbinder_reader_read_string8(reader);
 | 
					    return gbinder_reader_read_string8(reader);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const GBinderRpcProtocol gbinder_rpc_protocol_hidl = {
 | 
				
			||||||
 | 
					    .name = "hidl",
 | 
				
			||||||
 | 
					    .ping_tx = HIDL_PING_TRANSACTION,
 | 
				
			||||||
 | 
					    .write_ping = gbinder_rpc_protocol_hidl_write_ping,
 | 
				
			||||||
 | 
					    .write_rpc_header = gbinder_rpc_protocol_hidl_write_rpc_header,
 | 
				
			||||||
 | 
					    .read_rpc_header = gbinder_rpc_protocol_hidl_read_rpc_header
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*==========================================================================*
 | 
				
			||||||
 | 
					 * Implementation
 | 
				
			||||||
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* All known protocols */
 | 
				
			||||||
 | 
					static const GBinderRpcProtocol* gbinder_rpc_protocol_list[] = {
 | 
				
			||||||
 | 
					    &gbinder_rpc_protocol_aidl,
 | 
				
			||||||
 | 
					    &gbinder_rpc_protocol_aidl2,
 | 
				
			||||||
 | 
					    &gbinder_rpc_protocol_aidl3,
 | 
				
			||||||
 | 
					    &gbinder_rpc_protocol_aidl4,
 | 
				
			||||||
 | 
					    &gbinder_rpc_protocol_hidl
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					const GBinderRpcProtocol*
 | 
				
			||||||
 | 
					gbinder_rpc_protocol_find(
 | 
				
			||||||
 | 
					    const char* name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    guint i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < G_N_ELEMENTS(gbinder_rpc_protocol_list); i++) {
 | 
				
			||||||
 | 
					        if (!g_ascii_strcasecmp(gbinder_rpc_protocol_list[i]->name, name)) {
 | 
				
			||||||
 | 
					            return gbinder_rpc_protocol_list[i];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_rpc_protocol_map_add_default(
 | 
				
			||||||
 | 
					    GHashTable* map,
 | 
				
			||||||
 | 
					    const char* dev,
 | 
				
			||||||
 | 
					    const GBinderRpcProtocol* protocol)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (!g_hash_table_contains(map, dev)) {
 | 
				
			||||||
 | 
					        g_hash_table_insert(map, g_strdup(dev), (gpointer) protocol);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					gconstpointer
 | 
				
			||||||
 | 
					gbinder_rpc_protocol_value_map(
 | 
				
			||||||
 | 
					    const char* name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return gbinder_rpc_protocol_find(name);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					GHashTable*
 | 
				
			||||||
 | 
					gbinder_rpc_protocol_load_config()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GHashTable* map = gbinder_config_load(CONF_GROUP,
 | 
				
			||||||
 | 
					        gbinder_rpc_protocol_value_map);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Add default configuration if it's not overridden */
 | 
				
			||||||
 | 
					    gbinder_rpc_protocol_map_add_default(map,
 | 
				
			||||||
 | 
					        GBINDER_DEFAULT_BINDER, &gbinder_rpc_protocol_aidl);
 | 
				
			||||||
 | 
					    gbinder_rpc_protocol_map_add_default(map,
 | 
				
			||||||
 | 
					        GBINDER_DEFAULT_HWBINDER, &gbinder_rpc_protocol_hidl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return map;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Runs at exit */
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_rpc_protocol_exit()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (gbinder_rpc_protocol_map) {
 | 
				
			||||||
 | 
					        g_hash_table_destroy(gbinder_rpc_protocol_map);
 | 
				
			||||||
 | 
					        gbinder_rpc_protocol_map = NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    /* Reset the default too, mostly for unit testing */
 | 
				
			||||||
 | 
					    gbinder_rpc_protocol_default = &DEFAULT_PROTOCOL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*==========================================================================*
 | 
					/*==========================================================================*
 | 
				
			||||||
 * Interface
 | 
					 * Interface
 | 
				
			||||||
 *==========================================================================*/
 | 
					 *==========================================================================*/
 | 
				
			||||||
@@ -113,18 +404,43 @@ const GBinderRpcProtocol*
 | 
				
			|||||||
gbinder_rpc_protocol_for_device(
 | 
					gbinder_rpc_protocol_for_device(
 | 
				
			||||||
    const char* dev)
 | 
					    const char* dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    static const GBinderRpcProtocol protocol_binder = {
 | 
					    if (dev) {
 | 
				
			||||||
        .read_rpc_header = gbinder_rpc_protocol_binder_read_rpc_header,
 | 
					        const GBinderRpcProtocol* protocol;
 | 
				
			||||||
        .write_rpc_header = gbinder_rpc_protocol_binder_write_rpc_header
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static const GBinderRpcProtocol protocol_hwbinder = {
 | 
					        if (!gbinder_rpc_protocol_map) {
 | 
				
			||||||
        .read_rpc_header = gbinder_rpc_protocol_hwbinder_read_rpc_header,
 | 
					            const GBinderRpcProtocol* p;
 | 
				
			||||||
        .write_rpc_header = gbinder_rpc_protocol_hwbinder_write_rpc_header
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (dev && !strcmp(dev, GBINDER_DEFAULT_HWBINDER)) ?
 | 
					            /* One-time initialization */
 | 
				
			||||||
        &protocol_hwbinder : &protocol_binder;
 | 
					            gbinder_rpc_protocol_map = gbinder_rpc_protocol_load_config();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* "Default" is a special value stored in a special variable */
 | 
				
			||||||
 | 
					            p = g_hash_table_lookup(gbinder_rpc_protocol_map, CONF_DEFAULT);
 | 
				
			||||||
 | 
					            if (p) {
 | 
				
			||||||
 | 
					                g_hash_table_remove(gbinder_rpc_protocol_map, CONF_DEFAULT);
 | 
				
			||||||
 | 
					                gbinder_rpc_protocol_default = p;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                gbinder_rpc_protocol_default = &DEFAULT_PROTOCOL;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        protocol = g_hash_table_lookup(gbinder_rpc_protocol_map, dev);
 | 
				
			||||||
 | 
					        if (protocol) {
 | 
				
			||||||
 | 
					            GDEBUG("Using %s protocol for %s", protocol->name, dev);
 | 
				
			||||||
 | 
					            return protocol;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        GDEBUG("Using default protocol %s for %s",
 | 
				
			||||||
 | 
					            gbinder_rpc_protocol_default->name, dev);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        GDEBUG("Using default protocol %s",
 | 
				
			||||||
 | 
					            gbinder_rpc_protocol_default->name);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return gbinder_rpc_protocol_default;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const GBinderRpcProtocol*
 | 
				
			||||||
 | 
					gbinder_rpc_protocol_by_name(
 | 
				
			||||||
 | 
					    const char* protocol_name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return gbinder_rpc_protocol_find(protocol_name);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
				
			||||||
 * Contact: Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -36,18 +36,47 @@
 | 
				
			|||||||
#include "gbinder_types_p.h"
 | 
					#include "gbinder_types_p.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * For whatever reason services communicating via /dev/binder
 | 
					 * There are several versions of binder RPC protocol with diffferent
 | 
				
			||||||
 * and /dev/hwbinder use slightly different RPC headers.
 | 
					 * transaction headers and transaction codes.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct gbinder_rpc_protocol {
 | 
					struct gbinder_rpc_protocol {
 | 
				
			||||||
    const char* (*read_rpc_header)(GBinderReader* reader, char** iface);
 | 
					    const char* name;
 | 
				
			||||||
 | 
					    guint32 ping_tx;
 | 
				
			||||||
 | 
					    void (*write_ping)(GBinderWriter* writer);
 | 
				
			||||||
    void (*write_rpc_header)(GBinderWriter* writer, const char* iface);
 | 
					    void (*write_rpc_header)(GBinderWriter* writer, const char* iface);
 | 
				
			||||||
 | 
					    const char* (*read_rpc_header)(GBinderReader* reader, guint32 txcode,
 | 
				
			||||||
 | 
					        char** iface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * For the sake of simplicity, let's assume that the trailer has a
 | 
				
			||||||
 | 
					     * fixed size and that size is the same on both 32 and 64 bit platforms.
 | 
				
			||||||
 | 
					     * Also note that finish_unflatten_binder() is only invoked for the
 | 
				
			||||||
 | 
					     * remote objects that are not NULL, otherwise flat_binder_object_extra
 | 
				
			||||||
 | 
					     * bytes are just skipped.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    gsize flat_binder_object_extra;
 | 
				
			||||||
 | 
					    void (*finish_flatten_binder)(void* out, GBinderLocalObject* obj);
 | 
				
			||||||
 | 
					    void (*finish_unflatten_binder)(const void* in, GBinderRemoteObject* obj);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const GBinderRpcProtocol*
 | 
				
			||||||
 | 
					gbinder_rpc_protocol_by_name(
 | 
				
			||||||
 | 
					    const char* protocol_name)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Returns one of the above based on the device name */
 | 
				
			||||||
const GBinderRpcProtocol*
 | 
					const GBinderRpcProtocol*
 | 
				
			||||||
gbinder_rpc_protocol_for_device(
 | 
					gbinder_rpc_protocol_for_device(
 | 
				
			||||||
    const char* dev);
 | 
					    const char* dev)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Runs at exit, declared here strictly for unit tests */
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_rpc_protocol_exit(
 | 
				
			||||||
 | 
					    void)
 | 
				
			||||||
 | 
					    GBINDER_DESTRUCTOR
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* GBINDER_RPC_PROTOCOL_H */
 | 
					#endif /* GBINDER_RPC_PROTOCOL_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2023 Slava Monich <slava@monich.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -32,18 +32,88 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "gbinder_servicemanager_p.h"
 | 
					#include "gbinder_servicemanager_p.h"
 | 
				
			||||||
#include "gbinder_client_p.h"
 | 
					#include "gbinder_client_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_config.h"
 | 
				
			||||||
#include "gbinder_local_object_p.h"
 | 
					#include "gbinder_local_object_p.h"
 | 
				
			||||||
#include "gbinder_remote_object_p.h"
 | 
					#include "gbinder_remote_object_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_eventloop_p.h"
 | 
				
			||||||
#include "gbinder_driver.h"
 | 
					#include "gbinder_driver.h"
 | 
				
			||||||
#include "gbinder_ipc.h"
 | 
					#include "gbinder_ipc.h"
 | 
				
			||||||
#include "gbinder_log.h"
 | 
					#include "gbinder_log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <gbinder_client.h>
 | 
					#include <gbinder_client.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <gutil_idlepool.h>
 | 
					#include <gutil_misc.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <errno.h>
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*==========================================================================*
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Different versions of Android come with different flavors of service
 | 
				
			||||||
 | 
					 * managers. They are usually based on these two more or less independent
 | 
				
			||||||
 | 
					 * variants:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   platform/frameworks/native/cmds/servicemanager/ServiceManager.cpp
 | 
				
			||||||
 | 
					 *   platform/system/hwservicemanager/ServiceManager.cpp
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * They are talking slightly different protocols which slightly mutate
 | 
				
			||||||
 | 
					 * from version to version. If that's not complex enough, different
 | 
				
			||||||
 | 
					 * kinds of service managers can be running simultaneously, serving
 | 
				
			||||||
 | 
					 * different binder devices. Specific device => servicemanager mapping
 | 
				
			||||||
 | 
					 * can be optionally configured in /etc/gbinder.conf file. The default
 | 
				
			||||||
 | 
					 * service manager configuration looks like this:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   [ServiceManager]
 | 
				
			||||||
 | 
					 *   Default = aidl
 | 
				
			||||||
 | 
					 *   /dev/binder = aidl
 | 
				
			||||||
 | 
					 *   /dev/hwbinder = hidl
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CONF_GROUP GBINDER_CONFIG_GROUP_SERVICEMANAGER
 | 
				
			||||||
 | 
					#define CONF_DEFAULT GBINDER_CONFIG_VALUE_DEFAULT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_servicemanager_type {
 | 
				
			||||||
 | 
					    const char* name;
 | 
				
			||||||
 | 
					    GType (*get_type)(void);
 | 
				
			||||||
 | 
					} GBinderServiceManagerType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const GBinderServiceManagerType gbinder_servicemanager_types[] = {
 | 
				
			||||||
 | 
					    { "aidl", gbinder_servicemanager_aidl_get_type },
 | 
				
			||||||
 | 
					    { "aidl2", gbinder_servicemanager_aidl2_get_type },
 | 
				
			||||||
 | 
					    { "aidl3", gbinder_servicemanager_aidl3_get_type },
 | 
				
			||||||
 | 
					    { "aidl4", gbinder_servicemanager_aidl4_get_type },
 | 
				
			||||||
 | 
					    { "hidl", gbinder_servicemanager_hidl_get_type }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SERVICEMANAGER_TYPE_AIDL (gbinder_servicemanager_types + 0)
 | 
				
			||||||
 | 
					#define SERVICEMANAGER_TYPE_HIDL (gbinder_servicemanager_types + 4)
 | 
				
			||||||
 | 
					#define SERVICEMANAGER_TYPE_DEFAULT SERVICEMANAGER_TYPE_AIDL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static GHashTable* gbinder_servicemanager_map = NULL;
 | 
				
			||||||
 | 
					static const GBinderServiceManagerType* gbinder_servicemanager_default =
 | 
				
			||||||
 | 
					    SERVICEMANAGER_TYPE_DEFAULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PRESENSE_WAIT_MS_MIN  (100)
 | 
				
			||||||
 | 
					#define PRESENSE_WAIT_MS_MAX  (1000)
 | 
				
			||||||
 | 
					#define PRESENSE_WAIT_MS_STEP (100)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_servicemanager_watch {
 | 
				
			||||||
 | 
					    char* name;
 | 
				
			||||||
 | 
					    char* detail;
 | 
				
			||||||
 | 
					    GQuark quark;
 | 
				
			||||||
 | 
					    gboolean watched;
 | 
				
			||||||
 | 
					} GBinderServiceManagerWatch;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gbinder_servicemanager_priv {
 | 
				
			||||||
 | 
					    GHashTable* watch_table;
 | 
				
			||||||
 | 
					    gulong death_id;
 | 
				
			||||||
 | 
					    gboolean present;
 | 
				
			||||||
 | 
					    GBinderEventLoopTimeout* presence_check;
 | 
				
			||||||
 | 
					    guint presence_check_delay_ms;
 | 
				
			||||||
 | 
					    GBinderEventLoopCallback* autorelease_cb;
 | 
				
			||||||
 | 
					    GSList* autorelease;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
G_DEFINE_ABSTRACT_TYPE(GBinderServiceManager, gbinder_servicemanager,
 | 
					G_DEFINE_ABSTRACT_TYPE(GBinderServiceManager, gbinder_servicemanager,
 | 
				
			||||||
    G_TYPE_OBJECT)
 | 
					    G_TYPE_OBJECT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -51,15 +121,24 @@ G_DEFINE_ABSTRACT_TYPE(GBinderServiceManager, gbinder_servicemanager,
 | 
				
			|||||||
#define GBINDER_SERVICEMANAGER(obj) \
 | 
					#define GBINDER_SERVICEMANAGER(obj) \
 | 
				
			||||||
    G_TYPE_CHECK_INSTANCE_CAST((obj), GBINDER_TYPE_SERVICEMANAGER, \
 | 
					    G_TYPE_CHECK_INSTANCE_CAST((obj), GBINDER_TYPE_SERVICEMANAGER, \
 | 
				
			||||||
    GBinderServiceManager)
 | 
					    GBinderServiceManager)
 | 
				
			||||||
#define GBINDER_SERVICEMANAGER_CLASS(klass) \
 | 
					 | 
				
			||||||
    G_TYPE_CHECK_CLASS_CAST((klass), GBINDER_TYPE_SERVICEMANAGER, \
 | 
					 | 
				
			||||||
    GBinderServiceManagerClass)
 | 
					 | 
				
			||||||
#define GBINDER_SERVICEMANAGER_GET_CLASS(obj) \
 | 
					#define GBINDER_SERVICEMANAGER_GET_CLASS(obj) \
 | 
				
			||||||
    G_TYPE_INSTANCE_GET_CLASS((obj), GBINDER_TYPE_SERVICEMANAGER, \
 | 
					    G_TYPE_INSTANCE_GET_CLASS((obj), GBINDER_TYPE_SERVICEMANAGER, \
 | 
				
			||||||
    GBinderServiceManagerClass)
 | 
					    GBinderServiceManagerClass)
 | 
				
			||||||
#define GBINDER_IS_SERVICEMANAGER_TYPE(klass) \
 | 
					#define GBINDER_IS_SERVICEMANAGER_TYPE(klass) \
 | 
				
			||||||
    G_TYPE_CHECK_CLASS_TYPE(klass, GBINDER_TYPE_SERVICEMANAGER)
 | 
					    G_TYPE_CHECK_CLASS_TYPE(klass, GBINDER_TYPE_SERVICEMANAGER)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum gbinder_servicemanager_signal {
 | 
				
			||||||
 | 
					    SIGNAL_PRESENCE,
 | 
				
			||||||
 | 
					    SIGNAL_REGISTRATION,
 | 
				
			||||||
 | 
					    SIGNAL_COUNT
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const char SIGNAL_PRESENCE_NAME[] = "servicemanager-presence";
 | 
				
			||||||
 | 
					static const char SIGNAL_REGISTRATION_NAME[] = "servicemanager-registration";
 | 
				
			||||||
 | 
					#define DETAIL_LEN 32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static guint gbinder_servicemanager_signals[SIGNAL_COUNT] = { 0 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*==========================================================================*
 | 
					/*==========================================================================*
 | 
				
			||||||
 * Implementation
 | 
					 * Implementation
 | 
				
			||||||
 *==========================================================================*/
 | 
					 *==========================================================================*/
 | 
				
			||||||
@@ -81,53 +160,29 @@ gbinder_servicemanager_class_ref(
 | 
				
			|||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderServiceManager*
 | 
					static
 | 
				
			||||||
gbinder_servicemanager_new_with_type(
 | 
					GBinderServiceManagerWatch*
 | 
				
			||||||
    GType type,
 | 
					gbinder_servicemanager_watch_new(
 | 
				
			||||||
    const char* dev)
 | 
					    const char* name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GBinderServiceManager* self = NULL;
 | 
					    GBinderServiceManagerWatch* watch = g_new0(GBinderServiceManagerWatch, 1);
 | 
				
			||||||
    GBinderServiceManagerClass* klass = gbinder_servicemanager_class_ref(type);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (klass) {
 | 
					    watch->name = g_strdup(name);
 | 
				
			||||||
        GBinderIpc* ipc;
 | 
					    watch->detail = g_compute_checksum_for_string(G_CHECKSUM_MD5, name, -1);
 | 
				
			||||||
 | 
					    watch->quark = g_quark_from_string(watch->detail);
 | 
				
			||||||
 | 
					    return watch;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!dev) dev = klass->default_device;
 | 
					static
 | 
				
			||||||
        ipc = gbinder_ipc_new(dev);
 | 
					void
 | 
				
			||||||
        if (ipc) {
 | 
					gbinder_servicemanager_watch_free(
 | 
				
			||||||
            GBinderRemoteObject* object = gbinder_ipc_get_remote_object
 | 
					    gpointer data)
 | 
				
			||||||
                (ipc, klass->handle);
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServiceManagerWatch* watch = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (object) {
 | 
					    g_free(watch->name);
 | 
				
			||||||
                /* Lock */
 | 
					    g_free(watch->detail);
 | 
				
			||||||
                g_mutex_lock(&klass->mutex);
 | 
					    g_free(watch);
 | 
				
			||||||
                if (klass->table) {
 | 
					 | 
				
			||||||
                    self = g_hash_table_lookup(klass->table, dev);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                if (self) {
 | 
					 | 
				
			||||||
                    gbinder_servicemanager_ref(self);
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    char* key = g_strdup(dev); /* Owned by the hashtable */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    GVERBOSE_("%s", dev);
 | 
					 | 
				
			||||||
                    self = g_object_new(type, NULL);
 | 
					 | 
				
			||||||
                    self->client = gbinder_client_new(object, klass->iface);
 | 
					 | 
				
			||||||
                    self->dev = gbinder_remote_object_dev(object);
 | 
					 | 
				
			||||||
                    if (!klass->table) {
 | 
					 | 
				
			||||||
                        klass->table = g_hash_table_new_full(g_str_hash,
 | 
					 | 
				
			||||||
                            g_str_equal, g_free, NULL);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    g_hash_table_replace(klass->table, key, self);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                g_mutex_unlock(&klass->mutex);
 | 
					 | 
				
			||||||
                /* Unlock */
 | 
					 | 
				
			||||||
                gbinder_remote_object_unref(object);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            gbinder_ipc_unref(ipc);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        g_type_class_unref(klass);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return self;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct gbinder_servicemanager_list_tx_data {
 | 
					typedef struct gbinder_servicemanager_list_tx_data {
 | 
				
			||||||
@@ -144,7 +199,8 @@ gbinder_servicemanager_list_tx_exec(
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    GBinderServiceManagerListTxData* data = tx->user_data;
 | 
					    GBinderServiceManagerListTxData* data = tx->user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    data->result = GBINDER_SERVICEMANAGER_GET_CLASS(data->sm)->list(data->sm);
 | 
					    data->result = GBINDER_SERVICEMANAGER_GET_CLASS(data->sm)->
 | 
				
			||||||
 | 
					        list(data->sm, &gbinder_ipc_sync_worker);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
@@ -157,6 +213,7 @@ gbinder_servicemanager_list_tx_done(
 | 
				
			|||||||
    if (!data->func(data->sm, data->result, data->user_data)) {
 | 
					    if (!data->func(data->sm, data->result, data->user_data)) {
 | 
				
			||||||
        g_strfreev(data->result);
 | 
					        g_strfreev(data->result);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    data->result = NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
@@ -166,6 +223,7 @@ gbinder_servicemanager_list_tx_free(
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    GBinderServiceManagerListTxData* data = user_data;
 | 
					    GBinderServiceManagerListTxData* data = user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_strfreev(data->result);
 | 
				
			||||||
    gbinder_servicemanager_unref(data->sm);
 | 
					    gbinder_servicemanager_unref(data->sm);
 | 
				
			||||||
    g_slice_free(GBinderServiceManagerListTxData, data);
 | 
					    g_slice_free(GBinderServiceManagerListTxData, data);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -186,8 +244,9 @@ gbinder_servicemanager_get_service_tx_exec(
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    GBinderServiceManagerGetServiceTxData* data = tx->user_data;
 | 
					    GBinderServiceManagerGetServiceTxData* data = tx->user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    data->obj = GBINDER_SERVICEMANAGER_GET_CLASS(data->sm)->get_service
 | 
					    data->obj = GBINDER_SERVICEMANAGER_GET_CLASS(data->sm)->
 | 
				
			||||||
            (data->sm, data->name, &data->status);
 | 
					        get_service(data->sm, data->name, &data->status,
 | 
				
			||||||
 | 
					            &gbinder_ipc_sync_worker);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
@@ -229,8 +288,8 @@ gbinder_servicemanager_add_service_tx_exec(
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    GBinderServiceManagerAddServiceTxData* data = tx->user_data;
 | 
					    GBinderServiceManagerAddServiceTxData* data = tx->user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    data->status = GBINDER_SERVICEMANAGER_GET_CLASS(data->sm)->add_service
 | 
					    data->status = GBINDER_SERVICEMANAGER_GET_CLASS(data->sm)->
 | 
				
			||||||
            (data->sm, data->name, data->obj);
 | 
					        add_service(data->sm, data->name, data->obj, &gbinder_ipc_sync_worker);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
@@ -256,6 +315,303 @@ gbinder_servicemanager_add_service_tx_free(
 | 
				
			|||||||
    g_slice_free(GBinderServiceManagerAddServiceTxData, data);
 | 
					    g_slice_free(GBinderServiceManagerAddServiceTxData, data);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_reanimated(
 | 
				
			||||||
 | 
					    GBinderServiceManager* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServiceManagerPriv* priv = self->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (priv->presence_check) {
 | 
				
			||||||
 | 
					        gbinder_timeout_remove(priv->presence_check);
 | 
				
			||||||
 | 
					        priv->presence_check = NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    GINFO("Service manager %s has appeared", self->dev);
 | 
				
			||||||
 | 
					    /* Re-arm the watches */
 | 
				
			||||||
 | 
					    if (g_hash_table_size(priv->watch_table) > 0) {
 | 
				
			||||||
 | 
					        gpointer value;
 | 
				
			||||||
 | 
					        GHashTableIter it;
 | 
				
			||||||
 | 
					        GBinderServiceManagerClass* klass =
 | 
				
			||||||
 | 
					            GBINDER_SERVICEMANAGER_GET_CLASS(self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        g_hash_table_iter_init(&it, priv->watch_table);
 | 
				
			||||||
 | 
					        while (g_hash_table_iter_next(&it, NULL, &value)) {
 | 
				
			||||||
 | 
					            GBinderServiceManagerWatch* watch = value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            GASSERT(!watch->watched);
 | 
				
			||||||
 | 
					            watch->watched = klass->watch(self, watch->name);
 | 
				
			||||||
 | 
					            if (watch->watched) {
 | 
				
			||||||
 | 
					                GDEBUG("Watching %s", watch->name);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                GWARN("Failed to watch %s", watch->name);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    g_signal_emit(self, gbinder_servicemanager_signals[SIGNAL_PRESENCE], 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_servicemanager_presense_check_timer(
 | 
				
			||||||
 | 
					    gpointer user_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServiceManager* self = GBINDER_SERVICEMANAGER(user_data);
 | 
				
			||||||
 | 
					    GBinderRemoteObject* remote = self->client->remote;
 | 
				
			||||||
 | 
					    GBinderServiceManagerPriv* priv = self->priv;
 | 
				
			||||||
 | 
					    gboolean result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    GASSERT(remote->dead);
 | 
				
			||||||
 | 
					    gbinder_servicemanager_ref(self);
 | 
				
			||||||
 | 
					    if (gbinder_remote_object_reanimate(remote)) {
 | 
				
			||||||
 | 
					        /* Done */
 | 
				
			||||||
 | 
					        priv->presence_check = NULL;
 | 
				
			||||||
 | 
					        gbinder_servicemanager_reanimated(self);
 | 
				
			||||||
 | 
					        result = G_SOURCE_REMOVE;
 | 
				
			||||||
 | 
					    } else if (priv->presence_check_delay_ms < PRESENSE_WAIT_MS_MAX) {
 | 
				
			||||||
 | 
					        priv->presence_check_delay_ms += PRESENSE_WAIT_MS_STEP;
 | 
				
			||||||
 | 
					        priv->presence_check =
 | 
				
			||||||
 | 
					            gbinder_timeout_add(priv->presence_check_delay_ms,
 | 
				
			||||||
 | 
					                gbinder_servicemanager_presense_check_timer, self);
 | 
				
			||||||
 | 
					        result = G_SOURCE_REMOVE;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        result = G_SOURCE_CONTINUE;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    gbinder_servicemanager_unref(self);
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_presence_check_start(
 | 
				
			||||||
 | 
					    GBinderServiceManager* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServiceManagerPriv* priv = self->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    GASSERT(!priv->presence_check);
 | 
				
			||||||
 | 
					    priv->presence_check_delay_ms = PRESENSE_WAIT_MS_MIN;
 | 
				
			||||||
 | 
					    priv->presence_check = gbinder_timeout_add(PRESENSE_WAIT_MS_MIN,
 | 
				
			||||||
 | 
					        gbinder_servicemanager_presense_check_timer, self);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_died(
 | 
				
			||||||
 | 
					    GBinderRemoteObject* remote,
 | 
				
			||||||
 | 
					    void* user_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServiceManager* self = GBINDER_SERVICEMANAGER(user_data);
 | 
				
			||||||
 | 
					    GBinderServiceManagerPriv* priv = self->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    GWARN("Service manager %s has died", self->dev);
 | 
				
			||||||
 | 
					    gbinder_servicemanager_presence_check_start(self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Will re-arm watches after servicemanager gets restarted */
 | 
				
			||||||
 | 
					    if (g_hash_table_size(priv->watch_table) > 0) {
 | 
				
			||||||
 | 
					        gpointer value;
 | 
				
			||||||
 | 
					        GHashTableIter it;
 | 
				
			||||||
 | 
					        GBinderServiceManagerClass* klass =
 | 
				
			||||||
 | 
					            GBINDER_SERVICEMANAGER_GET_CLASS(self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        g_hash_table_iter_init(&it, priv->watch_table);
 | 
				
			||||||
 | 
					        while (g_hash_table_iter_next(&it, NULL, &value)) {
 | 
				
			||||||
 | 
					            GBinderServiceManagerWatch* watch = value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (watch->watched) {
 | 
				
			||||||
 | 
					                GDEBUG("Unwatching %s", watch->name);
 | 
				
			||||||
 | 
					                watch->watched = FALSE;
 | 
				
			||||||
 | 
					                klass->unwatch(self, watch->name);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    g_signal_emit(self, gbinder_servicemanager_signals[SIGNAL_PRESENCE], 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_sleep_ms(
 | 
				
			||||||
 | 
					    gulong ms)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct timespec wait;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    wait.tv_sec = ms/1000;                /* seconds */
 | 
				
			||||||
 | 
					    wait.tv_nsec = (ms % 1000) * 1000000; /* nanoseconds */
 | 
				
			||||||
 | 
					    while (nanosleep(&wait, &wait) == -1 && errno == EINTR &&
 | 
				
			||||||
 | 
					        (wait.tv_sec > 0 || wait.tv_nsec > 0));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_autorelease_cb(
 | 
				
			||||||
 | 
					    gpointer data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServiceManager* self = GBINDER_SERVICEMANAGER(data);
 | 
				
			||||||
 | 
					    GBinderServiceManagerPriv* priv = self->priv;
 | 
				
			||||||
 | 
					    GSList* list = priv->autorelease;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    priv->autorelease_cb = NULL;
 | 
				
			||||||
 | 
					    priv->autorelease = NULL;
 | 
				
			||||||
 | 
					    g_slist_free_full(list, g_object_unref);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_map_add_default(
 | 
				
			||||||
 | 
					    GHashTable* map,
 | 
				
			||||||
 | 
					    const char* dev,
 | 
				
			||||||
 | 
					    const GBinderServiceManagerType* type)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (!g_hash_table_contains(map, dev)) {
 | 
				
			||||||
 | 
					        g_hash_table_insert(map, g_strdup(dev), (gpointer) type);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					gconstpointer
 | 
				
			||||||
 | 
					gbinder_servicemanager_value_map(
 | 
				
			||||||
 | 
					    const char* name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    guint i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < G_N_ELEMENTS(gbinder_servicemanager_types); i++) {
 | 
				
			||||||
 | 
					        const GBinderServiceManagerType* t = gbinder_servicemanager_types + i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!g_strcmp0(name, t->name)) {
 | 
				
			||||||
 | 
					            return t;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					GHashTable*
 | 
				
			||||||
 | 
					gbinder_servicemanager_load_config()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GHashTable* map = gbinder_config_load(CONF_GROUP,
 | 
				
			||||||
 | 
					        gbinder_servicemanager_value_map);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Add default configuration if it's not overridden */
 | 
				
			||||||
 | 
					    gbinder_servicemanager_map_add_default(map,
 | 
				
			||||||
 | 
					        GBINDER_DEFAULT_BINDER, SERVICEMANAGER_TYPE_AIDL);
 | 
				
			||||||
 | 
					    gbinder_servicemanager_map_add_default(map,
 | 
				
			||||||
 | 
					        GBINDER_DEFAULT_HWBINDER, SERVICEMANAGER_TYPE_HIDL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return map;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Runs at exit */
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_exit(
 | 
				
			||||||
 | 
					    void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (gbinder_servicemanager_map) {
 | 
				
			||||||
 | 
					        g_hash_table_destroy(gbinder_servicemanager_map);
 | 
				
			||||||
 | 
					        gbinder_servicemanager_map = NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    /* Reset the default too, mostly for unit testing */
 | 
				
			||||||
 | 
					    gbinder_servicemanager_default = SERVICEMANAGER_TYPE_DEFAULT;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*==========================================================================*
 | 
				
			||||||
 | 
					 * Internal interface
 | 
				
			||||||
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderServiceManager*
 | 
				
			||||||
 | 
					gbinder_servicemanager_new_with_type(
 | 
				
			||||||
 | 
					    GType type,
 | 
				
			||||||
 | 
					    const char* dev,
 | 
				
			||||||
 | 
					    const char* rpc_protocol)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServiceManager* self = NULL;
 | 
				
			||||||
 | 
					    GBinderServiceManagerClass* klass = gbinder_servicemanager_class_ref(type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (klass) {
 | 
				
			||||||
 | 
					        GBinderIpc* ipc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!dev) dev = klass->default_device;
 | 
				
			||||||
 | 
					        ipc = gbinder_ipc_new(dev, rpc_protocol);
 | 
				
			||||||
 | 
					        if (ipc) {
 | 
				
			||||||
 | 
					            /* Create a (possibly) dead service manager object */
 | 
				
			||||||
 | 
					            GBinderRemoteObject* object = gbinder_ipc_get_service_manager(ipc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (object) {
 | 
				
			||||||
 | 
					                gboolean first_ref;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Lock */
 | 
				
			||||||
 | 
					                g_mutex_lock(&klass->mutex);
 | 
				
			||||||
 | 
					                if (klass->table) {
 | 
				
			||||||
 | 
					                    self = g_hash_table_lookup(klass->table, dev);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                if (self) {
 | 
				
			||||||
 | 
					                    first_ref = FALSE;
 | 
				
			||||||
 | 
					                    gbinder_servicemanager_ref(self);
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    char* key = g_strdup(dev); /* Owned by the hashtable */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    first_ref = TRUE;
 | 
				
			||||||
 | 
					                    self = g_object_new(type, NULL);
 | 
				
			||||||
 | 
					                    self->client = gbinder_client_new(object, klass->iface);
 | 
				
			||||||
 | 
					                    self->dev = gbinder_remote_object_dev(object);
 | 
				
			||||||
 | 
					                    if (!klass->table) {
 | 
				
			||||||
 | 
					                        klass->table = g_hash_table_new_full(g_str_hash,
 | 
				
			||||||
 | 
					                            g_str_equal, g_free, NULL);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    g_hash_table_replace(klass->table, key, self);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                g_mutex_unlock(&klass->mutex);
 | 
				
			||||||
 | 
					                /* Unlock */
 | 
				
			||||||
 | 
					                if (first_ref) {
 | 
				
			||||||
 | 
					                    GBinderServiceManagerPriv* priv = self->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    priv->death_id =
 | 
				
			||||||
 | 
					                        gbinder_remote_object_add_death_handler(object,
 | 
				
			||||||
 | 
					                            gbinder_servicemanager_died, self);
 | 
				
			||||||
 | 
					                    /* Query the actual state if necessary */
 | 
				
			||||||
 | 
					                    gbinder_remote_object_reanimate(object);
 | 
				
			||||||
 | 
					                    if (object->dead) {
 | 
				
			||||||
 | 
					                        gbinder_servicemanager_presence_check_start(self);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    GDEBUG("%s has %sservice manager", dev,
 | 
				
			||||||
 | 
					                        object->dead ? "no " : "");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                gbinder_remote_object_unref(object);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            gbinder_ipc_unref(ipc);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        g_type_class_unref(klass);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return self;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_service_registered(
 | 
				
			||||||
 | 
					    GBinderServiceManager* self,
 | 
				
			||||||
 | 
					    const char* name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServiceManagerClass* klass = GBINDER_SERVICEMANAGER_GET_CLASS(self);
 | 
				
			||||||
 | 
					    GBinderServiceManagerPriv* priv = self->priv;
 | 
				
			||||||
 | 
					    GBinderServiceManagerWatch* watch = NULL;
 | 
				
			||||||
 | 
					    const char* normalized_name;
 | 
				
			||||||
 | 
					    char* tmp_name = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (klass->check_name(self, name)) {
 | 
				
			||||||
 | 
					    case GBINDER_SERVICEMANAGER_NAME_OK:
 | 
				
			||||||
 | 
					        normalized_name = name;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case GBINDER_SERVICEMANAGER_NAME_NORMALIZE:
 | 
				
			||||||
 | 
					        normalized_name = tmp_name = klass->normalize_name(self, name);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					        normalized_name = NULL;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (normalized_name) {
 | 
				
			||||||
 | 
					        watch = g_hash_table_lookup(priv->watch_table, normalized_name);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    g_free(tmp_name);
 | 
				
			||||||
 | 
					    g_signal_emit(self, gbinder_servicemanager_signals[SIGNAL_REGISTRATION],
 | 
				
			||||||
 | 
					        watch ? watch->quark : 0, name);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*==========================================================================*
 | 
					/*==========================================================================*
 | 
				
			||||||
 * Interface
 | 
					 * Interface
 | 
				
			||||||
 *==========================================================================*/
 | 
					 *==========================================================================*/
 | 
				
			||||||
@@ -264,10 +620,57 @@ GBinderServiceManager*
 | 
				
			|||||||
gbinder_servicemanager_new(
 | 
					gbinder_servicemanager_new(
 | 
				
			||||||
    const char* dev)
 | 
					    const char* dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (!g_strcmp0(dev, GBINDER_DEFAULT_HWBINDER)) {
 | 
					    return gbinder_servicemanager_new2(dev, NULL, NULL);
 | 
				
			||||||
        return gbinder_hwservicemanager_new(dev);
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderServiceManager*
 | 
				
			||||||
 | 
					gbinder_servicemanager_new2(
 | 
				
			||||||
 | 
					    const char* dev,
 | 
				
			||||||
 | 
					    const char* sm_protocol,
 | 
				
			||||||
 | 
					    const char* rpc_protocol) /* Since 1.1.20 */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (!dev) {
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    } else if (!sm_protocol) {
 | 
				
			||||||
 | 
					        const GBinderServiceManagerType* type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* One-time initialization */
 | 
				
			||||||
 | 
					        if (!gbinder_servicemanager_map) {
 | 
				
			||||||
 | 
					            gbinder_servicemanager_map = gbinder_servicemanager_load_config();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* "Default" is a special value stored in a special variable */
 | 
				
			||||||
 | 
					            type = g_hash_table_lookup(gbinder_servicemanager_map,
 | 
				
			||||||
 | 
					                CONF_DEFAULT);
 | 
				
			||||||
 | 
					            if (type) {
 | 
				
			||||||
 | 
					                g_hash_table_remove(gbinder_servicemanager_map, CONF_DEFAULT);
 | 
				
			||||||
 | 
					                gbinder_servicemanager_default = type;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                gbinder_servicemanager_default = SERVICEMANAGER_TYPE_DEFAULT;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* If no protocol is specified, pick one up based on the device name */
 | 
				
			||||||
 | 
					        type = g_hash_table_lookup(gbinder_servicemanager_map, dev);
 | 
				
			||||||
 | 
					        if (type) {
 | 
				
			||||||
 | 
					            GDEBUG("Using %s service manager for %s", type->name, dev);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            type = gbinder_servicemanager_default;
 | 
				
			||||||
 | 
					            GDEBUG("Using default service manager %s for %s", type->name, dev);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return gbinder_servicemanager_new_with_type(type->get_type(), dev,
 | 
				
			||||||
 | 
					            rpc_protocol);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        return gbinder_defaultservicemanager_new(dev);
 | 
					        /* If protocol name is specified, it must be a valid one */
 | 
				
			||||||
 | 
					        const GBinderServiceManagerType* type =
 | 
				
			||||||
 | 
					            gbinder_servicemanager_value_map(sm_protocol);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (type) {
 | 
				
			||||||
 | 
					            return gbinder_servicemanager_new_with_type(type->get_type(), dev,
 | 
				
			||||||
 | 
					                rpc_protocol);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            GWARN("Unknown servicemanager protocol %s", sm_protocol);
 | 
				
			||||||
 | 
					            return NULL;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -277,10 +680,25 @@ gbinder_servicemanager_new_local_object(
 | 
				
			|||||||
    const char* iface,
 | 
					    const char* iface,
 | 
				
			||||||
    GBinderLocalTransactFunc txproc,
 | 
					    GBinderLocalTransactFunc txproc,
 | 
				
			||||||
    void* user_data)
 | 
					    void* user_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const char* ifaces[2];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ifaces[0] = iface;
 | 
				
			||||||
 | 
					    ifaces[1] = NULL;
 | 
				
			||||||
 | 
					    return gbinder_servicemanager_new_local_object2
 | 
				
			||||||
 | 
					        (self, ifaces, txproc, user_data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderLocalObject*
 | 
				
			||||||
 | 
					gbinder_servicemanager_new_local_object2(
 | 
				
			||||||
 | 
					    GBinderServiceManager* self,
 | 
				
			||||||
 | 
					    const char* const* ifaces,
 | 
				
			||||||
 | 
					    GBinderLocalTransactFunc txproc,
 | 
				
			||||||
 | 
					    void* user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (G_LIKELY(self)) {
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
        return gbinder_ipc_new_local_object(gbinder_client_ipc(self->client),
 | 
					        return gbinder_local_object_new(gbinder_client_ipc(self->client),
 | 
				
			||||||
            iface, txproc, user_data);
 | 
					            ifaces, txproc, user_data);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -304,6 +722,65 @@ gbinder_servicemanager_unref(
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char*
 | 
				
			||||||
 | 
					gbinder_servicemanager_device(
 | 
				
			||||||
 | 
					    GBinderServiceManager* self) /* Since 1.1.14 */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return G_LIKELY(self) ? self->dev : NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_servicemanager_is_present(
 | 
				
			||||||
 | 
					    GBinderServiceManager* self) /* Since 1.0.25 */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return G_LIKELY(self) && !self->client->remote->dead;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_servicemanager_wait(
 | 
				
			||||||
 | 
					    GBinderServiceManager* self,
 | 
				
			||||||
 | 
					    long max_wait_ms) /* Since 1.0.25 */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
 | 
					        GBinderRemoteObject* remote = self->client->remote;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!remote->dead) {
 | 
				
			||||||
 | 
					            return TRUE;
 | 
				
			||||||
 | 
					        } else if (gbinder_remote_object_reanimate(remote)) {
 | 
				
			||||||
 | 
					            gbinder_servicemanager_reanimated(self);
 | 
				
			||||||
 | 
					            return TRUE;
 | 
				
			||||||
 | 
					        } else if (max_wait_ms != 0) {
 | 
				
			||||||
 | 
					            /* Zero timeout means a singe check and it's already done */
 | 
				
			||||||
 | 
					            long delay_ms = PRESENSE_WAIT_MS_MIN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            while (max_wait_ms != 0) {
 | 
				
			||||||
 | 
					                if (max_wait_ms > 0) {
 | 
				
			||||||
 | 
					                    if (max_wait_ms < delay_ms) {
 | 
				
			||||||
 | 
					                        delay_ms = max_wait_ms;
 | 
				
			||||||
 | 
					                        max_wait_ms = 0;
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        max_wait_ms -= delay_ms;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                gbinder_servicemanager_sleep_ms(delay_ms);
 | 
				
			||||||
 | 
					                if (gbinder_remote_object_reanimate(remote)) {
 | 
				
			||||||
 | 
					                    gbinder_servicemanager_reanimated(self);
 | 
				
			||||||
 | 
					                    return TRUE;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                if (delay_ms < PRESENSE_WAIT_MS_MAX) {
 | 
				
			||||||
 | 
					                    delay_ms += PRESENSE_WAIT_MS_STEP;
 | 
				
			||||||
 | 
					                    if (delay_ms > PRESENSE_WAIT_MS_MAX) {
 | 
				
			||||||
 | 
					                        delay_ms = PRESENSE_WAIT_MS_MAX;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            /* Timeout */
 | 
				
			||||||
 | 
					            GWARN("Timeout waiting for service manager %s", self->dev);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return FALSE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gulong
 | 
					gulong
 | 
				
			||||||
gbinder_servicemanager_list(
 | 
					gbinder_servicemanager_list(
 | 
				
			||||||
    GBinderServiceManager* self,
 | 
					    GBinderServiceManager* self,
 | 
				
			||||||
@@ -331,7 +808,8 @@ gbinder_servicemanager_list_sync(
 | 
				
			|||||||
    GBinderServiceManager* self)
 | 
					    GBinderServiceManager* self)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (G_LIKELY(self)) {
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
        return GBINDER_SERVICEMANAGER_GET_CLASS(self)->list(self);
 | 
					        return GBINDER_SERVICEMANAGER_GET_CLASS(self)->
 | 
				
			||||||
 | 
					            list(self, &gbinder_ipc_sync_main);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -370,12 +848,17 @@ gbinder_servicemanager_get_service_sync(
 | 
				
			|||||||
    GBinderRemoteObject* obj = NULL;
 | 
					    GBinderRemoteObject* obj = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (G_LIKELY(self) && name) {
 | 
					    if (G_LIKELY(self) && name) {
 | 
				
			||||||
        obj = GBINDER_SERVICEMANAGER_GET_CLASS(self)->get_service
 | 
					        obj = GBINDER_SERVICEMANAGER_GET_CLASS(self)->
 | 
				
			||||||
            (self, name, status);
 | 
					            get_service(self, name, status, &gbinder_ipc_sync_main);
 | 
				
			||||||
        if (!self->pool) {
 | 
					        if (obj) {
 | 
				
			||||||
            self->pool = gutil_idle_pool_new();
 | 
					            GBinderServiceManagerPriv* priv = self->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            priv->autorelease = g_slist_prepend(priv->autorelease, obj);
 | 
				
			||||||
 | 
					            if (!priv->autorelease_cb) {
 | 
				
			||||||
 | 
					                priv->autorelease_cb = gbinder_idle_callback_schedule_new
 | 
				
			||||||
 | 
					                    (gbinder_servicemanager_autorelease_cb, self, NULL);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        gutil_idle_pool_add_object(self->pool, obj);
 | 
					 | 
				
			||||||
    } else if (status) {
 | 
					    } else if (status) {
 | 
				
			||||||
        *status = (-EINVAL);
 | 
					        *status = (-EINVAL);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -416,8 +899,8 @@ gbinder_servicemanager_add_service_sync(
 | 
				
			|||||||
    GBinderLocalObject* obj)
 | 
					    GBinderLocalObject* obj)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (G_LIKELY(self) && name && obj) {
 | 
					    if (G_LIKELY(self) && name && obj) {
 | 
				
			||||||
        return GBINDER_SERVICEMANAGER_GET_CLASS(self)->add_service
 | 
					        return GBINDER_SERVICEMANAGER_GET_CLASS(self)->
 | 
				
			||||||
            (self, name, obj);
 | 
					            add_service(self, name, obj, &gbinder_ipc_sync_main);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        return (-EINVAL);
 | 
					        return (-EINVAL);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -433,6 +916,140 @@ gbinder_servicemanager_cancel(
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gulong
 | 
				
			||||||
 | 
					gbinder_servicemanager_add_presence_handler(
 | 
				
			||||||
 | 
					    GBinderServiceManager* self,
 | 
				
			||||||
 | 
					    GBinderServiceManagerFunc func,
 | 
				
			||||||
 | 
					    void* user_data) /* Since 1.0.25 */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return (G_LIKELY(self) && G_LIKELY(func)) ? g_signal_connect(self,
 | 
				
			||||||
 | 
					        SIGNAL_PRESENCE_NAME, G_CALLBACK(func), user_data) : 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gulong
 | 
				
			||||||
 | 
					gbinder_servicemanager_add_registration_handler(
 | 
				
			||||||
 | 
					    GBinderServiceManager* self,
 | 
				
			||||||
 | 
					    const char* name,
 | 
				
			||||||
 | 
					    GBinderServiceManagerRegistrationFunc func,
 | 
				
			||||||
 | 
					    void* data) /* Since 1.0.13 */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    gulong id = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (G_LIKELY(self) && G_LIKELY(func)) {
 | 
				
			||||||
 | 
					        char* tmp_name = NULL;
 | 
				
			||||||
 | 
					        GBinderServiceManagerClass* klass =
 | 
				
			||||||
 | 
					            GBINDER_SERVICEMANAGER_GET_CLASS(self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        switch (klass->check_name(self, name)) {
 | 
				
			||||||
 | 
					        case GBINDER_SERVICEMANAGER_NAME_OK:
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case GBINDER_SERVICEMANAGER_NAME_NORMALIZE:
 | 
				
			||||||
 | 
					            name = tmp_name = klass->normalize_name(self, name);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            name = NULL;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (name) {
 | 
				
			||||||
 | 
					            GBinderServiceManagerPriv* priv = self->priv;
 | 
				
			||||||
 | 
					            GBinderServiceManagerWatch* watch = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            watch = g_hash_table_lookup(priv->watch_table, name);
 | 
				
			||||||
 | 
					            if (!watch) {
 | 
				
			||||||
 | 
					                watch = gbinder_servicemanager_watch_new(name);
 | 
				
			||||||
 | 
					                g_hash_table_insert(priv->watch_table, watch->name, watch);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (!watch->watched && !self->client->remote->dead) {
 | 
				
			||||||
 | 
					                watch->watched = klass->watch(self, watch->name);
 | 
				
			||||||
 | 
					                if (watch->watched) {
 | 
				
			||||||
 | 
					                    GDEBUG("Watching %s", watch->name);
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    GWARN("Failed to watch %s", watch->name);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            id = g_signal_connect_closure_by_id(self,
 | 
				
			||||||
 | 
					                gbinder_servicemanager_signals[SIGNAL_REGISTRATION],
 | 
				
			||||||
 | 
					                watch->quark, g_cclosure_new(G_CALLBACK(func), data, NULL),
 | 
				
			||||||
 | 
					                FALSE);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        g_free(tmp_name);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return id;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_remove_handler(
 | 
				
			||||||
 | 
					    GBinderServiceManager* self,
 | 
				
			||||||
 | 
					    gulong id) /* Since 1.0.13 */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    gbinder_servicemanager_remove_handlers(self, &id, 1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_remove_handlers(
 | 
				
			||||||
 | 
					    GBinderServiceManager* self,
 | 
				
			||||||
 | 
					    gulong* ids,
 | 
				
			||||||
 | 
					    guint count) /* Since 1.0.25 */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (G_LIKELY(self) && G_LIKELY(ids) && G_LIKELY(count)) {
 | 
				
			||||||
 | 
					        guint i, disconnected = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (i = 0; i < count; i++) {
 | 
				
			||||||
 | 
					            if (ids[i]) {
 | 
				
			||||||
 | 
					                g_signal_handler_disconnect(self, ids[i]);
 | 
				
			||||||
 | 
					                disconnected++;
 | 
				
			||||||
 | 
					                ids[i] = 0;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (disconnected) {
 | 
				
			||||||
 | 
					            GBinderServiceManagerClass* klass =
 | 
				
			||||||
 | 
					                GBINDER_SERVICEMANAGER_GET_CLASS(self);
 | 
				
			||||||
 | 
					            GBinderServiceManagerPriv* priv = self->priv;
 | 
				
			||||||
 | 
					            GHashTableIter it;
 | 
				
			||||||
 | 
					            gpointer value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            g_hash_table_iter_init(&it, priv->watch_table);
 | 
				
			||||||
 | 
					            while (disconnected && g_hash_table_iter_next(&it, NULL, &value)) {
 | 
				
			||||||
 | 
					                GBinderServiceManagerWatch* watch = value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (watch->watched && !g_signal_has_handler_pending(self,
 | 
				
			||||||
 | 
					                    gbinder_servicemanager_signals[SIGNAL_REGISTRATION],
 | 
				
			||||||
 | 
					                    watch->quark, TRUE)) {
 | 
				
			||||||
 | 
					                    /* This must be one of those we have just removed */
 | 
				
			||||||
 | 
					                    GDEBUG("Unwatching %s", watch->name);
 | 
				
			||||||
 | 
					                    watch->watched = FALSE;
 | 
				
			||||||
 | 
					                    klass->unwatch(self, watch->name);
 | 
				
			||||||
 | 
					                    disconnected--;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * These two exist mostly for backward compatibility. Normally,
 | 
				
			||||||
 | 
					 * gbinder_servicemanager_new() should be used, to allow the type of
 | 
				
			||||||
 | 
					 * service manager to be configurable per device via /etc/gbinder.conf
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderServiceManager*
 | 
				
			||||||
 | 
					gbinder_defaultservicemanager_new(
 | 
				
			||||||
 | 
					    const char* dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return gbinder_servicemanager_new_with_type
 | 
				
			||||||
 | 
					        (gbinder_servicemanager_aidl_get_type(), dev, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderServiceManager*
 | 
				
			||||||
 | 
					gbinder_hwservicemanager_new(
 | 
				
			||||||
 | 
					    const char* dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return gbinder_servicemanager_new_with_type
 | 
				
			||||||
 | 
					        (gbinder_servicemanager_hidl_get_type(), dev, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*==========================================================================*
 | 
					/*==========================================================================*
 | 
				
			||||||
 * Internals
 | 
					 * Internals
 | 
				
			||||||
 *==========================================================================*/
 | 
					 *==========================================================================*/
 | 
				
			||||||
@@ -442,6 +1059,12 @@ void
 | 
				
			|||||||
gbinder_servicemanager_init(
 | 
					gbinder_servicemanager_init(
 | 
				
			||||||
    GBinderServiceManager* self)
 | 
					    GBinderServiceManager* self)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServiceManagerPriv* priv = G_TYPE_INSTANCE_GET_PRIVATE(self,
 | 
				
			||||||
 | 
					        GBINDER_TYPE_SERVICEMANAGER, GBinderServiceManagerPriv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    self->priv = priv;
 | 
				
			||||||
 | 
					    priv->watch_table = g_hash_table_new_full(g_str_hash, g_str_equal,
 | 
				
			||||||
 | 
					        NULL, gbinder_servicemanager_watch_free);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
@@ -450,8 +1073,7 @@ gbinder_servicemanager_dispose(
 | 
				
			|||||||
    GObject* object)
 | 
					    GObject* object)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GBinderServiceManager* self = GBINDER_SERVICEMANAGER(object);
 | 
					    GBinderServiceManager* self = GBINDER_SERVICEMANAGER(object);
 | 
				
			||||||
    GBinderServiceManagerClass* klass =
 | 
					    GBinderServiceManagerClass* klass = GBINDER_SERVICEMANAGER_GET_CLASS(self);
 | 
				
			||||||
        GBINDER_SERVICEMANAGER_GET_CLASS(self);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GVERBOSE_("%s", self->dev);
 | 
					    GVERBOSE_("%s", self->dev);
 | 
				
			||||||
    /* Lock */
 | 
					    /* Lock */
 | 
				
			||||||
@@ -475,7 +1097,7 @@ gbinder_servicemanager_dispose(
 | 
				
			|||||||
     * gbinder_servicemanager_finalize() will not be called
 | 
					     * gbinder_servicemanager_finalize() will not be called
 | 
				
			||||||
     * this time around.
 | 
					     * this time around.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    if (klass->table && object->ref_count == 0) {
 | 
					    if (klass->table && g_atomic_int_get(&object->ref_count) <= 1) {
 | 
				
			||||||
        g_hash_table_remove(klass->table, self->dev);
 | 
					        g_hash_table_remove(klass->table, self->dev);
 | 
				
			||||||
        if (g_hash_table_size(klass->table) == 0) {
 | 
					        if (g_hash_table_size(klass->table) == 0) {
 | 
				
			||||||
            g_hash_table_unref(klass->table);
 | 
					            g_hash_table_unref(klass->table);
 | 
				
			||||||
@@ -493,9 +1115,13 @@ gbinder_servicemanager_finalize(
 | 
				
			|||||||
    GObject* object)
 | 
					    GObject* object)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GBinderServiceManager* self = GBINDER_SERVICEMANAGER(object);
 | 
					    GBinderServiceManager* self = GBINDER_SERVICEMANAGER(object);
 | 
				
			||||||
 | 
					    GBinderServiceManagerPriv* priv = self->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    gutil_idle_pool_drain(self->pool);
 | 
					    gbinder_timeout_remove(priv->presence_check);
 | 
				
			||||||
    gutil_idle_pool_unref(self->pool);
 | 
					    gbinder_remote_object_remove_handler(self->client->remote, priv->death_id);
 | 
				
			||||||
 | 
					    gbinder_idle_callback_destroy(priv->autorelease_cb);
 | 
				
			||||||
 | 
					    g_slist_free_full(priv->autorelease, g_object_unref);
 | 
				
			||||||
 | 
					    g_hash_table_destroy(priv->watch_table);
 | 
				
			||||||
    gbinder_client_unref(self->client);
 | 
					    gbinder_client_unref(self->client);
 | 
				
			||||||
    G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
 | 
					    G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -506,10 +1132,20 @@ gbinder_servicemanager_class_init(
 | 
				
			|||||||
    GBinderServiceManagerClass* klass)
 | 
					    GBinderServiceManagerClass* klass)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GObjectClass* object_class = G_OBJECT_CLASS(klass);
 | 
					    GObjectClass* object_class = G_OBJECT_CLASS(klass);
 | 
				
			||||||
 | 
					    GType type = G_OBJECT_CLASS_TYPE(klass);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    g_mutex_init(&klass->mutex);
 | 
					    g_mutex_init(&klass->mutex);
 | 
				
			||||||
 | 
					    g_type_class_add_private(klass, sizeof(GBinderServiceManagerPriv));
 | 
				
			||||||
    object_class->dispose = gbinder_servicemanager_dispose;
 | 
					    object_class->dispose = gbinder_servicemanager_dispose;
 | 
				
			||||||
    object_class->finalize = gbinder_servicemanager_finalize;
 | 
					    object_class->finalize = gbinder_servicemanager_finalize;
 | 
				
			||||||
 | 
					    gbinder_servicemanager_signals[SIGNAL_PRESENCE] =
 | 
				
			||||||
 | 
					        g_signal_new(SIGNAL_PRESENCE_NAME, type,
 | 
				
			||||||
 | 
					            G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL,
 | 
				
			||||||
 | 
					            G_TYPE_NONE, 0);
 | 
				
			||||||
 | 
					    gbinder_servicemanager_signals[SIGNAL_REGISTRATION] =
 | 
				
			||||||
 | 
					        g_signal_new(SIGNAL_REGISTRATION_NAME, type,
 | 
				
			||||||
 | 
					            G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED, 0, NULL, NULL, NULL,
 | 
				
			||||||
 | 
					            G_TYPE_NONE, 1, G_TYPE_STRING);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										331
									
								
								src/gbinder_servicemanager_aidl.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										331
									
								
								src/gbinder_servicemanager_aidl.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,331 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
				
			||||||
 | 
					 * Copyright (C) 2018-2023 Slava Monich <slava@monich.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   1. Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 | 
					 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
				
			||||||
 | 
					 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
				
			||||||
 | 
					 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
				
			||||||
 | 
					 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
				
			||||||
 | 
					 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
				
			||||||
 | 
					 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
				
			||||||
 | 
					 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
				
			||||||
 | 
					 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
				
			||||||
 | 
					 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "gbinder_servicemanager_aidl.h"
 | 
				
			||||||
 | 
					#include "gbinder_servicepoll.h"
 | 
				
			||||||
 | 
					#include "gbinder_eventloop_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_client_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gbinder_local_request.h>
 | 
				
			||||||
 | 
					#include <gbinder_remote_reply.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_servicemanager_aidl_watch {
 | 
				
			||||||
 | 
					    GBinderServicePoll* poll;
 | 
				
			||||||
 | 
					    char* name;
 | 
				
			||||||
 | 
					    gulong handler_id;
 | 
				
			||||||
 | 
					    GBinderEventLoopTimeout* notify;
 | 
				
			||||||
 | 
					} GBinderServiceManagerAidlWatch;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gbinder_servicemanager_aidl_priv {
 | 
				
			||||||
 | 
					    GBinderServicePoll* poll;
 | 
				
			||||||
 | 
					    GHashTable* watch_table;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					G_DEFINE_TYPE(GBinderServiceManagerAidl,
 | 
				
			||||||
 | 
					    gbinder_servicemanager_aidl,
 | 
				
			||||||
 | 
					    GBINDER_TYPE_SERVICEMANAGER)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PARENT_CLASS gbinder_servicemanager_aidl_parent_class
 | 
				
			||||||
 | 
					#define GBINDER_SERVICEMANAGER_AIDL(obj) \
 | 
				
			||||||
 | 
					    G_TYPE_CHECK_INSTANCE_CAST((obj), GBINDER_TYPE_SERVICEMANAGER_AIDL, \
 | 
				
			||||||
 | 
					    GBinderServiceManagerAidl)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SERVICEMANAGER_AIDL_IFACE  "android.os.IServiceManager"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_aidl_watch_proc(
 | 
				
			||||||
 | 
					    GBinderServicePoll* poll,
 | 
				
			||||||
 | 
					    const char* name_added,
 | 
				
			||||||
 | 
					    void* user_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServiceManagerAidlWatch* watch = user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!g_strcmp0(name_added, watch->name)) {
 | 
				
			||||||
 | 
					        GBinderServiceManager* manager =
 | 
				
			||||||
 | 
					            gbinder_servicepoll_manager(watch->poll);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (watch->notify) {
 | 
				
			||||||
 | 
					            gbinder_timeout_remove(watch->notify);
 | 
				
			||||||
 | 
					            watch->notify = NULL;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        gbinder_servicemanager_service_registered(manager, name_added);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_servicemanager_aidl_watch_notify(
 | 
				
			||||||
 | 
					    gpointer user_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServiceManagerAidlWatch* watch = user_data;
 | 
				
			||||||
 | 
					    GBinderServiceManager* manager = gbinder_servicepoll_manager(watch->poll);
 | 
				
			||||||
 | 
					    char* name = g_strdup(watch->name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    GASSERT(watch->notify);
 | 
				
			||||||
 | 
					    watch->notify = NULL;
 | 
				
			||||||
 | 
					    gbinder_servicemanager_service_registered(manager, name);
 | 
				
			||||||
 | 
					    g_free(name);
 | 
				
			||||||
 | 
					    return G_SOURCE_REMOVE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_aidl_watch_free(
 | 
				
			||||||
 | 
					    gpointer user_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServiceManagerAidlWatch* watch = user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gbinder_timeout_remove(watch->notify);
 | 
				
			||||||
 | 
					    gbinder_servicepoll_remove_handler(watch->poll, watch->handler_id);
 | 
				
			||||||
 | 
					    gbinder_servicepoll_unref(watch->poll);
 | 
				
			||||||
 | 
					    g_free(watch->name);
 | 
				
			||||||
 | 
					    g_slice_free(GBinderServiceManagerAidlWatch, watch);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					GBinderServiceManagerAidlWatch*
 | 
				
			||||||
 | 
					gbinder_servicemanager_aidl_watch_new(
 | 
				
			||||||
 | 
					    GBinderServiceManagerAidl* self,
 | 
				
			||||||
 | 
					    const char* name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServiceManagerAidlPriv* priv = self->priv;
 | 
				
			||||||
 | 
					    GBinderServiceManagerAidlWatch* watch =
 | 
				
			||||||
 | 
					        g_slice_new0(GBinderServiceManagerAidlWatch);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    watch->name = g_strdup(name);
 | 
				
			||||||
 | 
					    watch->poll = gbinder_servicepoll_new(&self->manager, &priv->poll);
 | 
				
			||||||
 | 
					    watch->handler_id = gbinder_servicepoll_add_handler(priv->poll,
 | 
				
			||||||
 | 
					        gbinder_servicemanager_aidl_watch_proc, watch);
 | 
				
			||||||
 | 
					    return watch;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					GBinderLocalRequest*
 | 
				
			||||||
 | 
					gbinder_servicemanager_aidl_list_services_req(
 | 
				
			||||||
 | 
					    GBinderClient* client,
 | 
				
			||||||
 | 
					    gint32 index)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderLocalRequest* req = gbinder_client_new_request(client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gbinder_local_request_append_int32(req, index);
 | 
				
			||||||
 | 
					    return req;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					GBinderLocalRequest*
 | 
				
			||||||
 | 
					gbinder_servicemanager_aidl_add_service_req(
 | 
				
			||||||
 | 
					    GBinderClient* client,
 | 
				
			||||||
 | 
					    const char* name,
 | 
				
			||||||
 | 
					    GBinderLocalObject* obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderLocalRequest* req = gbinder_client_new_request(client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gbinder_local_request_append_string16(req, name);
 | 
				
			||||||
 | 
					    gbinder_local_request_append_local_object(req, obj);
 | 
				
			||||||
 | 
					    gbinder_local_request_append_int32(req, 0);
 | 
				
			||||||
 | 
					    return req;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					char**
 | 
				
			||||||
 | 
					gbinder_servicemanager_aidl_list(
 | 
				
			||||||
 | 
					    GBinderServiceManager* manager,
 | 
				
			||||||
 | 
					    const GBinderIpcSyncApi* api)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GPtrArray* list = g_ptr_array_new();
 | 
				
			||||||
 | 
					    GBinderClient* client = manager->client;
 | 
				
			||||||
 | 
					    GBinderServiceManagerAidlClass* klass =
 | 
				
			||||||
 | 
					        GBINDER_SERVICEMANAGER_AIDL_GET_CLASS(manager);
 | 
				
			||||||
 | 
					    GBinderLocalRequest* req = klass->list_services_req(client, 0);
 | 
				
			||||||
 | 
					    GBinderRemoteReply* reply;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while ((reply = gbinder_client_transact_sync_reply2(client,
 | 
				
			||||||
 | 
					        LIST_SERVICES_TRANSACTION, req, NULL, api)) != NULL) {
 | 
				
			||||||
 | 
					        char* service = gbinder_remote_reply_read_string16(reply);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gbinder_remote_reply_unref(reply);
 | 
				
			||||||
 | 
					        if (service) {
 | 
				
			||||||
 | 
					            g_ptr_array_add(list, service);
 | 
				
			||||||
 | 
					            gbinder_local_request_unref(req);
 | 
				
			||||||
 | 
					            req = klass->list_services_req(client, list->len);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gbinder_local_request_unref(req);
 | 
				
			||||||
 | 
					    g_ptr_array_add(list, NULL);
 | 
				
			||||||
 | 
					    return (char**)g_ptr_array_free(list, FALSE);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					GBinderRemoteObject*
 | 
				
			||||||
 | 
					gbinder_servicemanager_aidl_get_service(
 | 
				
			||||||
 | 
					    GBinderServiceManager* self,
 | 
				
			||||||
 | 
					    const char* name,
 | 
				
			||||||
 | 
					    int* status,
 | 
				
			||||||
 | 
					    const GBinderIpcSyncApi* api)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderRemoteObject* obj;
 | 
				
			||||||
 | 
					    GBinderRemoteReply* reply;
 | 
				
			||||||
 | 
					    GBinderLocalRequest* req = gbinder_client_new_request(self->client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gbinder_local_request_append_string16(req, name);
 | 
				
			||||||
 | 
					    reply = gbinder_client_transact_sync_reply2(self->client,
 | 
				
			||||||
 | 
					        CHECK_SERVICE_TRANSACTION, req, status, api);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    obj = gbinder_remote_reply_read_object(reply);
 | 
				
			||||||
 | 
					    gbinder_remote_reply_unref(reply);
 | 
				
			||||||
 | 
					    gbinder_local_request_unref(req);
 | 
				
			||||||
 | 
					    return obj;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					gbinder_servicemanager_aidl_add_service(
 | 
				
			||||||
 | 
					    GBinderServiceManager* manager,
 | 
				
			||||||
 | 
					    const char* name,
 | 
				
			||||||
 | 
					    GBinderLocalObject* obj,
 | 
				
			||||||
 | 
					    const GBinderIpcSyncApi* api)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int status;
 | 
				
			||||||
 | 
					    GBinderClient* client = manager->client;
 | 
				
			||||||
 | 
					    GBinderLocalRequest* req = GBINDER_SERVICEMANAGER_AIDL_GET_CLASS
 | 
				
			||||||
 | 
					        (manager)->add_service_req(client, name, obj);
 | 
				
			||||||
 | 
					    GBinderRemoteReply* reply = gbinder_client_transact_sync_reply2(client,
 | 
				
			||||||
 | 
					        ADD_SERVICE_TRANSACTION, req, &status, api);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gbinder_remote_reply_unref(reply);
 | 
				
			||||||
 | 
					    gbinder_local_request_unref(req);
 | 
				
			||||||
 | 
					    return status;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					GBINDER_SERVICEMANAGER_NAME_CHECK
 | 
				
			||||||
 | 
					gbinder_servicemanager_aidl_check_name(
 | 
				
			||||||
 | 
					    GBinderServiceManager* self,
 | 
				
			||||||
 | 
					    const char* name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return GBINDER_SERVICEMANAGER_NAME_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_servicemanager_aidl_watch(
 | 
				
			||||||
 | 
					    GBinderServiceManager* manager,
 | 
				
			||||||
 | 
					    const char* name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServiceManagerAidl* self = GBINDER_SERVICEMANAGER_AIDL(manager);
 | 
				
			||||||
 | 
					    GBinderServiceManagerAidlPriv* priv = self->priv;
 | 
				
			||||||
 | 
					    GBinderServiceManagerAidlWatch* watch =
 | 
				
			||||||
 | 
					        gbinder_servicemanager_aidl_watch_new(self, name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_hash_table_replace(priv->watch_table, watch->name, watch);
 | 
				
			||||||
 | 
					    if (gbinder_servicepoll_is_known_name(watch->poll, name)) {
 | 
				
			||||||
 | 
					        watch->notify = gbinder_idle_add
 | 
				
			||||||
 | 
					            (gbinder_servicemanager_aidl_watch_notify, watch);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return TRUE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_aidl_unwatch(
 | 
				
			||||||
 | 
					    GBinderServiceManager* manager,
 | 
				
			||||||
 | 
					    const char* name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServiceManagerAidl* self = GBINDER_SERVICEMANAGER_AIDL(manager);
 | 
				
			||||||
 | 
					    GBinderServiceManagerAidlPriv* priv = self->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_hash_table_remove(priv->watch_table, name);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_aidl_init(
 | 
				
			||||||
 | 
					    GBinderServiceManagerAidl* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServiceManagerAidlPriv* priv = G_TYPE_INSTANCE_GET_PRIVATE(self,
 | 
				
			||||||
 | 
					        GBINDER_TYPE_SERVICEMANAGER_AIDL, GBinderServiceManagerAidlPriv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    self->priv = priv;
 | 
				
			||||||
 | 
					    priv->watch_table = g_hash_table_new_full(g_str_hash, g_str_equal,
 | 
				
			||||||
 | 
					        NULL, gbinder_servicemanager_aidl_watch_free);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_aidl_finalize(
 | 
				
			||||||
 | 
					    GObject* object)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServiceManagerAidl* self = GBINDER_SERVICEMANAGER_AIDL(object);
 | 
				
			||||||
 | 
					    GBinderServiceManagerAidlPriv* priv = self->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_hash_table_destroy(priv->watch_table);
 | 
				
			||||||
 | 
					    G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_aidl_class_init(
 | 
				
			||||||
 | 
					    GBinderServiceManagerAidlClass* klass)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServiceManagerClass* manager = GBINDER_SERVICEMANAGER_CLASS(klass);
 | 
				
			||||||
 | 
					    GObjectClass* object = G_OBJECT_CLASS(klass);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_type_class_add_private(klass, sizeof(GBinderServiceManagerAidlPriv));
 | 
				
			||||||
 | 
					    klass->list_services_req = gbinder_servicemanager_aidl_list_services_req;
 | 
				
			||||||
 | 
					    klass->add_service_req = gbinder_servicemanager_aidl_add_service_req;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    manager->iface = SERVICEMANAGER_AIDL_IFACE;
 | 
				
			||||||
 | 
					    manager->default_device = GBINDER_DEFAULT_BINDER;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    manager->list = gbinder_servicemanager_aidl_list;
 | 
				
			||||||
 | 
					    manager->get_service = gbinder_servicemanager_aidl_get_service;
 | 
				
			||||||
 | 
					    manager->add_service = gbinder_servicemanager_aidl_add_service;
 | 
				
			||||||
 | 
					    manager->check_name = gbinder_servicemanager_aidl_check_name;
 | 
				
			||||||
 | 
					    /* normalize_name is not needed */
 | 
				
			||||||
 | 
					    manager->watch = gbinder_servicemanager_aidl_watch;
 | 
				
			||||||
 | 
					    manager->unwatch = gbinder_servicemanager_aidl_unwatch;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    object->finalize = gbinder_servicemanager_aidl_finalize;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Local Variables:
 | 
				
			||||||
 | 
					 * mode: C
 | 
				
			||||||
 | 
					 * c-basic-offset: 4
 | 
				
			||||||
 | 
					 * indent-tabs-mode: nil
 | 
				
			||||||
 | 
					 * End:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
							
								
								
									
										77
									
								
								src/gbinder_servicemanager_aidl.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/gbinder_servicemanager_aidl.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,77 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2020-2022 Jolla Ltd.
 | 
				
			||||||
 | 
					 * Copyright (C) 2020-2022 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   1. Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 | 
					 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
				
			||||||
 | 
					 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
				
			||||||
 | 
					 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
				
			||||||
 | 
					 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
				
			||||||
 | 
					 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
				
			||||||
 | 
					 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
				
			||||||
 | 
					 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
				
			||||||
 | 
					 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
				
			||||||
 | 
					 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GBINDER_SERVICEMANAGER_AIDL_H
 | 
				
			||||||
 | 
					#define GBINDER_SERVICEMANAGER_AIDL_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "gbinder_servicemanager_p.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_servicemanager_aidl_priv GBinderServiceManagerAidlPriv;
 | 
				
			||||||
 | 
					typedef struct gbinder_servicemanager_aidl {
 | 
				
			||||||
 | 
					    GBinderServiceManager manager;
 | 
				
			||||||
 | 
					    GBinderServiceManagerAidlPriv* priv;
 | 
				
			||||||
 | 
					} GBinderServiceManagerAidl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_servicemanager_aidl_class {
 | 
				
			||||||
 | 
					    GBinderServiceManagerClass parent;
 | 
				
			||||||
 | 
					    GBinderLocalRequest* (*list_services_req)
 | 
				
			||||||
 | 
					        (GBinderClient* client, gint32 index);
 | 
				
			||||||
 | 
					    GBinderLocalRequest* (*add_service_req)
 | 
				
			||||||
 | 
					        (GBinderClient* client, const char* name, GBinderLocalObject* obj);
 | 
				
			||||||
 | 
					} GBinderServiceManagerAidlClass;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define GBINDER_TYPE_SERVICEMANAGER_AIDL \
 | 
				
			||||||
 | 
					    gbinder_servicemanager_aidl_get_type()
 | 
				
			||||||
 | 
					#define GBINDER_SERVICEMANAGER_AIDL_GET_CLASS(obj) \
 | 
				
			||||||
 | 
					    G_TYPE_INSTANCE_GET_CLASS((obj), GBINDER_TYPE_SERVICEMANAGER_AIDL, \
 | 
				
			||||||
 | 
					    GBinderServiceManagerAidlClass)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum gbinder_servicemanager_aidl_calls {
 | 
				
			||||||
 | 
					    GET_SERVICE_TRANSACTION = GBINDER_FIRST_CALL_TRANSACTION,
 | 
				
			||||||
 | 
					    CHECK_SERVICE_TRANSACTION,
 | 
				
			||||||
 | 
					    ADD_SERVICE_TRANSACTION,
 | 
				
			||||||
 | 
					    LIST_SERVICES_TRANSACTION
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DUMP_FLAG_PRIORITY_DEFAULT (0x08)
 | 
				
			||||||
 | 
					#define DUMP_FLAG_PRIORITY_ALL     (0x0f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* GBINDER_SERVICEMANAGER_AIDL_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Local Variables:
 | 
				
			||||||
 | 
					 * mode: C
 | 
				
			||||||
 | 
					 * c-basic-offset: 4
 | 
				
			||||||
 | 
					 * indent-tabs-mode: nil
 | 
				
			||||||
 | 
					 * End:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										100
									
								
								src/gbinder_servicemanager_aidl2.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								src/gbinder_servicemanager_aidl2.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,100 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2020 Jolla Ltd.
 | 
				
			||||||
 | 
					 * Copyright (C) 2020 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   1. Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 | 
					 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
				
			||||||
 | 
					 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
				
			||||||
 | 
					 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
				
			||||||
 | 
					 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
				
			||||||
 | 
					 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
				
			||||||
 | 
					 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
				
			||||||
 | 
					 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
				
			||||||
 | 
					 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
				
			||||||
 | 
					 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "gbinder_servicemanager_aidl.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gbinder_client.h>
 | 
				
			||||||
 | 
					#include <gbinder_local_request.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Variant of AIDL servicemanager appeared in Android 9 (API level 28) */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef GBinderServiceManagerAidl GBinderServiceManagerAidl2;
 | 
				
			||||||
 | 
					typedef GBinderServiceManagerAidlClass GBinderServiceManagerAidl2Class;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					G_DEFINE_TYPE(GBinderServiceManagerAidl2,
 | 
				
			||||||
 | 
					    gbinder_servicemanager_aidl2,
 | 
				
			||||||
 | 
					    GBINDER_TYPE_SERVICEMANAGER_AIDL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PARENT_CLASS gbinder_servicemanager_aidl2_parent_class
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					GBinderLocalRequest*
 | 
				
			||||||
 | 
					gbinder_servicemanager_aidl2_list_services_req(
 | 
				
			||||||
 | 
					    GBinderClient* client,
 | 
				
			||||||
 | 
					    gint32 index)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderLocalRequest* req = gbinder_client_new_request(client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gbinder_local_request_append_int32(req, index);
 | 
				
			||||||
 | 
					    gbinder_local_request_append_int32(req, DUMP_FLAG_PRIORITY_ALL);
 | 
				
			||||||
 | 
					    return req;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					GBinderLocalRequest*
 | 
				
			||||||
 | 
					gbinder_servicemanager_aidl2_add_service_req(
 | 
				
			||||||
 | 
					    GBinderClient* client,
 | 
				
			||||||
 | 
					    const char* name,
 | 
				
			||||||
 | 
					    GBinderLocalObject* obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderLocalRequest* req = gbinder_client_new_request(client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gbinder_local_request_append_string16(req, name);
 | 
				
			||||||
 | 
					    gbinder_local_request_append_local_object(req, obj);
 | 
				
			||||||
 | 
					    gbinder_local_request_append_int32(req, 0);
 | 
				
			||||||
 | 
					    gbinder_local_request_append_int32(req, DUMP_FLAG_PRIORITY_DEFAULT);
 | 
				
			||||||
 | 
					    return req;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_aidl2_init(
 | 
				
			||||||
 | 
					    GBinderServiceManagerAidl* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_aidl2_class_init(
 | 
				
			||||||
 | 
					    GBinderServiceManagerAidl2Class* cls)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    cls->list_services_req = gbinder_servicemanager_aidl2_list_services_req;
 | 
				
			||||||
 | 
					    cls->add_service_req = gbinder_servicemanager_aidl2_add_service_req;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Local Variables:
 | 
				
			||||||
 | 
					 * mode: C
 | 
				
			||||||
 | 
					 * c-basic-offset: 4
 | 
				
			||||||
 | 
					 * indent-tabs-mode: nil
 | 
				
			||||||
 | 
					 * End:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
							
								
								
									
										162
									
								
								src/gbinder_servicemanager_aidl3.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								src/gbinder_servicemanager_aidl3.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,162 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2021-2022 Jolla Ltd.
 | 
				
			||||||
 | 
					 * Copyright (C) 2021-2022 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 | 
					 * Copyright (C) 2021 Gary Wang <gary.wang@canonical.com>
 | 
				
			||||||
 | 
					 * Copyright (C) 2021 Madhushan Nishantha <jlmadushan@gmail.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   1. Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 | 
					 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
				
			||||||
 | 
					 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
				
			||||||
 | 
					 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
				
			||||||
 | 
					 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
				
			||||||
 | 
					 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
				
			||||||
 | 
					 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
				
			||||||
 | 
					 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
				
			||||||
 | 
					 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
				
			||||||
 | 
					 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "gbinder_servicemanager_aidl_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_client_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_reader_p.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gbinder_local_request.h>
 | 
				
			||||||
 | 
					#include <gbinder_remote_reply.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Variant of AIDL servicemanager appeared in Android 11 (API level 30) */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef GBinderServiceManagerAidl GBinderServiceManagerAidl3;
 | 
				
			||||||
 | 
					typedef GBinderServiceManagerAidlClass GBinderServiceManagerAidl3Class;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					G_DEFINE_TYPE(GBinderServiceManagerAidl3,
 | 
				
			||||||
 | 
					    gbinder_servicemanager_aidl3,
 | 
				
			||||||
 | 
					    GBINDER_TYPE_SERVICEMANAGER_AIDL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PARENT_CLASS gbinder_servicemanager_aidl3_parent_class
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderRemoteObject*
 | 
				
			||||||
 | 
					gbinder_servicemanager_aidl3_get_service(
 | 
				
			||||||
 | 
					    GBinderServiceManager* self,
 | 
				
			||||||
 | 
					    const char* name,
 | 
				
			||||||
 | 
					    int* status,
 | 
				
			||||||
 | 
					    const GBinderIpcSyncApi* api)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderClient* client = self->client;
 | 
				
			||||||
 | 
					    GBinderLocalRequest* req = gbinder_client_new_request(client);
 | 
				
			||||||
 | 
					    GBinderRemoteObject* obj;
 | 
				
			||||||
 | 
					    GBinderRemoteReply* reply;
 | 
				
			||||||
 | 
					    GBinderReader reader;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gbinder_local_request_append_string16(req, name);
 | 
				
			||||||
 | 
					    reply = gbinder_client_transact_sync_reply2(client,
 | 
				
			||||||
 | 
					        CHECK_SERVICE_TRANSACTION, req, status, api);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gbinder_remote_reply_init_reader(reply, &reader);
 | 
				
			||||||
 | 
					    gbinder_reader_read_int32(&reader, NULL /* status? */);
 | 
				
			||||||
 | 
					    obj = gbinder_reader_read_object(&reader);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gbinder_remote_reply_unref(reply);
 | 
				
			||||||
 | 
					    gbinder_local_request_unref(req);
 | 
				
			||||||
 | 
					    return obj;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char**
 | 
				
			||||||
 | 
					gbinder_servicemanager_aidl3_list(
 | 
				
			||||||
 | 
					    GBinderServiceManager* manager,
 | 
				
			||||||
 | 
					    const GBinderIpcSyncApi* api)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GPtrArray* list = g_ptr_array_new();
 | 
				
			||||||
 | 
					    GBinderClient* client = manager->client;
 | 
				
			||||||
 | 
					    GBinderRemoteReply* reply;
 | 
				
			||||||
 | 
					    GBinderLocalRequest* req = gbinder_client_new_request(client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * Starting from Android 11, no `index` field is required but
 | 
				
			||||||
 | 
					     * only with `dump priority` field to request to list services.
 | 
				
			||||||
 | 
					     * As a result, a vector of strings which stands for service
 | 
				
			||||||
 | 
					     * list is given in the binder response.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    gbinder_local_request_append_int32(req, DUMP_FLAG_PRIORITY_ALL);
 | 
				
			||||||
 | 
					    reply = gbinder_client_transact_sync_reply2(client,
 | 
				
			||||||
 | 
					        LIST_SERVICES_TRANSACTION, req, NULL, api);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (reply) {
 | 
				
			||||||
 | 
					        GBinderReader reader;
 | 
				
			||||||
 | 
					        gint32 count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gbinder_remote_reply_init_reader(reply, &reader);
 | 
				
			||||||
 | 
					        gbinder_reader_read_int32(&reader, NULL /* status */);
 | 
				
			||||||
 | 
					        if (gbinder_reader_read_int32(&reader, &count)) {
 | 
				
			||||||
 | 
					            int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* Iterate each service name */
 | 
				
			||||||
 | 
					            for (i = 0; i < count; i++) {
 | 
				
			||||||
 | 
					                g_ptr_array_add(list, gbinder_reader_read_string16(&reader));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        gbinder_remote_reply_unref(reply);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gbinder_local_request_unref(req);
 | 
				
			||||||
 | 
					    g_ptr_array_add(list, NULL);
 | 
				
			||||||
 | 
					    return (char**)g_ptr_array_free(list, FALSE);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					GBinderLocalRequest*
 | 
				
			||||||
 | 
					gbinder_servicemanager_aidl3_add_service_req(
 | 
				
			||||||
 | 
					    GBinderClient* client,
 | 
				
			||||||
 | 
					    const char* name,
 | 
				
			||||||
 | 
					    GBinderLocalObject* obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderLocalRequest* req = gbinder_client_new_request(client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gbinder_local_request_append_string16(req, name);
 | 
				
			||||||
 | 
					    gbinder_local_request_append_local_object(req, obj);
 | 
				
			||||||
 | 
					    gbinder_local_request_append_int32(req, 0);
 | 
				
			||||||
 | 
					    gbinder_local_request_append_int32(req, DUMP_FLAG_PRIORITY_DEFAULT);
 | 
				
			||||||
 | 
					    return req;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_aidl3_init(
 | 
				
			||||||
 | 
					    GBinderServiceManagerAidl3* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_aidl3_class_init(
 | 
				
			||||||
 | 
					    GBinderServiceManagerAidl3Class* klass)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServiceManagerClass* manager = GBINDER_SERVICEMANAGER_CLASS(klass);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    klass->add_service_req = gbinder_servicemanager_aidl3_add_service_req;
 | 
				
			||||||
 | 
					    manager->list = gbinder_servicemanager_aidl3_list;
 | 
				
			||||||
 | 
					    manager->get_service = gbinder_servicemanager_aidl3_get_service;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Local Variables:
 | 
				
			||||||
 | 
					 * mode: C
 | 
				
			||||||
 | 
					 * c-basic-offset: 4
 | 
				
			||||||
 | 
					 * indent-tabs-mode: nil
 | 
				
			||||||
 | 
					 * End:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
							
								
								
									
										115
									
								
								src/gbinder_servicemanager_aidl4.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								src/gbinder_servicemanager_aidl4.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,115 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2020-2022 Jolla Ltd.
 | 
				
			||||||
 | 
					 * Copyright (C) 2020-2022 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 | 
					 * Copyright (C) 2021 Gary Wang <gary.wang@canonical.com>
 | 
				
			||||||
 | 
					 * Copyright (C) 2021 Madhushan Nishantha <jlmadushan@gmail.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   1. Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 | 
					 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
				
			||||||
 | 
					 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
				
			||||||
 | 
					 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
				
			||||||
 | 
					 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
				
			||||||
 | 
					 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
				
			||||||
 | 
					 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
				
			||||||
 | 
					 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
				
			||||||
 | 
					 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
				
			||||||
 | 
					 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "gbinder_servicemanager_aidl_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_client_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_reader_p.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gbinder_local_request.h>
 | 
				
			||||||
 | 
					#include <gbinder_remote_reply.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Variant of AIDL servicemanager appeared in Android 12 (API level 31) */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef GBinderServiceManagerAidl GBinderServiceManagerAidl4;
 | 
				
			||||||
 | 
					typedef GBinderServiceManagerAidlClass GBinderServiceManagerAidl4Class;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					G_DEFINE_TYPE(GBinderServiceManagerAidl4,
 | 
				
			||||||
 | 
					    gbinder_servicemanager_aidl4,
 | 
				
			||||||
 | 
					    GBINDER_TYPE_SERVICEMANAGER_AIDL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PARENT_CLASS gbinder_servicemanager_aidl4_parent_class
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define BINDER_WIRE_FORMAT_VERSION (1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					GBinderLocalRequest*
 | 
				
			||||||
 | 
					gbinder_servicemanager_aidl4_add_service_req(
 | 
				
			||||||
 | 
					    GBinderClient* client,
 | 
				
			||||||
 | 
					    const char* name,
 | 
				
			||||||
 | 
					    GBinderLocalObject* obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderLocalRequest* req = gbinder_client_new_request(client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gbinder_local_request_append_string16(req, name);
 | 
				
			||||||
 | 
					    gbinder_local_request_append_local_object(req, obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * When reading nullable strong binder, from Android 12, the format of
 | 
				
			||||||
 | 
					     * the `stability` field passed on the wire was changed and evolved to
 | 
				
			||||||
 | 
					     * `struct Category`, which consists of the following members with 4 bytes
 | 
				
			||||||
 | 
					     * long.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * struct Category {
 | 
				
			||||||
 | 
					     *   uint8_t version;
 | 
				
			||||||
 | 
					     *   uint8_t reserved[2];
 | 
				
			||||||
 | 
					     *   Level level;        <- bitmask of Stability::Level
 | 
				
			||||||
 | 
					     * }
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * Hmmm, is that ^ really true?
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    gbinder_local_request_append_int32(req,
 | 
				
			||||||
 | 
					        GBINDER_FOURCC(GBINDER_STABILITY_SYSTEM, 0, 0,
 | 
				
			||||||
 | 
					            BINDER_WIRE_FORMAT_VERSION));
 | 
				
			||||||
 | 
					    gbinder_local_request_append_int32(req, 0);
 | 
				
			||||||
 | 
					    gbinder_local_request_append_int32(req, DUMP_FLAG_PRIORITY_DEFAULT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return req;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_aidl4_init(
 | 
				
			||||||
 | 
					    GBinderServiceManagerAidl* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_aidl4_class_init(
 | 
				
			||||||
 | 
					    GBinderServiceManagerAidl4Class* cls)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServiceManagerClass* manager = GBINDER_SERVICEMANAGER_CLASS(cls);
 | 
				
			||||||
 | 
					    cls->add_service_req = gbinder_servicemanager_aidl4_add_service_req;
 | 
				
			||||||
 | 
					    manager->list = gbinder_servicemanager_aidl3_list;
 | 
				
			||||||
 | 
					    manager->get_service = gbinder_servicemanager_aidl3_get_service;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Local Variables:
 | 
				
			||||||
 | 
					 * mode: C
 | 
				
			||||||
 | 
					 * c-basic-offset: 4
 | 
				
			||||||
 | 
					 * indent-tabs-mode: nil
 | 
				
			||||||
 | 
					 * End:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										61
									
								
								src/gbinder_servicemanager_aidl_p.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/gbinder_servicemanager_aidl_p.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
				
			||||||
 | 
					 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 | 
					 * Copyright (C) 2021 Gary Wang <gary.wang@canonical.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   1. Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 | 
					 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
				
			||||||
 | 
					 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
				
			||||||
 | 
					 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
				
			||||||
 | 
					 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
				
			||||||
 | 
					 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
				
			||||||
 | 
					 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
				
			||||||
 | 
					 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
				
			||||||
 | 
					 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
				
			||||||
 | 
					 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GBINDER_SERVICEMANAGER_AIDL_PRIVATE_H
 | 
				
			||||||
 | 
					#define GBINDER_SERVICEMANAGER_AIDL_PRIVATE_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "gbinder_servicemanager_aidl.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char**
 | 
				
			||||||
 | 
					gbinder_servicemanager_aidl3_list(
 | 
				
			||||||
 | 
					    GBinderServiceManager* manager,
 | 
				
			||||||
 | 
					    const GBinderIpcSyncApi* api)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderRemoteObject*
 | 
				
			||||||
 | 
					gbinder_servicemanager_aidl3_get_service(
 | 
				
			||||||
 | 
					    GBinderServiceManager* manager,
 | 
				
			||||||
 | 
					    const char* name,
 | 
				
			||||||
 | 
					    int* status,
 | 
				
			||||||
 | 
					    const GBinderIpcSyncApi* api)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* GBINDER_SERVICEMANAGER_AIDL_PRIVATE_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Local Variables:
 | 
				
			||||||
 | 
					 * mode: C
 | 
				
			||||||
 | 
					 * c-basic-offset: 4
 | 
				
			||||||
 | 
					 * indent-tabs-mode: nil
 | 
				
			||||||
 | 
					 * End:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
							
								
								
									
										393
									
								
								src/gbinder_servicemanager_hidl.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										393
									
								
								src/gbinder_servicemanager_hidl.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,393 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
				
			||||||
 | 
					 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   1. Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 | 
					 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
				
			||||||
 | 
					 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
				
			||||||
 | 
					 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
				
			||||||
 | 
					 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
				
			||||||
 | 
					 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
				
			||||||
 | 
					 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
				
			||||||
 | 
					 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
				
			||||||
 | 
					 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
				
			||||||
 | 
					 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "gbinder_servicemanager_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_client_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gbinder_local_object.h>
 | 
				
			||||||
 | 
					#include <gbinder_local_request.h>
 | 
				
			||||||
 | 
					#include <gbinder_remote_reply.h>
 | 
				
			||||||
 | 
					#include <gbinder_remote_request.h>
 | 
				
			||||||
 | 
					#include <gbinder_reader.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_servicemanager_hidl_watch {
 | 
				
			||||||
 | 
					    char* name;
 | 
				
			||||||
 | 
					    GBinderLocalObject* callback;
 | 
				
			||||||
 | 
					} GBinderServiceManagerHidlWatch;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef GBinderServiceManagerClass GBinderServiceManagerHidlClass;
 | 
				
			||||||
 | 
					typedef struct gbinder_servicemanager_hidl {
 | 
				
			||||||
 | 
					    GBinderServiceManager manager;
 | 
				
			||||||
 | 
					    GHashTable* watch_table;
 | 
				
			||||||
 | 
					} GBinderServiceManagerHidl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					G_DEFINE_TYPE(GBinderServiceManagerHidl,
 | 
				
			||||||
 | 
					    gbinder_servicemanager_hidl,
 | 
				
			||||||
 | 
					    GBINDER_TYPE_SERVICEMANAGER)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PARENT_CLASS gbinder_servicemanager_hidl_parent_class
 | 
				
			||||||
 | 
					#define GBINDER_TYPE_SERVICEMANAGER_HIDL \
 | 
				
			||||||
 | 
					    gbinder_servicemanager_hidl_get_type()
 | 
				
			||||||
 | 
					#define GBINDER_SERVICEMANAGER_HIDL(obj) \
 | 
				
			||||||
 | 
					    G_TYPE_CHECK_INSTANCE_CAST((obj), GBINDER_TYPE_SERVICEMANAGER_HIDL, \
 | 
				
			||||||
 | 
					    GBinderServiceManagerHidl)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum gbinder_servicemanager_hidl_calls {
 | 
				
			||||||
 | 
					    GET_TRANSACTION = GBINDER_FIRST_CALL_TRANSACTION,
 | 
				
			||||||
 | 
					    ADD_TRANSACTION,
 | 
				
			||||||
 | 
					    GET_TRANSPORT_TRANSACTION,
 | 
				
			||||||
 | 
					    LIST_TRANSACTION,
 | 
				
			||||||
 | 
					    LIST_BY_INTERFACE_TRANSACTION,
 | 
				
			||||||
 | 
					    REGISTER_FOR_NOTIFICATIONS_TRANSACTION,
 | 
				
			||||||
 | 
					    DEBUG_DUMP_TRANSACTION,
 | 
				
			||||||
 | 
					    REGISTER_PASSTHROUGH_CLIENT_TRANSACTION
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum gbinder_servicemanager_hidl_notifications {
 | 
				
			||||||
 | 
					    ON_REGISTRATION_TRANSACTION = GBINDER_FIRST_CALL_TRANSACTION
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SERVICEMANAGER_HIDL_IFACE  "android.hidl.manager@1.0::IServiceManager"
 | 
				
			||||||
 | 
					#define SERVICEMANAGER_HIDL_NOTIFICATION_IFACE \
 | 
				
			||||||
 | 
					    "android.hidl.manager@1.0::IServiceNotification"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_hidl_handle_registration(
 | 
				
			||||||
 | 
					    GBinderServiceManagerHidl* self,
 | 
				
			||||||
 | 
					    GBinderReader* reader)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    char* fqname = gbinder_reader_read_hidl_string(reader);
 | 
				
			||||||
 | 
					    char* name = gbinder_reader_read_hidl_string(reader);
 | 
				
			||||||
 | 
					    gboolean preexisting;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* (string fqName, string name, bool preexisting) */
 | 
				
			||||||
 | 
					    if (fqname && name && gbinder_reader_read_bool(reader, &preexisting) &&
 | 
				
			||||||
 | 
					        gbinder_reader_at_end(reader)) {
 | 
				
			||||||
 | 
					        char* full_name = g_strconcat(fqname, "/", name, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        GDEBUG("%s %s", full_name, preexisting ? "true" : "false");
 | 
				
			||||||
 | 
					        gbinder_servicemanager_service_registered(&self->manager, full_name);
 | 
				
			||||||
 | 
					        g_free(full_name);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        GWARN("Failed to parse IServiceNotification::onRegistration payload");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    g_free(fqname);
 | 
				
			||||||
 | 
					    g_free(name);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					GBinderLocalReply*
 | 
				
			||||||
 | 
					gbinder_servicemanager_hidl_notification(
 | 
				
			||||||
 | 
					    GBinderLocalObject* obj,
 | 
				
			||||||
 | 
					    GBinderRemoteRequest* req,
 | 
				
			||||||
 | 
					    guint code,
 | 
				
			||||||
 | 
					    guint flags,
 | 
				
			||||||
 | 
					    int* status,
 | 
				
			||||||
 | 
					    void* user_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServiceManagerHidl* self = GBINDER_SERVICEMANAGER_HIDL(user_data);
 | 
				
			||||||
 | 
					    const char* iface = gbinder_remote_request_interface(req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!g_strcmp0(iface, SERVICEMANAGER_HIDL_NOTIFICATION_IFACE)) {
 | 
				
			||||||
 | 
					        GBinderReader reader;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gbinder_remote_request_init_reader(req, &reader);
 | 
				
			||||||
 | 
					        switch (code) {
 | 
				
			||||||
 | 
					        case ON_REGISTRATION_TRANSACTION:
 | 
				
			||||||
 | 
					            GDEBUG(SERVICEMANAGER_HIDL_NOTIFICATION_IFACE " %u onRegistration",
 | 
				
			||||||
 | 
					                code);
 | 
				
			||||||
 | 
					            gbinder_servicemanager_hidl_handle_registration(self, &reader);
 | 
				
			||||||
 | 
					            *status = GBINDER_STATUS_OK;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            GDEBUG(SERVICEMANAGER_HIDL_NOTIFICATION_IFACE " %u", code);
 | 
				
			||||||
 | 
					            *status = GBINDER_STATUS_FAILED;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        GDEBUG("%s %u", iface, code);
 | 
				
			||||||
 | 
					        *status = GBINDER_STATUS_FAILED;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					char**
 | 
				
			||||||
 | 
					gbinder_servicemanager_hidl_list(
 | 
				
			||||||
 | 
					    GBinderServiceManager* self,
 | 
				
			||||||
 | 
					    const GBinderIpcSyncApi* api)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderLocalRequest* req = gbinder_client_new_request(self->client);
 | 
				
			||||||
 | 
					    GBinderRemoteReply* reply = gbinder_client_transact_sync_reply2
 | 
				
			||||||
 | 
					        (self->client, LIST_TRANSACTION, req, NULL, api);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gbinder_local_request_unref(req);
 | 
				
			||||||
 | 
					    if (reply) {
 | 
				
			||||||
 | 
					        GBinderReader reader;
 | 
				
			||||||
 | 
					        char** result = NULL;
 | 
				
			||||||
 | 
					        int status = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gbinder_remote_reply_init_reader(reply, &reader);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Read status */
 | 
				
			||||||
 | 
					        GVERIFY(gbinder_reader_read_int32(&reader, &status));
 | 
				
			||||||
 | 
					        GASSERT(status == GBINDER_STATUS_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Followed by hidl_vec<string> */
 | 
				
			||||||
 | 
					        result = gbinder_reader_read_hidl_string_vec(&reader);
 | 
				
			||||||
 | 
					        gbinder_remote_reply_unref(reply);
 | 
				
			||||||
 | 
					        return result;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					GBinderRemoteObject*
 | 
				
			||||||
 | 
					gbinder_servicemanager_hidl_get_service(
 | 
				
			||||||
 | 
					    GBinderServiceManager* self,
 | 
				
			||||||
 | 
					    const char* fqinstance,
 | 
				
			||||||
 | 
					    int* status,
 | 
				
			||||||
 | 
					    const GBinderIpcSyncApi* api)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /* e.g. "android.hardware.radio@1.1::IRadio/slot1" */
 | 
				
			||||||
 | 
					    const char* sep = strchr(fqinstance, '/');
 | 
				
			||||||
 | 
					    GBinderRemoteObject* obj = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (sep) {
 | 
				
			||||||
 | 
					        GBinderRemoteReply* reply;
 | 
				
			||||||
 | 
					        GBinderLocalRequest* req = gbinder_client_new_request(self->client);
 | 
				
			||||||
 | 
					        char* fqname = g_strndup(fqinstance, sep - fqinstance);
 | 
				
			||||||
 | 
					        const char* name = sep + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gbinder_local_request_append_hidl_string(req, fqname);
 | 
				
			||||||
 | 
					        gbinder_local_request_append_hidl_string(req, name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        reply = gbinder_client_transact_sync_reply2(self->client,
 | 
				
			||||||
 | 
					            GET_TRANSACTION, req, status, api);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (reply) {
 | 
				
			||||||
 | 
					            GBinderReader reader;
 | 
				
			||||||
 | 
					            int status = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            gbinder_remote_reply_init_reader(reply, &reader);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* Read status */
 | 
				
			||||||
 | 
					            GVERIFY(gbinder_reader_read_int32(&reader, &status));
 | 
				
			||||||
 | 
					            GASSERT(status == GBINDER_STATUS_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* Read the object */
 | 
				
			||||||
 | 
					            obj = gbinder_reader_read_object(&reader);
 | 
				
			||||||
 | 
					            gbinder_remote_reply_unref(reply);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gbinder_local_request_unref(req);
 | 
				
			||||||
 | 
					        g_free(fqname);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        GERR("Invalid instance \"%s\"", fqinstance);
 | 
				
			||||||
 | 
					        if (status) *status = (-EINVAL);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return obj;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					gbinder_servicemanager_hidl_add_service(
 | 
				
			||||||
 | 
					    GBinderServiceManager* self,
 | 
				
			||||||
 | 
					    const char* name,
 | 
				
			||||||
 | 
					    GBinderLocalObject* obj,
 | 
				
			||||||
 | 
					    const GBinderIpcSyncApi* api)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int status;
 | 
				
			||||||
 | 
					    GBinderRemoteReply* reply;
 | 
				
			||||||
 | 
					    GBinderLocalRequest* req = gbinder_client_new_request(self->client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* add(string name, interface service) generates (bool success); */
 | 
				
			||||||
 | 
					    gbinder_local_request_append_hidl_string(req, name);
 | 
				
			||||||
 | 
					    gbinder_local_request_append_local_object(req, obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    reply = gbinder_client_transact_sync_reply2(self->client,
 | 
				
			||||||
 | 
					        ADD_TRANSACTION, req, &status, api);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gbinder_remote_reply_unref(reply);
 | 
				
			||||||
 | 
					    gbinder_local_request_unref(req);
 | 
				
			||||||
 | 
					    return status;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_hidl_watch_free(
 | 
				
			||||||
 | 
					    gpointer data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServiceManagerHidlWatch* watch = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_free(watch->name);
 | 
				
			||||||
 | 
					    gbinder_local_object_drop(watch->callback);
 | 
				
			||||||
 | 
					    g_free(watch);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					GBINDER_SERVICEMANAGER_NAME_CHECK
 | 
				
			||||||
 | 
					gbinder_servicemanager_hidl_check_name(
 | 
				
			||||||
 | 
					    GBinderServiceManager* self,
 | 
				
			||||||
 | 
					    const char* name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (name) {
 | 
				
			||||||
 | 
					        const gsize len = strlen(name);
 | 
				
			||||||
 | 
					        static const char allowed_chars[] = "./0123456789:@"
 | 
				
			||||||
 | 
					            "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 | 
				
			||||||
 | 
					            "abcdefghijklmnopqrstuvwxyz";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (len && strspn(name, allowed_chars) == len) {
 | 
				
			||||||
 | 
					            return strchr(name, '/') ?
 | 
				
			||||||
 | 
					                GBINDER_SERVICEMANAGER_NAME_NORMALIZE :
 | 
				
			||||||
 | 
					                GBINDER_SERVICEMANAGER_NAME_OK;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return GBINDER_SERVICEMANAGER_NAME_INVALID;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					char*
 | 
				
			||||||
 | 
					gbinder_servicemanager_hidl_normalize_name(
 | 
				
			||||||
 | 
					    GBinderServiceManager* self,
 | 
				
			||||||
 | 
					    const char* name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /* Slash must be there, see gbinder_servicemanager_hidl_check_name() */
 | 
				
			||||||
 | 
					    return g_strndup(name, strchr(name, '/') - name);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_servicemanager_hidl_watch(
 | 
				
			||||||
 | 
					    GBinderServiceManager* manager,
 | 
				
			||||||
 | 
					    const char* name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServiceManagerHidl* self = GBINDER_SERVICEMANAGER_HIDL(manager);
 | 
				
			||||||
 | 
					    GBinderLocalRequest* req = gbinder_client_new_request(manager->client);
 | 
				
			||||||
 | 
					    GBinderRemoteReply* reply;
 | 
				
			||||||
 | 
					    GBinderServiceManagerHidlWatch* watch =
 | 
				
			||||||
 | 
					        g_new0(GBinderServiceManagerHidlWatch, 1);
 | 
				
			||||||
 | 
					    gboolean success = FALSE;
 | 
				
			||||||
 | 
					    int status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    watch->name = g_strdup(name);
 | 
				
			||||||
 | 
					    watch->callback = gbinder_servicemanager_new_local_object(manager,
 | 
				
			||||||
 | 
					        SERVICEMANAGER_HIDL_NOTIFICATION_IFACE,
 | 
				
			||||||
 | 
					        gbinder_servicemanager_hidl_notification, self);
 | 
				
			||||||
 | 
					    g_hash_table_replace(self->watch_table, watch->name, watch);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* registerForNotifications(string fqName, string name,
 | 
				
			||||||
 | 
					     * IServiceNotification callback) generates (bool success); */
 | 
				
			||||||
 | 
					    gbinder_local_request_append_hidl_string(req, name);
 | 
				
			||||||
 | 
					    gbinder_local_request_append_hidl_string(req, "");
 | 
				
			||||||
 | 
					    gbinder_local_request_append_local_object(req, watch->callback);
 | 
				
			||||||
 | 
					    reply = gbinder_client_transact_sync_reply(manager->client,
 | 
				
			||||||
 | 
					        REGISTER_FOR_NOTIFICATIONS_TRANSACTION, req, &status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (status == GBINDER_STATUS_OK && reply) {
 | 
				
			||||||
 | 
					        GBinderReader reader;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gbinder_remote_reply_init_reader(reply, &reader);
 | 
				
			||||||
 | 
					        if (gbinder_reader_read_int32(&reader, &status) &&
 | 
				
			||||||
 | 
					            status == GBINDER_STATUS_OK) {
 | 
				
			||||||
 | 
					            gbinder_reader_read_bool(&reader, &success);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    gbinder_remote_reply_unref(reply);
 | 
				
			||||||
 | 
					    gbinder_local_request_unref(req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!success) {
 | 
				
			||||||
 | 
					        /* unwatch() won't be called if we return FALSE */
 | 
				
			||||||
 | 
					        g_hash_table_remove(self->watch_table, watch->name);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return success;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_hidl_unwatch(
 | 
				
			||||||
 | 
					    GBinderServiceManager* manager,
 | 
				
			||||||
 | 
					    const char* name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    g_hash_table_remove(GBINDER_SERVICEMANAGER_HIDL(manager)->
 | 
				
			||||||
 | 
					        watch_table, name);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_hidl_init(
 | 
				
			||||||
 | 
					    GBinderServiceManagerHidl* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    self->watch_table = g_hash_table_new_full(g_str_hash, g_str_equal,
 | 
				
			||||||
 | 
					        NULL, gbinder_servicemanager_hidl_watch_free);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_hidl_finalize(
 | 
				
			||||||
 | 
					    GObject* object)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServiceManagerHidl* self = GBINDER_SERVICEMANAGER_HIDL(object);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_hash_table_destroy(self->watch_table);
 | 
				
			||||||
 | 
					    G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_hidl_class_init(
 | 
				
			||||||
 | 
					    GBinderServiceManagerHidlClass* klass)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    klass->iface = SERVICEMANAGER_HIDL_IFACE;
 | 
				
			||||||
 | 
					    klass->default_device = GBINDER_DEFAULT_HWBINDER;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    klass->list = gbinder_servicemanager_hidl_list;
 | 
				
			||||||
 | 
					    klass->get_service = gbinder_servicemanager_hidl_get_service;
 | 
				
			||||||
 | 
					    klass->add_service = gbinder_servicemanager_hidl_add_service;
 | 
				
			||||||
 | 
					    klass->check_name = gbinder_servicemanager_hidl_check_name;
 | 
				
			||||||
 | 
					    klass->normalize_name = gbinder_servicemanager_hidl_normalize_name;
 | 
				
			||||||
 | 
					    klass->watch = gbinder_servicemanager_hidl_watch;
 | 
				
			||||||
 | 
					    klass->unwatch = gbinder_servicemanager_hidl_unwatch;
 | 
				
			||||||
 | 
					    G_OBJECT_CLASS(klass)->finalize = gbinder_servicemanager_hidl_finalize;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Local Variables:
 | 
				
			||||||
 | 
					 * mode: C
 | 
				
			||||||
 | 
					 * c-basic-offset: 4
 | 
				
			||||||
 | 
					 * indent-tabs-mode: nil
 | 
				
			||||||
 | 
					 * End:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -39,38 +39,81 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <glib-object.h>
 | 
					#include <glib-object.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_servicemanager_priv GBinderServiceManagerPriv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct gbinder_servicemanager {
 | 
					typedef struct gbinder_servicemanager {
 | 
				
			||||||
    GObject parent;
 | 
					    GObject parent;
 | 
				
			||||||
 | 
					    GBinderServiceManagerPriv* priv;
 | 
				
			||||||
    const char* dev;
 | 
					    const char* dev;
 | 
				
			||||||
    GBinderClient* client;
 | 
					    GBinderClient* client;
 | 
				
			||||||
    GUtilIdlePool* pool;
 | 
					 | 
				
			||||||
} GBinderServiceManager;
 | 
					} GBinderServiceManager;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef enum gbinder_servicemanager_name_check {
 | 
				
			||||||
 | 
					    GBINDER_SERVICEMANAGER_NAME_OK,
 | 
				
			||||||
 | 
					    GBINDER_SERVICEMANAGER_NAME_NORMALIZE,
 | 
				
			||||||
 | 
					    GBINDER_SERVICEMANAGER_NAME_INVALID,
 | 
				
			||||||
 | 
					} GBINDER_SERVICEMANAGER_NAME_CHECK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct gbinder_servicemanager_class {
 | 
					typedef struct gbinder_servicemanager_class {
 | 
				
			||||||
    GObjectClass parent;
 | 
					    GObjectClass parent;
 | 
				
			||||||
    GMutex mutex;
 | 
					    GMutex mutex;
 | 
				
			||||||
    GHashTable* table;
 | 
					    GHashTable* table;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    guint32 handle;
 | 
					 | 
				
			||||||
    const char* iface;
 | 
					    const char* iface;
 | 
				
			||||||
    const char* default_device;
 | 
					    const char* default_device;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Methods (synchronous) */
 | 
					    /* Methods (synchronous) */
 | 
				
			||||||
    char** (*list)(GBinderServiceManager* self);
 | 
					    char** (*list)(GBinderServiceManager* self, const GBinderIpcSyncApi* api);
 | 
				
			||||||
    GBinderRemoteObject* (*get_service)
 | 
					    GBinderRemoteObject* (*get_service)(GBinderServiceManager* self,
 | 
				
			||||||
        (GBinderServiceManager* self, const char* name, int* status);
 | 
					        const char* name, int* status, const GBinderIpcSyncApi* api);
 | 
				
			||||||
    int (*add_service)
 | 
					    int (*add_service)(GBinderServiceManager* self, const char* name,
 | 
				
			||||||
        (GBinderServiceManager* self, const char* name,
 | 
					        GBinderLocalObject* obj, const GBinderIpcSyncApi* api);
 | 
				
			||||||
            GBinderLocalObject* obj);
 | 
					
 | 
				
			||||||
 | 
					    /* Checking/normalizing watch names */
 | 
				
			||||||
 | 
					    GBINDER_SERVICEMANAGER_NAME_CHECK (*check_name)
 | 
				
			||||||
 | 
					        (GBinderServiceManager* self, const char* name);
 | 
				
			||||||
 | 
					    char* (*normalize_name)(GBinderServiceManager* self, const char* name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* If watch() returns FALSE, unwatch() is not called */
 | 
				
			||||||
 | 
					    gboolean (*watch)(GBinderServiceManager* self, const char* name);
 | 
				
			||||||
 | 
					    void (*unwatch)(GBinderServiceManager* self, const char* name);
 | 
				
			||||||
} GBinderServiceManagerClass;
 | 
					} GBinderServiceManagerClass;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GType gbinder_servicemanager_get_type(void);
 | 
					GType gbinder_servicemanager_get_type(void) GBINDER_INTERNAL;
 | 
				
			||||||
#define GBINDER_TYPE_SERVICEMANAGER (gbinder_servicemanager_get_type())
 | 
					#define GBINDER_TYPE_SERVICEMANAGER (gbinder_servicemanager_get_type())
 | 
				
			||||||
 | 
					#define GBINDER_SERVICEMANAGER_CLASS(klass) \
 | 
				
			||||||
 | 
					    G_TYPE_CHECK_CLASS_CAST((klass), GBINDER_TYPE_SERVICEMANAGER, \
 | 
				
			||||||
 | 
					    GBinderServiceManagerClass)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define gbinder_servicemanager_ipc(sm) gbinder_client_ipc(sm->client)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GBinderServiceManager*
 | 
					GBinderServiceManager*
 | 
				
			||||||
gbinder_servicemanager_new_with_type(
 | 
					gbinder_servicemanager_new_with_type(
 | 
				
			||||||
    GType type,
 | 
					    GType type,
 | 
				
			||||||
    const char* dev);
 | 
					    const char* dev,
 | 
				
			||||||
 | 
					    const char* rpc_protocol)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_service_registered(
 | 
				
			||||||
 | 
					    GBinderServiceManager* self,
 | 
				
			||||||
 | 
					    const char* name)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Declared for unit tests */
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicemanager_exit(
 | 
				
			||||||
 | 
					    void)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL
 | 
				
			||||||
 | 
					    GBINDER_DESTRUCTOR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Derived types */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GType gbinder_servicemanager_aidl_get_type(void) GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					GType gbinder_servicemanager_aidl2_get_type(void) GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					GType gbinder_servicemanager_aidl3_get_type(void) GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					GType gbinder_servicemanager_aidl4_get_type(void) GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					GType gbinder_servicemanager_hidl_get_type(void) GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* GBINDER_SERVICEMANAGER_PRIVATE_H */
 | 
					#endif /* GBINDER_SERVICEMANAGER_PRIVATE_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										205
									
								
								src/gbinder_servicename.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										205
									
								
								src/gbinder_servicename.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,205 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2019-2021 Jolla Ltd.
 | 
				
			||||||
 | 
					 * Copyright (C) 2019-2021 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   1. Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 | 
					 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
				
			||||||
 | 
					 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
				
			||||||
 | 
					 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
				
			||||||
 | 
					 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
				
			||||||
 | 
					 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
				
			||||||
 | 
					 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
				
			||||||
 | 
					 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
				
			||||||
 | 
					 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
				
			||||||
 | 
					 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "gbinder_types_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_eventloop_p.h"
 | 
				
			||||||
 | 
					#include "gbinder_servicename.h"
 | 
				
			||||||
 | 
					#include "gbinder_servicemanager.h"
 | 
				
			||||||
 | 
					#include "gbinder_local_object.h"
 | 
				
			||||||
 | 
					#include "gbinder_log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gutil_macros.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Since 1.0.26 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define GBINDER_SERVICENAME_RETRY_INTERVAL_MS (500)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_servicename_priv {
 | 
				
			||||||
 | 
					    GBinderServiceName pub;
 | 
				
			||||||
 | 
					    gint refcount;
 | 
				
			||||||
 | 
					    char* name;
 | 
				
			||||||
 | 
					    GBinderLocalObject* object;
 | 
				
			||||||
 | 
					    GBinderServiceManager* sm;
 | 
				
			||||||
 | 
					    GBinderEventLoopTimeout* retry_timer;
 | 
				
			||||||
 | 
					    gulong presence_id;
 | 
				
			||||||
 | 
					    gulong add_call_id;
 | 
				
			||||||
 | 
					} GBinderServiceNamePriv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicename_add_service(
 | 
				
			||||||
 | 
					    GBinderServiceNamePriv* priv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBINDER_INLINE_FUNC GBinderServiceNamePriv*
 | 
				
			||||||
 | 
					gbinder_servicename_cast(GBinderServiceName* pub)
 | 
				
			||||||
 | 
					    { return G_CAST(pub, GBinderServiceNamePriv, pub); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*==========================================================================*
 | 
				
			||||||
 | 
					 * Implementation
 | 
				
			||||||
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_servicename_add_service_retry(
 | 
				
			||||||
 | 
					    gpointer user_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServiceNamePriv* priv = user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    priv->retry_timer = NULL;
 | 
				
			||||||
 | 
					    gbinder_servicename_add_service(priv);
 | 
				
			||||||
 | 
					    return G_SOURCE_REMOVE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicename_add_service_done(
 | 
				
			||||||
 | 
					    GBinderServiceManager* sm,
 | 
				
			||||||
 | 
					    int status,
 | 
				
			||||||
 | 
					    void* user_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServiceNamePriv* priv = user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    GASSERT(priv->add_call_id);
 | 
				
			||||||
 | 
					    priv->add_call_id = 0;
 | 
				
			||||||
 | 
					    if (status) {
 | 
				
			||||||
 | 
					        GWARN("Error %d adding name \"%s\"", status, priv->name);
 | 
				
			||||||
 | 
					        gbinder_timeout_remove(priv->retry_timer);
 | 
				
			||||||
 | 
					        priv->retry_timer =
 | 
				
			||||||
 | 
					            gbinder_timeout_add(GBINDER_SERVICENAME_RETRY_INTERVAL_MS,
 | 
				
			||||||
 | 
					                gbinder_servicename_add_service_retry, priv);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        GDEBUG("Service \"%s\" has been registered", priv->name);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicename_add_service(
 | 
				
			||||||
 | 
					    GBinderServiceNamePriv* priv)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GDEBUG("Adding service \"%s\"", priv->name);
 | 
				
			||||||
 | 
					    gbinder_servicemanager_cancel(priv->sm, priv->add_call_id);
 | 
				
			||||||
 | 
					    priv->add_call_id = gbinder_servicemanager_add_service(priv->sm,
 | 
				
			||||||
 | 
					        priv->name, priv->object, gbinder_servicename_add_service_done, priv);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicename_presence_handler(
 | 
				
			||||||
 | 
					    GBinderServiceManager* sm,
 | 
				
			||||||
 | 
					    void* user_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServiceNamePriv* priv = user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (gbinder_servicemanager_is_present(sm)) {
 | 
				
			||||||
 | 
					        gbinder_servicename_add_service(priv);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        if (priv->add_call_id) {
 | 
				
			||||||
 | 
					            gbinder_servicemanager_cancel(priv->sm, priv->add_call_id);
 | 
				
			||||||
 | 
					            priv->add_call_id = 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (priv->retry_timer) {
 | 
				
			||||||
 | 
					            gbinder_timeout_remove(priv->retry_timer);
 | 
				
			||||||
 | 
					            priv->retry_timer = NULL;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*==========================================================================*
 | 
				
			||||||
 | 
					 * Interface
 | 
				
			||||||
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderServiceName*
 | 
				
			||||||
 | 
					gbinder_servicename_new(
 | 
				
			||||||
 | 
					    GBinderServiceManager* sm,
 | 
				
			||||||
 | 
					    GBinderLocalObject* object,
 | 
				
			||||||
 | 
					    const char* name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (G_LIKELY(sm) && G_LIKELY(object) && G_LIKELY(name)) {
 | 
				
			||||||
 | 
					        GBinderServiceNamePriv* priv = g_slice_new0(GBinderServiceNamePriv);
 | 
				
			||||||
 | 
					        GBinderServiceName* self = &priv->pub;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        g_atomic_int_set(&priv->refcount, 1);
 | 
				
			||||||
 | 
					        priv->object = gbinder_local_object_ref(object);
 | 
				
			||||||
 | 
					        priv->sm = gbinder_servicemanager_ref(sm);
 | 
				
			||||||
 | 
					        self->name = priv->name = g_strdup(name);
 | 
				
			||||||
 | 
					        priv->presence_id = gbinder_servicemanager_add_presence_handler(sm,
 | 
				
			||||||
 | 
					            gbinder_servicename_presence_handler, priv);
 | 
				
			||||||
 | 
					        if (gbinder_servicemanager_is_present(sm)) {
 | 
				
			||||||
 | 
					            gbinder_servicename_add_service(priv);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return self;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderServiceName*
 | 
				
			||||||
 | 
					gbinder_servicename_ref(
 | 
				
			||||||
 | 
					    GBinderServiceName* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
 | 
					        GBinderServiceNamePriv* priv = gbinder_servicename_cast(self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        GASSERT(priv->refcount > 0);
 | 
				
			||||||
 | 
					        g_atomic_int_inc(&priv->refcount);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return self;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicename_unref(
 | 
				
			||||||
 | 
					    GBinderServiceName* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
 | 
					        GBinderServiceNamePriv* priv = gbinder_servicename_cast(self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        GASSERT(priv->refcount > 0);
 | 
				
			||||||
 | 
					        if (g_atomic_int_dec_and_test(&priv->refcount)) {
 | 
				
			||||||
 | 
					            gbinder_servicemanager_cancel(priv->sm, priv->add_call_id);
 | 
				
			||||||
 | 
					            gbinder_servicemanager_remove_handler(priv->sm, priv->presence_id);
 | 
				
			||||||
 | 
					            gbinder_servicemanager_unref(priv->sm);
 | 
				
			||||||
 | 
					            gbinder_local_object_unref(priv->object);
 | 
				
			||||||
 | 
					            gbinder_timeout_remove(priv->retry_timer);
 | 
				
			||||||
 | 
					            g_free(priv->name);
 | 
				
			||||||
 | 
					            gutil_slice_free(priv);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Local Variables:
 | 
				
			||||||
 | 
					 * mode: C
 | 
				
			||||||
 | 
					 * c-basic-offset: 4
 | 
				
			||||||
 | 
					 * indent-tabs-mode: nil
 | 
				
			||||||
 | 
					 * End:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
							
								
								
									
										272
									
								
								src/gbinder_servicepoll.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										272
									
								
								src/gbinder_servicepoll.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,272 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
				
			||||||
 | 
					 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   1. Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 | 
					 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
				
			||||||
 | 
					 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
				
			||||||
 | 
					 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
				
			||||||
 | 
					 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
				
			||||||
 | 
					 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
				
			||||||
 | 
					 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
				
			||||||
 | 
					 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
				
			||||||
 | 
					 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
				
			||||||
 | 
					 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "gbinder_servicepoll.h"
 | 
				
			||||||
 | 
					#include "gbinder_servicemanager.h"
 | 
				
			||||||
 | 
					#include "gbinder_eventloop_p.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gutil_strv.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <glib-object.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* This is configurable mostly so that unit testing doesn't take too long */
 | 
				
			||||||
 | 
					guint gbinder_servicepoll_interval_ms = 2000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef GObjectClass GBinderServicePollClass;
 | 
				
			||||||
 | 
					struct gbinder_servicepoll {
 | 
				
			||||||
 | 
					    GObject object;
 | 
				
			||||||
 | 
					    GBinderServiceManager* manager;
 | 
				
			||||||
 | 
					    char** list;
 | 
				
			||||||
 | 
					    gulong list_id;
 | 
				
			||||||
 | 
					    GBinderEventLoopTimeout* timer;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PARENT_CLASS gbinder_servicepoll_parent_class
 | 
				
			||||||
 | 
					#define THIS_TYPE gbinder_servicepoll_get_type()
 | 
				
			||||||
 | 
					#define THIS(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, THIS_TYPE, GBinderServicePoll)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GType THIS_TYPE GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					G_DEFINE_TYPE(GBinderServicePoll, gbinder_servicepoll, G_TYPE_OBJECT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum gbinder_servicepoll_signal {
 | 
				
			||||||
 | 
					    SIGNAL_NAME_ADDED,
 | 
				
			||||||
 | 
					    SIGNAL_COUNT
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const char SIGNAL_NAME_ADDED_NAME[] = "servicepoll-name-added";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static guint gbinder_servicepoll_signals[SIGNAL_COUNT] = { 0 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*==========================================================================*
 | 
				
			||||||
 | 
					 * Implementation
 | 
				
			||||||
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* GBinderServiceManagerListFunc callback returns TRUE to keep the services
 | 
				
			||||||
 | 
					 * list, otherwise the caller will deallocate it. */
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_servicepoll_list(
 | 
				
			||||||
 | 
					    GBinderServiceManager* sm,
 | 
				
			||||||
 | 
					    char** services,
 | 
				
			||||||
 | 
					    void* user_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServicePoll* self = THIS(user_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gbinder_servicepoll_ref(self);
 | 
				
			||||||
 | 
					    self->list_id = 0;
 | 
				
			||||||
 | 
					    if (services) {
 | 
				
			||||||
 | 
					        const GStrV* ptr_new;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ptr_new = services = gutil_strv_sort(services, TRUE);
 | 
				
			||||||
 | 
					        if (self->list) {
 | 
				
			||||||
 | 
					            const GStrV* ptr_old = self->list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            while (*ptr_new && *ptr_old) {
 | 
				
			||||||
 | 
					                const int i = gutil_strv_find(ptr_old, *ptr_new);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (i < 0) {
 | 
				
			||||||
 | 
					                    /* New name */
 | 
				
			||||||
 | 
					                    g_signal_emit(self, gbinder_servicepoll_signals
 | 
				
			||||||
 | 
					                        [SIGNAL_NAME_ADDED], 0, *ptr_new);
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    int k;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    /* If some names have disappeared, then i may be > 0 */
 | 
				
			||||||
 | 
					                    for (k = 0; k < i; k ++) ptr_old++;
 | 
				
			||||||
 | 
					                    ptr_old++;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                ptr_new++;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        while (*ptr_new) {
 | 
				
			||||||
 | 
					            g_signal_emit(self, gbinder_servicepoll_signals
 | 
				
			||||||
 | 
					                [SIGNAL_NAME_ADDED], 0, *ptr_new);
 | 
				
			||||||
 | 
					            ptr_new++;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_strfreev(self->list);
 | 
				
			||||||
 | 
					    self->list = services;
 | 
				
			||||||
 | 
					    gbinder_servicepoll_unref(self);
 | 
				
			||||||
 | 
					    return TRUE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_servicepoll_timer(
 | 
				
			||||||
 | 
					    gpointer user_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServicePoll* self = THIS(user_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!self->list_id) {
 | 
				
			||||||
 | 
					        self->list_id = gbinder_servicemanager_list(self->manager,
 | 
				
			||||||
 | 
					            gbinder_servicepoll_list, self);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return G_SOURCE_CONTINUE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					GBinderServicePoll*
 | 
				
			||||||
 | 
					gbinder_servicepoll_create(
 | 
				
			||||||
 | 
					    GBinderServiceManager* manager)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServicePoll* self = g_object_new(THIS_TYPE, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    self->manager = gbinder_servicemanager_ref(manager);
 | 
				
			||||||
 | 
					    self->list_id = gbinder_servicemanager_list(manager,
 | 
				
			||||||
 | 
					        gbinder_servicepoll_list, self);
 | 
				
			||||||
 | 
					    return self;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*==========================================================================*
 | 
				
			||||||
 | 
					 * API
 | 
				
			||||||
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderServicePoll*
 | 
				
			||||||
 | 
					gbinder_servicepoll_new(
 | 
				
			||||||
 | 
					    GBinderServiceManager* manager,
 | 
				
			||||||
 | 
					    GBinderServicePoll** weakptr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (weakptr) {
 | 
				
			||||||
 | 
					        if (*weakptr) {
 | 
				
			||||||
 | 
					            gbinder_servicepoll_ref(*weakptr);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            *weakptr = gbinder_servicepoll_create(manager);
 | 
				
			||||||
 | 
					            g_object_add_weak_pointer(G_OBJECT(*weakptr), (gpointer*)weakptr);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return *weakptr;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        return gbinder_servicepoll_create(manager);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderServicePoll*
 | 
				
			||||||
 | 
					gbinder_servicepoll_ref(
 | 
				
			||||||
 | 
					    GBinderServicePoll* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
 | 
					        g_object_ref(THIS(self));
 | 
				
			||||||
 | 
					        return self;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicepoll_unref(
 | 
				
			||||||
 | 
					    GBinderServicePoll* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (G_LIKELY(self)) {
 | 
				
			||||||
 | 
					        g_object_unref(THIS(self));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderServiceManager*
 | 
				
			||||||
 | 
					gbinder_servicepoll_manager(
 | 
				
			||||||
 | 
					    GBinderServicePoll* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return G_LIKELY(self) ? self->manager : NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_servicepoll_is_known_name(
 | 
				
			||||||
 | 
					    GBinderServicePoll* self,
 | 
				
			||||||
 | 
					    const char* name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return G_LIKELY(self) && gutil_strv_contains(self->list, name);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gulong
 | 
				
			||||||
 | 
					gbinder_servicepoll_add_handler(
 | 
				
			||||||
 | 
					    GBinderServicePoll* self,
 | 
				
			||||||
 | 
					    GBinderServicePollFunc fn,
 | 
				
			||||||
 | 
					    void* user_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return (G_LIKELY(self) && G_LIKELY(fn)) ? g_signal_connect(self,
 | 
				
			||||||
 | 
					        SIGNAL_NAME_ADDED_NAME, G_CALLBACK(fn), user_data) : 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicepoll_remove_handler(
 | 
				
			||||||
 | 
					    GBinderServicePoll* self,
 | 
				
			||||||
 | 
					    gulong id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (G_LIKELY(self) && G_LIKELY(id)) {
 | 
				
			||||||
 | 
					        g_signal_handler_disconnect(self, id);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*==========================================================================*
 | 
				
			||||||
 | 
					 * Internals
 | 
				
			||||||
 | 
					 *==========================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicepoll_init(
 | 
				
			||||||
 | 
					    GBinderServicePoll* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    self->timer = gbinder_timeout_add(gbinder_servicepoll_interval_ms,
 | 
				
			||||||
 | 
					        gbinder_servicepoll_timer, self);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicepoll_finalize(
 | 
				
			||||||
 | 
					    GObject* object)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GBinderServicePoll* self = THIS(object);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gbinder_timeout_remove(self->timer);
 | 
				
			||||||
 | 
					    gbinder_servicemanager_cancel(self->manager, self->list_id);
 | 
				
			||||||
 | 
					    gbinder_servicemanager_unref(self->manager);
 | 
				
			||||||
 | 
					    g_strfreev(self->list);
 | 
				
			||||||
 | 
					    G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicepoll_class_init(
 | 
				
			||||||
 | 
					    GBinderServicePollClass* klass)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    G_OBJECT_CLASS(klass)->finalize = gbinder_servicepoll_finalize;
 | 
				
			||||||
 | 
					    gbinder_servicepoll_signals[SIGNAL_NAME_ADDED] =
 | 
				
			||||||
 | 
					        g_signal_new(SIGNAL_NAME_ADDED_NAME, G_OBJECT_CLASS_TYPE(klass),
 | 
				
			||||||
 | 
					            G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE,
 | 
				
			||||||
 | 
					            1, G_TYPE_STRING);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Local Variables:
 | 
				
			||||||
 | 
					 * mode: C
 | 
				
			||||||
 | 
					 * c-basic-offset: 4
 | 
				
			||||||
 | 
					 * indent-tabs-mode: nil
 | 
				
			||||||
 | 
					 * End:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
							
								
								
									
										95
									
								
								src/gbinder_servicepoll.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								src/gbinder_servicepoll.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,95 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2018-2020 Jolla Ltd.
 | 
				
			||||||
 | 
					 * Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   1. Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 | 
					 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
				
			||||||
 | 
					 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
				
			||||||
 | 
					 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
				
			||||||
 | 
					 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
				
			||||||
 | 
					 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
				
			||||||
 | 
					 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
				
			||||||
 | 
					 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
				
			||||||
 | 
					 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
				
			||||||
 | 
					 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GBINDER_SERVICEPOLL_H
 | 
				
			||||||
 | 
					#define GBINDER_SERVICEPOLL_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "gbinder_types_p.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern guint gbinder_servicepoll_interval_ms GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					(*GBinderServicePollFunc)(
 | 
				
			||||||
 | 
					    GBinderServicePoll* poll,
 | 
				
			||||||
 | 
					    const char* name_added,
 | 
				
			||||||
 | 
					    void* user_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderServicePoll*
 | 
				
			||||||
 | 
					gbinder_servicepoll_new(
 | 
				
			||||||
 | 
					    GBinderServiceManager* manager,
 | 
				
			||||||
 | 
					    GBinderServicePoll** weakptr)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderServicePoll*
 | 
				
			||||||
 | 
					gbinder_servicepoll_ref(
 | 
				
			||||||
 | 
					    GBinderServicePoll* poll)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicepoll_unref(
 | 
				
			||||||
 | 
					    GBinderServicePoll* poll)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GBinderServiceManager*
 | 
				
			||||||
 | 
					gbinder_servicepoll_manager(
 | 
				
			||||||
 | 
					    GBinderServicePoll* poll)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gboolean
 | 
				
			||||||
 | 
					gbinder_servicepoll_is_known_name(
 | 
				
			||||||
 | 
					    GBinderServicePoll* poll,
 | 
				
			||||||
 | 
					    const char* name)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gulong
 | 
				
			||||||
 | 
					gbinder_servicepoll_add_handler(
 | 
				
			||||||
 | 
					    GBinderServicePoll* poll,
 | 
				
			||||||
 | 
					    GBinderServicePollFunc func,
 | 
				
			||||||
 | 
					    void* user_data)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_servicepoll_remove_handler(
 | 
				
			||||||
 | 
					    GBinderServicePoll* poll,
 | 
				
			||||||
 | 
					    gulong id)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* GBINDER_SERVICEPOLL_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Local Variables:
 | 
				
			||||||
 | 
					 * mode: C
 | 
				
			||||||
 | 
					 * c-basic-offset: 4
 | 
				
			||||||
 | 
					 * indent-tabs-mode: nil
 | 
				
			||||||
 | 
					 * End:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
				
			||||||
 * Contact: Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -34,6 +34,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
#include <fcntl.h>
 | 
					#include <fcntl.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
#include <sys/ioctl.h>
 | 
					#include <sys/ioctl.h>
 | 
				
			||||||
#include <sys/mman.h>
 | 
					#include <sys/mman.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -58,7 +59,10 @@ gbinder_system_ioctl(
 | 
				
			|||||||
    int request,
 | 
					    int request,
 | 
				
			||||||
    void* data)
 | 
					    void* data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return ioctl(fd, request, data);
 | 
					    int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while ((ret = ioctl(fd, request, data)) < 0 && errno == EINTR);
 | 
				
			||||||
 | 
					    return ret >= 0 ? 0 : -errno;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void*
 | 
					void*
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2020 Jolla Ltd.
 | 
				
			||||||
 * Contact: Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -38,29 +38,34 @@
 | 
				
			|||||||
int
 | 
					int
 | 
				
			||||||
gbinder_system_open(
 | 
					gbinder_system_open(
 | 
				
			||||||
    const char* path,
 | 
					    const char* path,
 | 
				
			||||||
    int flags);
 | 
					    int flags)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
gbinder_system_close(
 | 
					gbinder_system_close(
 | 
				
			||||||
    int fd);
 | 
					    int fd)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
gbinder_system_ioctl(
 | 
					gbinder_system_ioctl(
 | 
				
			||||||
    int fd,
 | 
					    int fd,
 | 
				
			||||||
    int request,
 | 
					    int request,
 | 
				
			||||||
    void* data);
 | 
					    void* data)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void*
 | 
					void*
 | 
				
			||||||
gbinder_system_mmap(
 | 
					gbinder_system_mmap(
 | 
				
			||||||
   size_t length,
 | 
					   size_t length,
 | 
				
			||||||
   int prot,
 | 
					   int prot,
 | 
				
			||||||
   int flags,
 | 
					   int flags,
 | 
				
			||||||
   int fd);
 | 
					   int fd)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
gbinder_system_munmap(
 | 
					gbinder_system_munmap(
 | 
				
			||||||
    void* addr,
 | 
					    void* addr,
 | 
				
			||||||
    size_t length);
 | 
					    size_t length)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* GBINDER_SYSTEM_H */
 | 
					#endif /* GBINDER_SYSTEM_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -35,38 +35,24 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <gbinder_types.h>
 | 
					#include <gbinder_types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbinder_buffer_contents GBinderBufferContents;
 | 
				
			||||||
 | 
					typedef struct gbinder_buffer_contents_list GBinderBufferContentsList;
 | 
				
			||||||
typedef struct gbinder_cleanup GBinderCleanup;
 | 
					typedef struct gbinder_cleanup GBinderCleanup;
 | 
				
			||||||
typedef struct gbinder_driver GBinderDriver;
 | 
					typedef struct gbinder_driver GBinderDriver;
 | 
				
			||||||
typedef struct gbinder_handler GBinderHandler;
 | 
					typedef struct gbinder_handler GBinderHandler;
 | 
				
			||||||
typedef struct gbinder_io GBinderIo;
 | 
					typedef struct gbinder_io GBinderIo;
 | 
				
			||||||
typedef struct gbinder_ipc GBinderIpc;
 | 
					typedef struct gbinder_object_converter GBinderObjectConverter;
 | 
				
			||||||
typedef struct gbinder_object_registry GBinderObjectRegistry;
 | 
					typedef struct gbinder_object_registry GBinderObjectRegistry;
 | 
				
			||||||
typedef struct gbinder_output_data GBinderOutputData;
 | 
					typedef struct gbinder_output_data GBinderOutputData;
 | 
				
			||||||
 | 
					typedef struct gbinder_proxy_object GBinderProxyObject;
 | 
				
			||||||
typedef struct gbinder_rpc_protocol GBinderRpcProtocol;
 | 
					typedef struct gbinder_rpc_protocol GBinderRpcProtocol;
 | 
				
			||||||
 | 
					typedef struct gbinder_servicepoll GBinderServicePoll;
 | 
				
			||||||
typedef struct hidl_vec {
 | 
					typedef struct gbinder_ipc_looper_tx GBinderIpcLooperTx;
 | 
				
			||||||
    union {
 | 
					typedef struct gbinder_ipc_sync_api GBinderIpcSyncApi;
 | 
				
			||||||
        guint64 value;
 | 
					 | 
				
			||||||
        const void* ptr;
 | 
					 | 
				
			||||||
    } data;
 | 
					 | 
				
			||||||
    guint32 count;
 | 
					 | 
				
			||||||
    guint32 owns_buffer;
 | 
					 | 
				
			||||||
} HidlVec;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define HIDL_VEC_BUFFER_OFFSET (0)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef struct hidl_string {
 | 
					 | 
				
			||||||
    union {
 | 
					 | 
				
			||||||
        guint64 value;
 | 
					 | 
				
			||||||
        const char* str;
 | 
					 | 
				
			||||||
    } data;
 | 
					 | 
				
			||||||
    guint32 len;
 | 
					 | 
				
			||||||
    guint32 owns_buffer;
 | 
					 | 
				
			||||||
} HidlString;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define HIDL_STRING_BUFFER_OFFSET (0)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define GBINDER_INLINE_FUNC static inline
 | 
					#define GBINDER_INLINE_FUNC static inline
 | 
				
			||||||
 | 
					#define GBINDER_INTERNAL G_GNUC_INTERNAL
 | 
				
			||||||
 | 
					#define GBINDER_DESTRUCTOR __attribute__((destructor))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define GBINDER_TRANSACTION(c2,c3,c4)     GBINDER_FOURCC('_',c2,c3,c4)
 | 
					#define GBINDER_TRANSACTION(c2,c3,c4)     GBINDER_FOURCC('_',c2,c3,c4)
 | 
				
			||||||
#define GBINDER_PING_TRANSACTION          GBINDER_TRANSACTION('P','N','G')
 | 
					#define GBINDER_PING_TRANSACTION          GBINDER_TRANSACTION('P','N','G')
 | 
				
			||||||
@@ -88,6 +74,9 @@ typedef struct hidl_string {
 | 
				
			|||||||
#define HIDL_DEBUG_TRANSACTION                    HIDL_FOURCC('D','B','G')
 | 
					#define HIDL_DEBUG_TRANSACTION                    HIDL_FOURCC('D','B','G')
 | 
				
			||||||
#define HIDL_HASH_CHAIN_TRANSACTION               HIDL_FOURCC('H','S','H')
 | 
					#define HIDL_HASH_CHAIN_TRANSACTION               HIDL_FOURCC('H','S','H')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* As a special case, ServiceManager's handle is zero */
 | 
				
			||||||
 | 
					#define GBINDER_SERVICEMANAGER_HANDLE (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* GBINDER_TYPES_PRIVATE_H */
 | 
					#endif /* GBINDER_TYPES_PRIVATE_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1003
									
								
								src/gbinder_writer.c
									
									
									
									
									
								
							
							
						
						
									
										1003
									
								
								src/gbinder_writer.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
					 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
				
			||||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
					 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You may use this file under the terms of BSD license as follows:
 | 
					 * You may use this file under the terms of BSD license as follows:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -13,9 +13,9 @@
 | 
				
			|||||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
					 *   2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
					 *      notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 *      documentation and/or other materials provided with the distribution.
 | 
					 *      documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
					 *   3. Neither the names of the copyright holders nor the names of its
 | 
				
			||||||
 *      be used to endorse or promote products derived from this software
 | 
					 *      contributors may be used to endorse or promote products derived
 | 
				
			||||||
 *      without specific prior written permission.
 | 
					 *      from this software without specific prior written permission.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
@@ -39,6 +39,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
typedef struct gbinder_writer_data {
 | 
					typedef struct gbinder_writer_data {
 | 
				
			||||||
    const GBinderIo* io;
 | 
					    const GBinderIo* io;
 | 
				
			||||||
 | 
					    const GBinderRpcProtocol* protocol;
 | 
				
			||||||
    GByteArray* bytes;
 | 
					    GByteArray* bytes;
 | 
				
			||||||
    GUtilIntArray* offsets;
 | 
					    GUtilIntArray* offsets;
 | 
				
			||||||
    gsize buffers_size;
 | 
					    gsize buffers_size;
 | 
				
			||||||
@@ -48,82 +49,133 @@ typedef struct gbinder_writer_data {
 | 
				
			|||||||
void
 | 
					void
 | 
				
			||||||
gbinder_writer_init(
 | 
					gbinder_writer_init(
 | 
				
			||||||
    GBinderWriter* writer,
 | 
					    GBinderWriter* writer,
 | 
				
			||||||
    GBinderWriterData* data);
 | 
					    GBinderWriterData* data)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_writer_data_set_contents(
 | 
				
			||||||
 | 
					    GBinderWriterData* data,
 | 
				
			||||||
 | 
					    GBinderBuffer* buffer,
 | 
				
			||||||
 | 
					    GBinderObjectConverter* convert)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_writer_data_append_contents(
 | 
				
			||||||
 | 
					    GBinderWriterData* data,
 | 
				
			||||||
 | 
					    GBinderBuffer* buffer,
 | 
				
			||||||
 | 
					    gsize data_offset,
 | 
				
			||||||
 | 
					    GBinderObjectConverter* convert)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_writer_data_append_bool(
 | 
					gbinder_writer_data_append_bool(
 | 
				
			||||||
    GBinderWriterData* data,
 | 
					    GBinderWriterData* data,
 | 
				
			||||||
    gboolean value);
 | 
					    gboolean value)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_writer_data_append_int32(
 | 
					gbinder_writer_data_append_int32(
 | 
				
			||||||
    GBinderWriterData* data,
 | 
					    GBinderWriterData* data,
 | 
				
			||||||
    guint32 value);
 | 
					    guint32 value)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_writer_data_append_int64(
 | 
					gbinder_writer_data_append_int64(
 | 
				
			||||||
    GBinderWriterData* data,
 | 
					    GBinderWriterData* data,
 | 
				
			||||||
    guint64 value);
 | 
					    guint64 value)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_writer_data_append_float(
 | 
					gbinder_writer_data_append_float(
 | 
				
			||||||
    GBinderWriterData* data,
 | 
					    GBinderWriterData* data,
 | 
				
			||||||
    gfloat value);
 | 
					    gfloat value)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_writer_data_append_double(
 | 
					gbinder_writer_data_append_double(
 | 
				
			||||||
    GBinderWriterData* data,
 | 
					    GBinderWriterData* data,
 | 
				
			||||||
    gdouble value);
 | 
					    gdouble value)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_writer_data_append_string8(
 | 
					gbinder_writer_data_append_string8(
 | 
				
			||||||
    GBinderWriterData* data,
 | 
					    GBinderWriterData* data,
 | 
				
			||||||
    const char* str);
 | 
					    const char* str)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_writer_data_append_string8_len(
 | 
					gbinder_writer_data_append_string8_len(
 | 
				
			||||||
    GBinderWriterData* data,
 | 
					    GBinderWriterData* data,
 | 
				
			||||||
    const char* str,
 | 
					    const char* str,
 | 
				
			||||||
    gsize len);
 | 
					    gsize len)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_writer_data_append_string16(
 | 
					gbinder_writer_data_append_string16(
 | 
				
			||||||
    GBinderWriterData* data,
 | 
					    GBinderWriterData* data,
 | 
				
			||||||
    const char* utf8);
 | 
					    const char* utf8)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_writer_data_append_string16_len(
 | 
					gbinder_writer_data_append_string16_len(
 | 
				
			||||||
    GBinderWriterData* data,
 | 
					    GBinderWriterData* data,
 | 
				
			||||||
    const char* utf8,
 | 
					    const char* utf8,
 | 
				
			||||||
    gssize num_bytes);
 | 
					    gssize num_bytes)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
guint
 | 
					guint
 | 
				
			||||||
gbinder_writer_data_append_buffer_object(
 | 
					gbinder_writer_data_append_buffer_object(
 | 
				
			||||||
    GBinderWriterData* data,
 | 
					    GBinderWriterData* data,
 | 
				
			||||||
    const void* ptr,
 | 
					    const void* ptr,
 | 
				
			||||||
    gsize size,
 | 
					    gsize size,
 | 
				
			||||||
    const GBinderParent* parent);
 | 
					    const GBinderParent* parent)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_writer_data_append_parcelable(
 | 
				
			||||||
 | 
					    GBinderWriterData* data,
 | 
				
			||||||
 | 
					    const void* ptr,
 | 
				
			||||||
 | 
					    gsize size)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_writer_data_append_hidl_vec(
 | 
				
			||||||
 | 
					    GBinderWriterData* data,
 | 
				
			||||||
 | 
					    const void* base,
 | 
				
			||||||
 | 
					    guint count,
 | 
				
			||||||
 | 
					    guint elemsize)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_writer_data_append_hidl_string(
 | 
					gbinder_writer_data_append_hidl_string(
 | 
				
			||||||
    GBinderWriterData* data,
 | 
					    GBinderWriterData* data,
 | 
				
			||||||
    const char* str);
 | 
					    const char* str)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_writer_data_append_hidl_string_vec(
 | 
					gbinder_writer_data_append_hidl_string_vec(
 | 
				
			||||||
    GBinderWriterData* data,
 | 
					    GBinderWriterData* data,
 | 
				
			||||||
    const char* strv[],
 | 
					    const char* strv[],
 | 
				
			||||||
    gssize count);
 | 
					    gssize count)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_writer_data_append_local_object(
 | 
					gbinder_writer_data_append_local_object(
 | 
				
			||||||
    GBinderWriterData* data,
 | 
					    GBinderWriterData* data,
 | 
				
			||||||
    GBinderLocalObject* obj);
 | 
					    GBinderLocalObject* obj)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
gbinder_writer_data_append_remote_object(
 | 
					gbinder_writer_data_append_remote_object(
 | 
				
			||||||
    GBinderWriterData* data,
 | 
					    GBinderWriterData* data,
 | 
				
			||||||
    GBinderRemoteObject* obj);
 | 
					    GBinderRemoteObject* obj)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					gbinder_writer_data_append_fd(
 | 
				
			||||||
 | 
					    GBinderWriterData* data,
 | 
				
			||||||
 | 
					    int fd)
 | 
				
			||||||
 | 
					    GBINDER_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* GBINDER_WRITER_PRIVATE_H */
 | 
					#endif /* GBINDER_WRITER_PRIVATE_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
all:
 | 
					all:
 | 
				
			||||||
%:
 | 
					%:
 | 
				
			||||||
 | 
						@$(MAKE) -C binder-bridge $*
 | 
				
			||||||
	@$(MAKE) -C binder-client $*
 | 
						@$(MAKE) -C binder-client $*
 | 
				
			||||||
 | 
						@$(MAKE) -C binder-dump $*
 | 
				
			||||||
	@$(MAKE) -C binder-list $*
 | 
						@$(MAKE) -C binder-list $*
 | 
				
			||||||
 | 
						@$(MAKE) -C binder-ping $*
 | 
				
			||||||
	@$(MAKE) -C binder-service $*
 | 
						@$(MAKE) -C binder-service $*
 | 
				
			||||||
 | 
						@$(MAKE) -C binder-call $*
 | 
				
			||||||
	@$(MAKE) -C rild-card-status $*
 | 
						@$(MAKE) -C rild-card-status $*
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										5
									
								
								test/ashmem-test/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								test/ashmem-test/Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					# -*- Mode: makefile-gmake -*-
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EXE = ashmem-test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include ../common/Makefile
 | 
				
			||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user