mirror of
				https://github.com/topjohnwu/Magisk
				synced 2025-11-02 14:12:29 +01:00 
			
		
		
		
	Compare commits
	
		
			297 Commits
		
	
	
		
			canary-280
			...
			v30.0
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					e81de7ec36 | ||
| 
						 | 
					c78da1ce24 | ||
| 
						 | 
					7b2d40987c | ||
| 
						 | 
					3a37e8c9c5 | ||
| 
						 | 
					58b405bce1 | ||
| 
						 | 
					810174ef73 | ||
| 
						 | 
					690a5ac033 | ||
| 
						 | 
					89aad31f7e | ||
| 
						 | 
					7124db98e3 | ||
| 
						 | 
					0860e859f7 | ||
| 
						 | 
					04008949b8 | ||
| 
						 | 
					39f2940bd1 | ||
| 
						 | 
					1460317ebd | ||
| 
						 | 
					12340c9bd5 | ||
| 
						 | 
					c4590fe2ba | ||
| 
						 | 
					b36066bbcd | ||
| 
						 | 
					65d1c5827c | ||
| 
						 | 
					1d675c8b2e | ||
| 
						 | 
					0b494ed7df | ||
| 
						 | 
					48d9fc24eb | ||
| 
						 | 
					83426f7f36 | ||
| 
						 | 
					0e86d4dbcb | ||
| 
						 | 
					5e050d7456 | ||
| 
						 | 
					898580bf90 | ||
| 
						 | 
					86621a4c46 | ||
| 
						 | 
					a834e72b71 | ||
| 
						 | 
					d8cf42af16 | ||
| 
						 | 
					8c79d66b7b | ||
| 
						 | 
					fada8b148a | ||
| 
						 | 
					dc0acea47c | ||
| 
						 | 
					78d1200608 | ||
| 
						 | 
					527bbc0368 | ||
| 
						 | 
					4c89c7e2b3 | ||
| 
						 | 
					adbea7e313 | ||
| 
						 | 
					76962f965e | ||
| 
						 | 
					a4b8c5e46b | ||
| 
						 | 
					83c707439c | ||
| 
						 | 
					25dd6121f4 | ||
| 
						 | 
					67f35ad027 | ||
| 
						 | 
					0c4b8afbc5 | ||
| 
						 | 
					34b30d7ce1 | ||
| 
						 | 
					2215088973 | ||
| 
						 | 
					8b7fb6cdde | ||
| 
						 | 
					94c7dbedf2 | ||
| 
						 | 
					b1dc47a047 | ||
| 
						 | 
					62b1310d97 | ||
| 
						 | 
					0a86916d3a | ||
| 
						 | 
					9907ce57aa | ||
| 
						 | 
					b92626cacc | ||
| 
						 | 
					5a762f0a8e | ||
| 
						 | 
					5dd7a7d804 | ||
| 
						 | 
					7831f40691 | ||
| 
						 | 
					4f4b1ff885 | ||
| 
						 | 
					97901979dd | ||
| 
						 | 
					287316842c | ||
| 
						 | 
					608786e8f3 | ||
| 
						 | 
					9684a35cab | ||
| 
						 | 
					e3e4202954 | ||
| 
						 | 
					23c2054d46 | ||
| 
						 | 
					a20a2a8fa0 | ||
| 
						 | 
					a2896be4a6 | ||
| 
						 | 
					e9220a28d9 | ||
| 
						 | 
					cf12087e21 | ||
| 
						 | 
					00c1b36837 | ||
| 
						 | 
					03e034795d | ||
| 
						 | 
					79c0fafe43 | ||
| 
						 | 
					d499819ba0 | ||
| 
						 | 
					86da917174 | ||
| 
						 | 
					30bd7d6555 | ||
| 
						 | 
					e5a12f0f5f | ||
| 
						 | 
					c85a8434c6 | ||
| 
						 | 
					427a1ca4e5 | ||
| 
						 | 
					22884e173a | ||
| 
						 | 
					d1829308e9 | ||
| 
						 | 
					73840f8721 | ||
| 
						 | 
					c7d1af9805 | ||
| 
						 | 
					4ad26d3dfb | ||
| 
						 | 
					0c70b7670c | ||
| 
						 | 
					f44d044095 | ||
| 
						 | 
					5c1cb13472 | ||
| 
						 | 
					3327fc668e | ||
| 
						 | 
					610945ac54 | ||
| 
						 | 
					ddf5474917 | ||
| 
						 | 
					6ba1685ade | ||
| 
						 | 
					e02b5f7868 | ||
| 
						 | 
					ab2e5d1e7e | ||
| 
						 | 
					f3fef7bfe4 | ||
| 
						 | 
					c34c7838bb | ||
| 
						 | 
					c8a16b0e0c | ||
| 
						 | 
					14f9ed91a1 | ||
| 
						 | 
					7a207d4ccf | ||
| 
						 | 
					92a42d901f | ||
| 
						 | 
					084d89fcce | ||
| 
						 | 
					55b036c071 | ||
| 
						 | 
					30e79310ab | ||
| 
						 | 
					f063fa5054 | ||
| 
						 | 
					7bd901273c | ||
| 
						 | 
					c1e061603b | ||
| 
						 | 
					cb08504fe5 | ||
| 
						 | 
					c0a1fb77be | ||
| 
						 | 
					4864c1112a | ||
| 
						 | 
					9ddeab034b | ||
| 
						 | 
					c4847ed288 | ||
| 
						 | 
					b8f1523fb2 | ||
| 
						 | 
					fb7fa8a6b3 | ||
| 
						 | 
					9c7d359093 | ||
| 
						 | 
					eb54bc1fd7 | ||
| 
						 | 
					d4a0286e13 | ||
| 
						 | 
					83e66767ff | ||
| 
						 | 
					7dc010749b | ||
| 
						 | 
					8e8d013b1b | ||
| 
						 | 
					bba0373808 | ||
| 
						 | 
					1fa318dc8c | ||
| 
						 | 
					6edc5e2037 | ||
| 
						 | 
					1523ed9f78 | ||
| 
						 | 
					8e604d2ab8 | ||
| 
						 | 
					2aba7247a9 | ||
| 
						 | 
					e66fe8533e | ||
| 
						 | 
					b03fbb3917 | ||
| 
						 | 
					c2ece62e4c | ||
| 
						 | 
					8c972dcf34 | ||
| 
						 | 
					50af14f2a3 | ||
| 
						 | 
					e0a356b319 | ||
| 
						 | 
					c09a792958 | ||
| 
						 | 
					0bbfe7f44d | ||
| 
						 | 
					a396abf565 | ||
| 
						 | 
					1e3edb8883 | ||
| 
						 | 
					3b8b61bf35 | ||
| 
						 | 
					6f90456036 | ||
| 
						 | 
					f56fd4e215 | ||
| 
						 | 
					aa35aac5d5 | ||
| 
						 | 
					1f162b819d | ||
| 
						 | 
					52ef1d1cb2 | ||
| 
						 | 
					f14e3a89cc | ||
| 
						 | 
					95d3eac2e0 | ||
| 
						 | 
					8e73536e02 | ||
| 
						 | 
					12a0870bc9 | ||
| 
						 | 
					6ff82c4e86 | ||
| 
						 | 
					c64de35375 | ||
| 
						 | 
					ee5283f4e8 | ||
| 
						 | 
					bd0e954fea | ||
| 
						 | 
					675471a49e | ||
| 
						 | 
					c90e73ccec | ||
| 
						 | 
					a43c1267d8 | ||
| 
						 | 
					e8958c6b5c | ||
| 
						 | 
					e8a3bf82c6 | ||
| 
						 | 
					27fd79176a | ||
| 
						 | 
					28d86a3454 | ||
| 
						 | 
					c6c1a17ae6 | ||
| 
						 | 
					2b47d47215 | ||
| 
						 | 
					0e82df9e10 | ||
| 
						 | 
					893821ad88 | ||
| 
						 | 
					6b80fbfa99 | ||
| 
						 | 
					8c3c7d0194 | ||
| 
						 | 
					b94a3d9f2f | ||
| 
						 | 
					442d0b5ddc | ||
| 
						 | 
					494615d9a0 | ||
| 
						 | 
					afbfb81837 | ||
| 
						 | 
					3ed4e258a3 | ||
| 
						 | 
					dddd41c95b | ||
| 
						 | 
					5f2ca81e86 | ||
| 
						 | 
					c9eac0c438 | ||
| 
						 | 
					b6b34f7612 | ||
| 
						 | 
					e55c413261 | ||
| 
						 | 
					0399cde50a | ||
| 
						 | 
					019eb03823 | ||
| 
						 | 
					363410e1c0 | ||
| 
						 | 
					fc2ef21660 | ||
| 
						 | 
					18cb659ff3 | ||
| 
						 | 
					63231d97ce | ||
| 
						 | 
					9ac81a8a25 | ||
| 
						 | 
					79af2787ae | ||
| 
						 | 
					f5f9b285c0 | ||
| 
						 | 
					6c05f2ae85 | ||
| 
						 | 
					29043e1684 | ||
| 
						 | 
					b73d4a7022 | ||
| 
						 | 
					ad95e8951b | ||
| 
						 | 
					bf591fca12 | ||
| 
						 | 
					dcf027884d | ||
| 
						 | 
					584f3820fe | ||
| 
						 | 
					3c7c46307a | ||
| 
						 | 
					4d80361805 | ||
| 
						 | 
					9a74e19117 | ||
| 
						 | 
					b1e17706a4 | ||
| 
						 | 
					caad129d69 | ||
| 
						 | 
					da58571ce5 | ||
| 
						 | 
					2aa7f1c094 | ||
| 
						 | 
					823e31a91b | ||
| 
						 | 
					fb926ae302 | ||
| 
						 | 
					e0489eeffd | ||
| 
						 | 
					dc9d5a4cac | ||
| 
						 | 
					143743d0b0 | ||
| 
						 | 
					563f0d5ad5 | ||
| 
						 | 
					c99f4a591b | ||
| 
						 | 
					449204e380 | ||
| 
						 | 
					a85c4c6528 | ||
| 
						 | 
					d203a6fff6 | ||
| 
						 | 
					6c612d66d7 | ||
| 
						 | 
					540253a55b | ||
| 
						 | 
					15b7c4ccd1 | ||
| 
						 | 
					442d5335ea | ||
| 
						 | 
					8a80eea597 | ||
| 
						 | 
					5e35703091 | ||
| 
						 | 
					b7ca73f431 | ||
| 
						 | 
					a14fc90f07 | ||
| 
						 | 
					c913f7ec74 | ||
| 
						 | 
					7f6c9e8411 | ||
| 
						 | 
					bb02ea3a20 | ||
| 
						 | 
					3981c9665e | ||
| 
						 | 
					88628fdf3c | ||
| 
						 | 
					0469817781 | ||
| 
						 | 
					a786801141 | ||
| 
						 | 
					ab86732c89 | ||
| 
						 | 
					59622d1688 | ||
| 
						 | 
					58a25a3e2b | ||
| 
						 | 
					15dca29a87 | ||
| 
						 | 
					46980819c0 | ||
| 
						 | 
					4fb6a7268c | ||
| 
						 | 
					c05e963f37 | ||
| 
						 | 
					7f7f625864 | ||
| 
						 | 
					b25aa8295a | ||
| 
						 | 
					15a605765c | ||
| 
						 | 
					b575c95710 | ||
| 
						 | 
					a48a9c858a | ||
| 
						 | 
					0d8d6290a3 | ||
| 
						 | 
					4dcd733ddd | ||
| 
						 | 
					b62835cbeb | ||
| 
						 | 
					6ea740b5ab | ||
| 
						 | 
					7ab98dd5ac | ||
| 
						 | 
					fc8b3400fc | ||
| 
						 | 
					54428ba415 | ||
| 
						 | 
					95d1e69d8e | ||
| 
						 | 
					a0f13ab49f | ||
| 
						 | 
					c3e8405020 | ||
| 
						 | 
					a93593ea66 | ||
| 
						 | 
					23eff70883 | ||
| 
						 | 
					110dd4a8b9 | ||
| 
						 | 
					d9c2bffc9f | ||
| 
						 | 
					049db49dc8 | ||
| 
						 | 
					7c1d2ec61e | ||
| 
						 | 
					a1b2830c06 | ||
| 
						 | 
					82d1d19267 | ||
| 
						 | 
					4d4195c02d | ||
| 
						 | 
					5637a258fc | ||
| 
						 | 
					ee6810f417 | ||
| 
						 | 
					7098248c64 | ||
| 
						 | 
					0d31d356ef | ||
| 
						 | 
					b782e7dcb7 | ||
| 
						 | 
					a4671b4698 | ||
| 
						 | 
					7edd8be169 | ||
| 
						 | 
					24650eefe4 | ||
| 
						 | 
					8e1a44e7eb | ||
| 
						 | 
					2722875190 | ||
| 
						 | 
					3ca6d06f69 | ||
| 
						 | 
					10e47248de | ||
| 
						 | 
					e73ff679ac | ||
| 
						 | 
					53e401fa2d | ||
| 
						 | 
					d2768357da | ||
| 
						 | 
					a6c2ba7c1e | ||
| 
						 | 
					aae5b466fb | ||
| 
						 | 
					2b7be8b949 | ||
| 
						 | 
					b6511a510d | ||
| 
						 | 
					704541aef2 | ||
| 
						 | 
					005560a4c5 | ||
| 
						 | 
					231a5d1853 | ||
| 
						 | 
					9e2b59060d | ||
| 
						 | 
					08ea937f7c | ||
| 
						 | 
					2baedf74d1 | ||
| 
						 | 
					32faa4ced6 | ||
| 
						 | 
					ccdb0b5d13 | ||
| 
						 | 
					8506b672ad | ||
| 
						 | 
					ce2e33bb20 | ||
| 
						 | 
					6707b72260 | ||
| 
						 | 
					5885b8c20d | ||
| 
						 | 
					820710c086 | ||
| 
						 | 
					51cf196bf7 | ||
| 
						 | 
					dadba44cf9 | ||
| 
						 | 
					2ce4a5543b | ||
| 
						 | 
					9112a3a4f5 | ||
| 
						 | 
					24615afda1 | ||
| 
						 | 
					c5778f398b | ||
| 
						 | 
					4eb4097b9b | ||
| 
						 | 
					c512496847 | ||
| 
						 | 
					506961a10d | ||
| 
						 | 
					3414415907 | ||
| 
						 | 
					dc2ae7cfd1 | ||
| 
						 | 
					2e86d21c29 | ||
| 
						 | 
					2654382c43 | ||
| 
						 | 
					9e26b73813 | ||
| 
						 | 
					10cd13bf80 | ||
| 
						 | 
					f10ee5f887 | ||
| 
						 | 
					47cc532d96 | ||
| 
						 | 
					218327f92b | ||
| 
						 | 
					4eae66a1a7 | ||
| 
						 | 
					b09ceeb43c | ||
| 
						 | 
					4fb539c110 | ||
| 
						 | 
					849b284da5 | 
							
								
								
									
										6
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							@@ -12,13 +12,11 @@
 | 
			
		||||
 | 
			
		||||
# Denote all files that are truly binary and should not be modified.
 | 
			
		||||
tools/** binary
 | 
			
		||||
tools/rustup-wrapper/** -binary
 | 
			
		||||
tools/elf-cleaner/** -binary
 | 
			
		||||
*.jar binary
 | 
			
		||||
*.exe binary
 | 
			
		||||
*.apk binary
 | 
			
		||||
*.png binary
 | 
			
		||||
*.jpg binary
 | 
			
		||||
*.ttf binary
 | 
			
		||||
 | 
			
		||||
# Help GitHub detect languages
 | 
			
		||||
native/jni/external/** linguist-vendored
 | 
			
		||||
native/jni/systemproperties/** linguist-language=C++
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										25
									
								
								.github/actions/setup/action.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										25
									
								
								.github/actions/setup/action.yml
									
									
									
									
										vendored
									
									
								
							@@ -26,6 +26,15 @@ runs:
 | 
			
		||||
 | 
			
		||||
    - name: Cache sccache
 | 
			
		||||
      uses: actions/cache@v4
 | 
			
		||||
      if: ${{ github.event_name != 'pull_request' }}
 | 
			
		||||
      with:
 | 
			
		||||
        path: .sccache
 | 
			
		||||
        key: sccache-${{ runner.os }}-${{ github.sha }}
 | 
			
		||||
        restore-keys: sccache-${{ runner.os }}-
 | 
			
		||||
 | 
			
		||||
    - name: Restore sccache
 | 
			
		||||
      uses: actions/cache/restore@v4
 | 
			
		||||
      if: ${{ github.event_name == 'pull_request' }}
 | 
			
		||||
      with:
 | 
			
		||||
        path: .sccache
 | 
			
		||||
        key: sccache-${{ runner.os }}-${{ github.sha }}
 | 
			
		||||
@@ -55,18 +64,18 @@ runs:
 | 
			
		||||
 | 
			
		||||
    - name: Cache Gradle dependencies
 | 
			
		||||
      uses: actions/cache@v4
 | 
			
		||||
      if: inputs.is-asset-build == 'true'
 | 
			
		||||
      if: ${{ inputs.is-asset-build == 'true' && github.event_name != 'pull_request' }}
 | 
			
		||||
      with:
 | 
			
		||||
        path: |
 | 
			
		||||
          .gradle/caches
 | 
			
		||||
          .gradle/wrapper
 | 
			
		||||
          !.gradle/caches/build-cache-*
 | 
			
		||||
        key: gradle-cache-${{ hashFiles('gradle/**') }}
 | 
			
		||||
        key: gradle-cache-${{ hashFiles('app/gradle/**') }}
 | 
			
		||||
        restore-keys: gradle-cache-
 | 
			
		||||
 | 
			
		||||
    - name: Restore Gradle dependencies
 | 
			
		||||
      uses: actions/cache/restore@v4
 | 
			
		||||
      if: inputs.is-asset-build == 'false'
 | 
			
		||||
      if: ${{ inputs.is-asset-build == 'false' || github.event_name == 'pull_request' }}
 | 
			
		||||
      with:
 | 
			
		||||
        path: |
 | 
			
		||||
          .gradle/caches
 | 
			
		||||
@@ -78,19 +87,17 @@ runs:
 | 
			
		||||
 | 
			
		||||
    - name: Cache Gradle build cache
 | 
			
		||||
      uses: actions/cache@v4
 | 
			
		||||
      if: inputs.is-asset-build == 'true'
 | 
			
		||||
      if: ${{ inputs.is-asset-build == 'true' && github.event_name != 'pull_request' }}
 | 
			
		||||
      with:
 | 
			
		||||
        path: |
 | 
			
		||||
          .gradle/caches/build-cache-*
 | 
			
		||||
        path: .gradle/caches/build-cache-*
 | 
			
		||||
        key: gradle-build-cache-${{ github.sha }}
 | 
			
		||||
        restore-keys: gradle-build-cache-
 | 
			
		||||
 | 
			
		||||
    - name: Restore Gradle build cache
 | 
			
		||||
      uses: actions/cache/restore@v4
 | 
			
		||||
      if: inputs.is-asset-build == 'false'
 | 
			
		||||
      if: ${{ inputs.is-asset-build == 'false' || github.event_name == 'pull_request' }}
 | 
			
		||||
      with:
 | 
			
		||||
        path: |
 | 
			
		||||
          .gradle/caches/build-cache-*
 | 
			
		||||
        path: .gradle/caches/build-cache-*
 | 
			
		||||
        key: gradle-build-cache-${{ github.sha }}
 | 
			
		||||
        restore-keys: gradle-build-cache-
 | 
			
		||||
        enableCrossOsArchive: true
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										35
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										35
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							@@ -6,9 +6,7 @@ on:
 | 
			
		||||
    paths:
 | 
			
		||||
      - "app/**"
 | 
			
		||||
      - "native/**"
 | 
			
		||||
      - "buildSrc/**"
 | 
			
		||||
      - "build.py"
 | 
			
		||||
      - "gradle.properties"
 | 
			
		||||
      - ".github/workflows/build.yml"
 | 
			
		||||
  pull_request:
 | 
			
		||||
    branches: [master]
 | 
			
		||||
@@ -17,7 +15,7 @@ on:
 | 
			
		||||
jobs:
 | 
			
		||||
  build:
 | 
			
		||||
    name: Build Magisk artifacts
 | 
			
		||||
    runs-on: macos-14
 | 
			
		||||
    runs-on: macos-15
 | 
			
		||||
    strategy:
 | 
			
		||||
      fail-fast: false
 | 
			
		||||
    steps:
 | 
			
		||||
@@ -38,7 +36,7 @@ jobs:
 | 
			
		||||
        run: ./build.py -v all
 | 
			
		||||
 | 
			
		||||
      - name: Stop gradle daemon
 | 
			
		||||
        run: ./gradlew --stop
 | 
			
		||||
        run: ./app/gradlew --stop
 | 
			
		||||
 | 
			
		||||
      - name: Upload build artifact
 | 
			
		||||
        uses: actions/upload-artifact@v4
 | 
			
		||||
@@ -60,7 +58,7 @@ jobs:
 | 
			
		||||
    strategy:
 | 
			
		||||
      fail-fast: false
 | 
			
		||||
      matrix:
 | 
			
		||||
        os: [windows-latest, ubuntu-latest]
 | 
			
		||||
        os: [windows-2025, ubuntu-24.04]
 | 
			
		||||
    steps:
 | 
			
		||||
      - name: Check out
 | 
			
		||||
        uses: actions/checkout@v4
 | 
			
		||||
@@ -74,20 +72,23 @@ jobs:
 | 
			
		||||
        run: python build.py -v -c .github/ci.prop all
 | 
			
		||||
 | 
			
		||||
      - name: Stop gradle daemon
 | 
			
		||||
        run: ./gradlew --stop
 | 
			
		||||
        run: ./app/gradlew --stop
 | 
			
		||||
 | 
			
		||||
  avd-test:
 | 
			
		||||
    name: Test API ${{ matrix.version }} (x86_64)
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    runs-on: ubuntu-24.04
 | 
			
		||||
    needs: build
 | 
			
		||||
    if: ${{ github.event_name != 'push' }}
 | 
			
		||||
    strategy:
 | 
			
		||||
      fail-fast: false
 | 
			
		||||
      matrix:
 | 
			
		||||
        version: [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35]
 | 
			
		||||
        type: [""]
 | 
			
		||||
        include:
 | 
			
		||||
          - version: "Baklava"
 | 
			
		||||
          - version: 36
 | 
			
		||||
            type: "google_apis"
 | 
			
		||||
          - version: 36
 | 
			
		||||
            type: "google_apis_ps16k"
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - name: Check out
 | 
			
		||||
@@ -109,7 +110,7 @@ jobs:
 | 
			
		||||
        timeout-minutes: 10
 | 
			
		||||
        env:
 | 
			
		||||
          AVD_TEST_LOG: 1
 | 
			
		||||
        run: scripts/avd_test.sh ${{ matrix.version }} ${{ matrix.type }}
 | 
			
		||||
        run: scripts/avd.sh test ${{ matrix.version }} ${{ matrix.type }}
 | 
			
		||||
 | 
			
		||||
      - name: Upload logs on error
 | 
			
		||||
        if: ${{ failure() }}
 | 
			
		||||
@@ -122,8 +123,9 @@ jobs:
 | 
			
		||||
 | 
			
		||||
  avd-test-32:
 | 
			
		||||
    name: Test API ${{ matrix.version }} (x86)
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    runs-on: ubuntu-24.04
 | 
			
		||||
    needs: build
 | 
			
		||||
    if: ${{ github.event_name != 'push' }}
 | 
			
		||||
    strategy:
 | 
			
		||||
      fail-fast: false
 | 
			
		||||
      matrix:
 | 
			
		||||
@@ -150,7 +152,7 @@ jobs:
 | 
			
		||||
        env:
 | 
			
		||||
          FORCE_32_BIT: 1
 | 
			
		||||
          AVD_TEST_LOG: 1
 | 
			
		||||
        run: scripts/avd_test.sh ${{ matrix.version }}
 | 
			
		||||
        run: scripts/avd.sh test ${{ matrix.version }}
 | 
			
		||||
 | 
			
		||||
      - name: Upload logs on error
 | 
			
		||||
        if: ${{ failure() }}
 | 
			
		||||
@@ -161,20 +163,19 @@ jobs:
 | 
			
		||||
            kernel.log
 | 
			
		||||
            logcat.log
 | 
			
		||||
 | 
			
		||||
  cf_test:
 | 
			
		||||
  cf-test:
 | 
			
		||||
    name: Test ${{ matrix.device }}
 | 
			
		||||
    runs-on: ubuntu-24.04
 | 
			
		||||
    needs: build
 | 
			
		||||
    if: ${{ github.event_name != 'push' }}
 | 
			
		||||
    env:
 | 
			
		||||
      CF_HOME: /home/runner/aosp_cf_phone
 | 
			
		||||
    strategy:
 | 
			
		||||
      fail-fast: false
 | 
			
		||||
      matrix:
 | 
			
		||||
        include:
 | 
			
		||||
          - branch: "aosp-main"
 | 
			
		||||
            device: "aosp_cf_x86_64_phone"
 | 
			
		||||
          - branch: "aosp-main-throttled"
 | 
			
		||||
            device: "aosp_cf_x86_64_phone_pgagnostic"
 | 
			
		||||
          - branch: "aosp-android-latest-release"
 | 
			
		||||
            device: "aosp_cf_x86_64_only_phone"
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - name: Check out
 | 
			
		||||
@@ -193,7 +194,7 @@ jobs:
 | 
			
		||||
 | 
			
		||||
      - name: Run Cuttlefish test
 | 
			
		||||
        timeout-minutes: 10
 | 
			
		||||
        run: su $USER -c 'scripts/cuttlefish.sh test'
 | 
			
		||||
        run: sudo -E -u $USER scripts/cuttlefish.sh test
 | 
			
		||||
 | 
			
		||||
      - name: Upload logs on error
 | 
			
		||||
        if: ${{ failure() }}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -2,19 +2,13 @@ out
 | 
			
		||||
*.zip
 | 
			
		||||
*.jks
 | 
			
		||||
*.apk
 | 
			
		||||
*.log
 | 
			
		||||
/config.prop
 | 
			
		||||
/notes.md
 | 
			
		||||
/update.sh
 | 
			
		||||
/app/dict.txt
 | 
			
		||||
 | 
			
		||||
# Built binaries
 | 
			
		||||
native/out
 | 
			
		||||
 | 
			
		||||
# Android Studio / Gradle
 | 
			
		||||
# Android Studio
 | 
			
		||||
*.iml
 | 
			
		||||
.gradle
 | 
			
		||||
.idea
 | 
			
		||||
.kotlin
 | 
			
		||||
/local.properties
 | 
			
		||||
/build
 | 
			
		||||
/captures
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							@@ -4,21 +4,12 @@
 | 
			
		||||
[submodule "lz4"]
 | 
			
		||||
	path = native/src/external/lz4
 | 
			
		||||
	url = https://github.com/lz4/lz4.git
 | 
			
		||||
[submodule "bzip2"]
 | 
			
		||||
	path = native/src/external/bzip2
 | 
			
		||||
	url = https://github.com/nemequ/bzip2.git
 | 
			
		||||
[submodule "xz"]
 | 
			
		||||
	path = native/src/external/xz
 | 
			
		||||
	url = https://github.com/xz-mirror/xz.git
 | 
			
		||||
[submodule "libcxx"]
 | 
			
		||||
	path = native/src/external/libcxx
 | 
			
		||||
	url = https://github.com/topjohnwu/libcxx.git
 | 
			
		||||
[submodule "zlib"]
 | 
			
		||||
	path = native/src/external/zlib
 | 
			
		||||
	url = https://android.googlesource.com/platform/external/zlib
 | 
			
		||||
[submodule "zopfli"]
 | 
			
		||||
	path = native/src/external/zopfli
 | 
			
		||||
	url = https://github.com/google/zopfli.git
 | 
			
		||||
[submodule "cxx-rs"]
 | 
			
		||||
	path = native/src/external/cxx-rs
 | 
			
		||||
	url = https://github.com/topjohnwu/cxx.git
 | 
			
		||||
@@ -31,6 +22,3 @@
 | 
			
		||||
[submodule "crt0"]
 | 
			
		||||
	path = native/src/external/crt0
 | 
			
		||||
	url = https://github.com/topjohnwu/crt0.git
 | 
			
		||||
[submodule "termux-elf-cleaner"]
 | 
			
		||||
	path = tools/termux-elf-cleaner
 | 
			
		||||
	url = https://github.com/termux/termux-elf-cleaner.git
 | 
			
		||||
 
 | 
			
		||||
@@ -16,13 +16,7 @@ Some highlight features:
 | 
			
		||||
 | 
			
		||||
## Downloads
 | 
			
		||||
 | 
			
		||||
[Github](https://github.com/topjohnwu/Magisk/) is the only source where you can get official Magisk information and downloads.
 | 
			
		||||
 | 
			
		||||
Click the icon below to download Magisk apk.
 | 
			
		||||
 | 
			
		||||
[](https://github.com/topjohnwu/Magisk/releases/tag/v27.0)
 | 
			
		||||
[](https://github.com/topjohnwu/Magisk/releases/tag/v28.0)
 | 
			
		||||
[](https://github.com/topjohnwu/Magisk/releases/tag/canary-28003)
 | 
			
		||||
[Github](https://github.com/topjohnwu/Magisk/releases) is the only source where you can get official Magisk information and downloads.
 | 
			
		||||
 | 
			
		||||
## Useful Links
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								app/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
/dict.txt
 | 
			
		||||
 | 
			
		||||
# Gradle
 | 
			
		||||
.gradle
 | 
			
		||||
.kotlin
 | 
			
		||||
/local.properties
 | 
			
		||||
/build
 | 
			
		||||
@@ -35,7 +35,7 @@ android {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dependencies {
 | 
			
		||||
    implementation(project(":app:core"))
 | 
			
		||||
    implementation(project(":core"))
 | 
			
		||||
    coreLibraryDesugaring(libs.jdk.libs)
 | 
			
		||||
 | 
			
		||||
    implementation(libs.indeterminate.checkbox)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,13 @@
 | 
			
		||||
package com.topjohnwu.magisk.arch
 | 
			
		||||
 | 
			
		||||
import android.content.ContentResolver
 | 
			
		||||
import android.view.KeyEvent
 | 
			
		||||
import androidx.databinding.ViewDataBinding
 | 
			
		||||
import androidx.navigation.NavController
 | 
			
		||||
import androidx.navigation.NavDirections
 | 
			
		||||
import androidx.navigation.fragment.NavHostFragment
 | 
			
		||||
import androidx.navigation.navOptions
 | 
			
		||||
import com.topjohnwu.magisk.utils.AccessibilityUtils
 | 
			
		||||
 | 
			
		||||
abstract class NavigationActivity<Binding : ViewDataBinding> : UIActivity<Binding>() {
 | 
			
		||||
 | 
			
		||||
@@ -31,7 +34,17 @@ abstract class NavigationActivity<Binding : ViewDataBinding> : UIActivity<Bindin
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        fun navigate(directions: NavDirections, navigation: NavController, cr: ContentResolver) {
 | 
			
		||||
            if (AccessibilityUtils.isAnimationEnabled(cr)) {
 | 
			
		||||
                navigation.navigate(directions)
 | 
			
		||||
            } else {
 | 
			
		||||
                navigation.navigate(directions, navOptions {})
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun NavDirections.navigate() {
 | 
			
		||||
        navigation.navigate(this)
 | 
			
		||||
        navigate(this, navigation, contentResolver)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,6 @@ package com.topjohnwu.magisk.dialog
 | 
			
		||||
import com.topjohnwu.magisk.core.AppContext
 | 
			
		||||
import com.topjohnwu.magisk.core.Info
 | 
			
		||||
import com.topjohnwu.magisk.core.R
 | 
			
		||||
import com.topjohnwu.magisk.core.di.ServiceLocator
 | 
			
		||||
import com.topjohnwu.magisk.core.download.DownloadEngine
 | 
			
		||||
import com.topjohnwu.magisk.core.download.Subject
 | 
			
		||||
import com.topjohnwu.magisk.view.MagiskDialog
 | 
			
		||||
@@ -11,15 +10,10 @@ import java.io.File
 | 
			
		||||
 | 
			
		||||
class ManagerInstallDialog : MarkDownDialog() {
 | 
			
		||||
 | 
			
		||||
    private val svc get() = ServiceLocator.networkService
 | 
			
		||||
 | 
			
		||||
    override suspend fun getMarkdownText(): String {
 | 
			
		||||
        val text = svc.fetchString(Info.remote.magisk.note)
 | 
			
		||||
        val text = Info.update.note
 | 
			
		||||
        // Cache the changelog
 | 
			
		||||
        AppContext.cacheDir.listFiles { _, name -> name.endsWith(".md") }.orEmpty().forEach {
 | 
			
		||||
            it.delete()
 | 
			
		||||
        }
 | 
			
		||||
        File(AppContext.cacheDir, "${Info.remote.magisk.versionCode}.md").writeText(text)
 | 
			
		||||
        File(AppContext.cacheDir, "${Info.update.versionCode}.md").writeText(text)
 | 
			
		||||
        return text
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,8 @@ import com.topjohnwu.magisk.core.Info
 | 
			
		||||
import com.topjohnwu.magisk.core.download.DownloadEngine
 | 
			
		||||
import com.topjohnwu.magisk.databinding.FragmentHomeMd2Binding
 | 
			
		||||
import com.topjohnwu.magisk.core.R as CoreR
 | 
			
		||||
import androidx.navigation.findNavController
 | 
			
		||||
import com.topjohnwu.magisk.arch.NavigationActivity
 | 
			
		||||
 | 
			
		||||
class HomeFragment : BaseFragment<FragmentHomeMd2Binding>(), MenuProvider {
 | 
			
		||||
 | 
			
		||||
@@ -68,7 +70,13 @@ class HomeFragment : BaseFragment<FragmentHomeMd2Binding>(), MenuProvider {
 | 
			
		||||
    override fun onMenuItemSelected(item: MenuItem): Boolean {
 | 
			
		||||
        when (item.itemId) {
 | 
			
		||||
            R.id.action_settings ->
 | 
			
		||||
                HomeFragmentDirections.actionHomeFragmentToSettingsFragment().navigate()
 | 
			
		||||
                activity?.let {
 | 
			
		||||
                    NavigationActivity.navigate(
 | 
			
		||||
                        HomeFragmentDirections.actionHomeFragmentToSettingsFragment(),
 | 
			
		||||
                        it.findNavController(R.id.main_nav_host),
 | 
			
		||||
                        it.contentResolver,
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
            R.id.action_reboot -> activity?.let { RebootMenu.inflate(it).show() }
 | 
			
		||||
            else -> return super.onOptionsItemSelected(item)
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -91,16 +91,15 @@ class HomeViewModel(
 | 
			
		||||
 | 
			
		||||
    override suspend fun doLoadWork() {
 | 
			
		||||
        appState = State.LOADING
 | 
			
		||||
        Info.getRemote(svc)?.apply {
 | 
			
		||||
        Info.fetchUpdate(svc)?.apply {
 | 
			
		||||
            appState = when {
 | 
			
		||||
                BuildConfig.APP_VERSION_CODE < magisk.versionCode -> State.OUTDATED
 | 
			
		||||
                BuildConfig.APP_VERSION_CODE < versionCode -> State.OUTDATED
 | 
			
		||||
                else -> State.UP_TO_DATE
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            val isDebug = Config.updateChannel == Config.Value.DEBUG_CHANNEL
 | 
			
		||||
            managerRemoteVersion =
 | 
			
		||||
                ("${magisk.version} (${magisk.versionCode})" +
 | 
			
		||||
                    if (isDebug) " (D)" else "").asText()
 | 
			
		||||
                ("$version (${versionCode})" + if (isDebug) " (D)" else "").asText()
 | 
			
		||||
        } ?: run {
 | 
			
		||||
            appState = State.INVALID
 | 
			
		||||
            managerRemoteVersion = CoreR.string.not_available.asText()
 | 
			
		||||
 
 | 
			
		||||
@@ -41,7 +41,7 @@ object RebootMenu {
 | 
			
		||||
            activity.getSystemService<PowerManager>()?.isRebootingUserspaceSupported == true) {
 | 
			
		||||
            menu.menu.findItem(R.id.action_reboot_userspace).isVisible = true
 | 
			
		||||
        }
 | 
			
		||||
        if (Const.Version.isCanary()) {
 | 
			
		||||
        if (Const.Version.atLeast_28_0()) {
 | 
			
		||||
            menu.menu.findItem(R.id.action_reboot_safe_mode).isChecked = Config.bootloop >= 2
 | 
			
		||||
        } else {
 | 
			
		||||
            menu.menu.findItem(R.id.action_reboot_safe_mode).isVisible = false
 | 
			
		||||
 
 | 
			
		||||
@@ -14,9 +14,8 @@ import com.topjohnwu.magisk.BR
 | 
			
		||||
import com.topjohnwu.magisk.R
 | 
			
		||||
import com.topjohnwu.magisk.arch.BaseViewModel
 | 
			
		||||
import com.topjohnwu.magisk.core.AppContext
 | 
			
		||||
import com.topjohnwu.magisk.core.BuildConfig
 | 
			
		||||
import com.topjohnwu.magisk.core.BuildConfig.APP_VERSION_CODE
 | 
			
		||||
import com.topjohnwu.magisk.core.Config
 | 
			
		||||
import com.topjohnwu.magisk.core.Const
 | 
			
		||||
import com.topjohnwu.magisk.core.Info
 | 
			
		||||
import com.topjohnwu.magisk.core.base.ContentResultCallback
 | 
			
		||||
import com.topjohnwu.magisk.core.ktx.toast
 | 
			
		||||
@@ -70,17 +69,16 @@ class InstallViewModel(svc: NetworkService, markwon: Markwon) : BaseViewModel()
 | 
			
		||||
    init {
 | 
			
		||||
        viewModelScope.launch(Dispatchers.IO) {
 | 
			
		||||
            try {
 | 
			
		||||
                val file = File(AppContext.cacheDir, "${BuildConfig.APP_VERSION_CODE}.md")
 | 
			
		||||
                val text = when {
 | 
			
		||||
                    file.exists() -> file.readText()
 | 
			
		||||
                    Const.Url.CHANGELOG_URL.isEmpty() -> ""
 | 
			
		||||
                val noteFile = File(AppContext.cacheDir, "${APP_VERSION_CODE}.md")
 | 
			
		||||
                val noteText = when {
 | 
			
		||||
                    noteFile.exists() -> noteFile.readText()
 | 
			
		||||
                    else -> {
 | 
			
		||||
                        val str = svc.fetchString(Const.Url.CHANGELOG_URL)
 | 
			
		||||
                        file.writeText(str)
 | 
			
		||||
                        str
 | 
			
		||||
                        val note = svc.fetchUpdate(APP_VERSION_CODE).note
 | 
			
		||||
                        noteFile.writeText(note)
 | 
			
		||||
                        note
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                val spanned = markwon.toMarkdown(text)
 | 
			
		||||
                val spanned = markwon.toMarkdown(noteText)
 | 
			
		||||
                withContext(Dispatchers.Main) {
 | 
			
		||||
                    notes = spanned
 | 
			
		||||
                }
 | 
			
		||||
@@ -100,13 +98,15 @@ class InstallViewModel(svc: NetworkService, markwon: Markwon) : BaseViewModel()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onSaveState(state: Bundle) {
 | 
			
		||||
        state.putParcelable(INSTALL_STATE_KEY, InstallState(
 | 
			
		||||
            methodId,
 | 
			
		||||
            step,
 | 
			
		||||
            Config.keepVerity,
 | 
			
		||||
            Config.keepEnc,
 | 
			
		||||
            Config.recovery
 | 
			
		||||
        ))
 | 
			
		||||
        state.putParcelable(
 | 
			
		||||
            INSTALL_STATE_KEY, InstallState(
 | 
			
		||||
                methodId,
 | 
			
		||||
                step,
 | 
			
		||||
                Config.keepVerity,
 | 
			
		||||
                Config.keepEnc,
 | 
			
		||||
                Config.recovery
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onRestoreState(state: Bundle) {
 | 
			
		||||
@@ -124,6 +124,7 @@ class InstallViewModel(svc: NetworkService, markwon: Markwon) : BaseViewModel()
 | 
			
		||||
        override fun onActivityLaunch() {
 | 
			
		||||
            AppContext.toast(CoreR.string.patch_file_msg, Toast.LENGTH_LONG)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        override fun onActivityResult(result: Uri) {
 | 
			
		||||
            uri.value = result
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@ import android.view.Menu
 | 
			
		||||
import android.view.MenuInflater
 | 
			
		||||
import android.view.MenuItem
 | 
			
		||||
import android.view.View
 | 
			
		||||
import android.widget.HorizontalScrollView
 | 
			
		||||
import androidx.core.view.MenuProvider
 | 
			
		||||
import androidx.core.view.isVisible
 | 
			
		||||
import com.topjohnwu.magisk.R
 | 
			
		||||
@@ -12,6 +13,7 @@ import com.topjohnwu.magisk.arch.BaseFragment
 | 
			
		||||
import com.topjohnwu.magisk.arch.viewModel
 | 
			
		||||
import com.topjohnwu.magisk.databinding.FragmentLogMd2Binding
 | 
			
		||||
import com.topjohnwu.magisk.ui.MainActivity
 | 
			
		||||
import com.topjohnwu.magisk.utils.AccessibilityUtils
 | 
			
		||||
import com.topjohnwu.magisk.utils.MotionRevealHelper
 | 
			
		||||
import rikka.recyclerview.addEdgeSpacing
 | 
			
		||||
import rikka.recyclerview.addItemSpacing
 | 
			
		||||
@@ -56,6 +58,11 @@ class LogFragment : BaseFragment<FragmentLogMd2Binding>(), MenuProvider {
 | 
			
		||||
            addItemSpacing(R.dimen.l1, R.dimen.l_50, R.dimen.l1)
 | 
			
		||||
            fixEdgeEffect()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!AccessibilityUtils.isAnimationEnabled(requireContext().contentResolver)) {
 | 
			
		||||
            val scrollView = view.findViewById<HorizontalScrollView>(R.id.log_scroll_magisk)
 | 
			
		||||
            scrollView.setOverScrollMode(View.OVER_SCROLL_NEVER)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -147,19 +147,11 @@ object UpdateChannel : BaseSettingsItem.Selector() {
 | 
			
		||||
        get() = Config.updateChannel
 | 
			
		||||
        set(value) {
 | 
			
		||||
            Config.updateChannel = value
 | 
			
		||||
            Info.remote = Info.EMPTY_REMOTE
 | 
			
		||||
            Info.resetUpdate()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    override val title = CoreR.string.settings_update_channel_title.asText()
 | 
			
		||||
 | 
			
		||||
    override val entryRes = CoreR.array.update_channel
 | 
			
		||||
    override fun entries(res: Resources): Array<String> {
 | 
			
		||||
        return super.entries(res).let {
 | 
			
		||||
            if (!Const.APP_IS_CANARY && !BuildConfig.DEBUG)
 | 
			
		||||
                it.copyOfRange(0, Config.Value.CANARY_CHANNEL)
 | 
			
		||||
            else it
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
object UpdateChannelUrl : BaseSettingsItem.Input() {
 | 
			
		||||
@@ -169,7 +161,7 @@ object UpdateChannelUrl : BaseSettingsItem.Input() {
 | 
			
		||||
        get() = Config.customChannelUrl
 | 
			
		||||
        set(value) {
 | 
			
		||||
            Config.customChannelUrl = value
 | 
			
		||||
            Info.remote = Info.EMPTY_REMOTE
 | 
			
		||||
            Info.resetUpdate()
 | 
			
		||||
            notifyPropertyChanged(BR.description)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,7 @@ import com.topjohnwu.magisk.BR
 | 
			
		||||
import com.topjohnwu.magisk.arch.BaseViewModel
 | 
			
		||||
import com.topjohnwu.magisk.core.AppContext
 | 
			
		||||
import com.topjohnwu.magisk.core.BuildConfig
 | 
			
		||||
import com.topjohnwu.magisk.core.Config
 | 
			
		||||
import com.topjohnwu.magisk.core.Const
 | 
			
		||||
import com.topjohnwu.magisk.core.Info
 | 
			
		||||
import com.topjohnwu.magisk.core.R
 | 
			
		||||
@@ -92,7 +93,7 @@ class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Handler {
 | 
			
		||||
            DownloadPath -> withExternalRW(doAction)
 | 
			
		||||
            UpdateChecker -> withPostNotificationPermission(doAction)
 | 
			
		||||
            Authentication -> AuthEvent(doAction).publish()
 | 
			
		||||
            Hide, Restore -> withInstallPermission(doAction)
 | 
			
		||||
            AutomaticResponse -> if (Config.suAuth) AuthEvent(doAction).publish() else doAction()
 | 
			
		||||
            else -> doAction()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,14 @@
 | 
			
		||||
package com.topjohnwu.magisk.utils
 | 
			
		||||
 | 
			
		||||
import android.content.ContentResolver
 | 
			
		||||
import android.provider.Settings
 | 
			
		||||
 | 
			
		||||
class AccessibilityUtils {
 | 
			
		||||
    companion object {
 | 
			
		||||
        fun isAnimationEnabled(cr: ContentResolver): Boolean {
 | 
			
		||||
            return !(Settings.Global.getFloat(cr, Settings.Global.ANIMATOR_DURATION_SCALE, 1.0f) == 0.0f
 | 
			
		||||
                && Settings.Global.getFloat(cr, Settings.Global.TRANSITION_ANIMATION_SCALE, 1.0f) == 0.0f
 | 
			
		||||
                && Settings.Global.getFloat(cr, Settings.Global.WINDOW_ANIMATION_SCALE, 1.0f) == 0.0f)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -16,6 +16,7 @@
 | 
			
		||||
        android:layout_height="match_parent">
 | 
			
		||||
 | 
			
		||||
        <HorizontalScrollView
 | 
			
		||||
            android:id="@+id/log_scroll_magisk"
 | 
			
		||||
            gone="@{viewModel.loading}"
 | 
			
		||||
            android:layout_width="match_parent"
 | 
			
		||||
            android:layout_height="match_parent"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,11 @@
 | 
			
		||||
tasks.register("clean") {
 | 
			
		||||
plugins {
 | 
			
		||||
    id("MagiskPlugin")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
tasks.register("clean", Delete::class) {
 | 
			
		||||
    delete(rootProject.layout.buildDirectory)
 | 
			
		||||
 | 
			
		||||
    subprojects.forEach {
 | 
			
		||||
        dependsOn(":app:${it.name}:clean")
 | 
			
		||||
        dependsOn(":${it.name}:clean")
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -30,5 +30,6 @@ dependencies {
 | 
			
		||||
    implementation(libs.ksp.plugin)
 | 
			
		||||
    implementation(libs.navigation.safe.args.plugin)
 | 
			
		||||
    implementation(libs.lsparanoid.plugin)
 | 
			
		||||
    implementation(libs.moshi.plugin)
 | 
			
		||||
    implementation(libs.jgit)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										77
									
								
								app/buildSrc/src/main/java/AddCommentTask.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								app/buildSrc/src/main/java/AddCommentTask.kt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,77 @@
 | 
			
		||||
import com.android.build.api.artifact.ArtifactTransformationRequest
 | 
			
		||||
import com.android.build.api.dsl.ApkSigningConfig
 | 
			
		||||
import com.android.builder.internal.packaging.IncrementalPackager
 | 
			
		||||
import com.android.tools.build.apkzlib.sign.SigningExtension
 | 
			
		||||
import com.android.tools.build.apkzlib.sign.SigningOptions
 | 
			
		||||
import com.android.tools.build.apkzlib.zfile.ZFiles
 | 
			
		||||
import com.android.tools.build.apkzlib.zip.ZFileOptions
 | 
			
		||||
import org.gradle.api.DefaultTask
 | 
			
		||||
import org.gradle.api.file.DirectoryProperty
 | 
			
		||||
import org.gradle.api.provider.Property
 | 
			
		||||
import org.gradle.api.tasks.Input
 | 
			
		||||
import org.gradle.api.tasks.InputFiles
 | 
			
		||||
import org.gradle.api.tasks.Internal
 | 
			
		||||
import org.gradle.api.tasks.OutputDirectory
 | 
			
		||||
import org.gradle.api.tasks.TaskAction
 | 
			
		||||
import java.io.File
 | 
			
		||||
import java.security.KeyStore
 | 
			
		||||
import java.security.cert.X509Certificate
 | 
			
		||||
import java.util.jar.JarFile
 | 
			
		||||
 | 
			
		||||
abstract class AddCommentTask: DefaultTask() {
 | 
			
		||||
    @get:Input
 | 
			
		||||
    abstract val comment: Property<String>
 | 
			
		||||
 | 
			
		||||
    @get:Input
 | 
			
		||||
    abstract val signingConfig: Property<ApkSigningConfig>
 | 
			
		||||
 | 
			
		||||
    @get:InputFiles
 | 
			
		||||
    abstract val apkFolder: DirectoryProperty
 | 
			
		||||
 | 
			
		||||
    @get:OutputDirectory
 | 
			
		||||
    abstract val outFolder: DirectoryProperty
 | 
			
		||||
 | 
			
		||||
    @get:Internal
 | 
			
		||||
    abstract val transformationRequest: Property<ArtifactTransformationRequest<AddCommentTask>>
 | 
			
		||||
 | 
			
		||||
    @TaskAction
 | 
			
		||||
    fun taskAction() = transformationRequest.get().submit(this) { artifact ->
 | 
			
		||||
        val inFile = File(artifact.outputFile)
 | 
			
		||||
        val outFile = outFolder.file(inFile.name).get().asFile
 | 
			
		||||
 | 
			
		||||
        val privateKey = signingConfig.get().getPrivateKey()
 | 
			
		||||
        val signingOptions = SigningOptions.builder()
 | 
			
		||||
            .setMinSdkVersion(0)
 | 
			
		||||
            .setV1SigningEnabled(true)
 | 
			
		||||
            .setV2SigningEnabled(true)
 | 
			
		||||
            .setKey(privateKey.privateKey)
 | 
			
		||||
            .setCertificates(privateKey.certificate as X509Certificate)
 | 
			
		||||
            .setValidation(SigningOptions.Validation.ASSUME_INVALID)
 | 
			
		||||
            .build()
 | 
			
		||||
        val options = ZFileOptions().apply {
 | 
			
		||||
            noTimestamps = true
 | 
			
		||||
            autoSortFiles = true
 | 
			
		||||
        }
 | 
			
		||||
        outFile.parentFile?.mkdirs()
 | 
			
		||||
        inFile.copyTo(outFile, overwrite = true)
 | 
			
		||||
        ZFiles.apk(outFile, options).use {
 | 
			
		||||
            SigningExtension(signingOptions).register(it)
 | 
			
		||||
            it.eocdComment = comment.get().toByteArray()
 | 
			
		||||
            it.get(IncrementalPackager.APP_METADATA_ENTRY_PATH)?.delete()
 | 
			
		||||
            it.get(IncrementalPackager.VERSION_CONTROL_INFO_ENTRY_PATH)?.delete()
 | 
			
		||||
            it.get(JarFile.MANIFEST_NAME)?.delete()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        outFile
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun ApkSigningConfig.getPrivateKey(): KeyStore.PrivateKeyEntry {
 | 
			
		||||
        val keyStore = KeyStore.getInstance(storeType ?: KeyStore.getDefaultType())
 | 
			
		||||
        storeFile!!.inputStream().use {
 | 
			
		||||
            keyStore.load(it, storePassword!!.toCharArray())
 | 
			
		||||
        }
 | 
			
		||||
        val keyPwdArray = keyPassword!!.toCharArray()
 | 
			
		||||
        val entry = keyStore.getEntry(keyAlias!!, KeyStore.PasswordProtection(keyPwdArray))
 | 
			
		||||
        return entry as KeyStore.PrivateKeyEntry
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -7,8 +7,10 @@ import org.objectweb.asm.MethodVisitor
 | 
			
		||||
import org.objectweb.asm.Opcodes
 | 
			
		||||
import org.objectweb.asm.Opcodes.ASM9
 | 
			
		||||
 | 
			
		||||
private const val ZIP_ENTRY_CLASS_NAME = "java.util.zip.ZipEntry"
 | 
			
		||||
private const val DESUGAR_CLASS_NAME = "com.topjohnwu.magisk.core.utils.Desugar"
 | 
			
		||||
private const val ZIP_ENTRY_CLASS_NAME = "java.util.zip.ZipEntry"
 | 
			
		||||
private const val ZIP_OUT_STREAM_CLASS_NAME = "org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream"
 | 
			
		||||
private const val ZIP_UTIL_CLASS_NAME = "org/apache/commons/compress/archivers/zip/ZipUtil"
 | 
			
		||||
private const val ZIP_ENTRY_GET_TIME_DESC = "()Ljava/nio/file/attribute/FileTime;"
 | 
			
		||||
private const val DESUGAR_GET_TIME_DESC =
 | 
			
		||||
    "(Ljava/util/zip/ZipEntry;)Ljava/nio/file/attribute/FileTime;"
 | 
			
		||||
@@ -20,27 +22,29 @@ abstract class DesugarClassVisitorFactory : AsmClassVisitorFactory<Instrumentati
 | 
			
		||||
        classContext: ClassContext,
 | 
			
		||||
        nextClassVisitor: ClassVisitor
 | 
			
		||||
    ): ClassVisitor {
 | 
			
		||||
        return DesugarClassVisitor(classContext, nextClassVisitor)
 | 
			
		||||
        return if (classContext.currentClassData.className == ZIP_OUT_STREAM_CLASS_NAME) {
 | 
			
		||||
            ZipEntryPatcher(classContext, ZipOutputStreamPatcher(nextClassVisitor))
 | 
			
		||||
        } else {
 | 
			
		||||
            ZipEntryPatcher(classContext, nextClassVisitor)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun isInstrumentable(classData: ClassData) = classData.className != DESUGAR_CLASS_NAME
 | 
			
		||||
 | 
			
		||||
    class DesugarClassVisitor(private val classContext: ClassContext, cv: ClassVisitor) :
 | 
			
		||||
        ClassVisitor(ASM9, cv) {
 | 
			
		||||
    // Patch ALL references to ZipEntry#getXXXTime
 | 
			
		||||
    class ZipEntryPatcher(
 | 
			
		||||
        private val classContext: ClassContext,
 | 
			
		||||
        cv: ClassVisitor
 | 
			
		||||
    ) : ClassVisitor(ASM9, cv) {
 | 
			
		||||
        override fun visitMethod(
 | 
			
		||||
            access: Int,
 | 
			
		||||
            name: String?,
 | 
			
		||||
            descriptor: String?,
 | 
			
		||||
            signature: String?,
 | 
			
		||||
            exceptions: Array<out String>?
 | 
			
		||||
        ): MethodVisitor {
 | 
			
		||||
            return DesugarMethodVisitor(
 | 
			
		||||
                super.visitMethod(access, name, descriptor, signature, exceptions)
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
        ) = MethodPatcher(super.visitMethod(access, name, descriptor, signature, exceptions))
 | 
			
		||||
 | 
			
		||||
        inner class DesugarMethodVisitor(mv: MethodVisitor?) :
 | 
			
		||||
            MethodVisitor(ASM9, mv) {
 | 
			
		||||
        inner class MethodPatcher(mv: MethodVisitor?) : MethodVisitor(ASM9, mv) {
 | 
			
		||||
            override fun visitMethodInsn(
 | 
			
		||||
                opcode: Int,
 | 
			
		||||
                owner: String,
 | 
			
		||||
@@ -75,4 +79,44 @@ abstract class DesugarClassVisitorFactory : AsmClassVisitorFactory<Instrumentati
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Patch ZipArchiveOutputStream#copyFromZipInputStream
 | 
			
		||||
    class ZipOutputStreamPatcher(cv: ClassVisitor) : ClassVisitor(ASM9, cv) {
 | 
			
		||||
        override fun visitMethod(
 | 
			
		||||
            access: Int,
 | 
			
		||||
            name: String,
 | 
			
		||||
            descriptor: String,
 | 
			
		||||
            signature: String?,
 | 
			
		||||
            exceptions: Array<out String?>?
 | 
			
		||||
        ): MethodVisitor? {
 | 
			
		||||
            return if (name == "copyFromZipInputStream") {
 | 
			
		||||
                MethodPatcher(super.visitMethod(access, name, descriptor, signature, exceptions))
 | 
			
		||||
            } else {
 | 
			
		||||
                super.visitMethod(access, name, descriptor, signature, exceptions)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        class MethodPatcher(mv: MethodVisitor?) : MethodVisitor(ASM9, mv) {
 | 
			
		||||
            override fun visitMethodInsn(
 | 
			
		||||
                opcode: Int,
 | 
			
		||||
                owner: String,
 | 
			
		||||
                name: String,
 | 
			
		||||
                descriptor: String?,
 | 
			
		||||
                isInterface: Boolean
 | 
			
		||||
            ) {
 | 
			
		||||
                if (owner == ZIP_UTIL_CLASS_NAME && name == "checkRequestedFeatures") {
 | 
			
		||||
                    // Redirect
 | 
			
		||||
                    mv.visitMethodInsn(
 | 
			
		||||
                        Opcodes.INVOKESTATIC,
 | 
			
		||||
                        DESUGAR_CLASS_NAME.replace('.', '/'),
 | 
			
		||||
                        name,
 | 
			
		||||
                        descriptor,
 | 
			
		||||
                        false
 | 
			
		||||
                    )
 | 
			
		||||
                } else {
 | 
			
		||||
                    super.visitMethodInsn(opcode, owner, name, descriptor, isInterface)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -5,6 +5,12 @@ import org.gradle.api.Project
 | 
			
		||||
import org.gradle.kotlin.dsl.provideDelegate
 | 
			
		||||
import java.io.File
 | 
			
		||||
import java.util.Properties
 | 
			
		||||
import java.util.Random
 | 
			
		||||
 | 
			
		||||
// Set non-zero value here to fix the random seed for reproducible builds
 | 
			
		||||
// CI builds are always reproducible
 | 
			
		||||
val RAND_SEED = if (System.getenv("CI") != null) 42 else 0
 | 
			
		||||
lateinit var RANDOM: Random
 | 
			
		||||
 | 
			
		||||
private val props = Properties()
 | 
			
		||||
private var commitHash = ""
 | 
			
		||||
@@ -14,7 +20,7 @@ private val defaultAbis = setOf("armeabi-v7a", "x86", "arm64-v8a", "x86_64")
 | 
			
		||||
object Config {
 | 
			
		||||
    operator fun get(key: String): String? {
 | 
			
		||||
        val v = props[key] as? String ?: return null
 | 
			
		||||
        return if (v.isBlank()) null else v
 | 
			
		||||
        return v.ifBlank { null }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun contains(key: String) = get(key) != null
 | 
			
		||||
@@ -28,19 +34,25 @@ object Config {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fun Project.rootFile(path: String): File {
 | 
			
		||||
    val file = File(path)
 | 
			
		||||
    return if (file.isAbsolute) file
 | 
			
		||||
    else File(rootProject.file(".."), path)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class MagiskPlugin : Plugin<Project> {
 | 
			
		||||
    override fun apply(project: Project) = project.applyPlugin()
 | 
			
		||||
 | 
			
		||||
    private fun Project.applyPlugin() {
 | 
			
		||||
        initRandom(rootProject.file("app/dict.txt"))
 | 
			
		||||
        initRandom(rootProject.file("dict.txt"))
 | 
			
		||||
        props.clear()
 | 
			
		||||
        rootProject.file("gradle.properties").inputStream().use { props.load(it) }
 | 
			
		||||
        val configPath: String? by this
 | 
			
		||||
        val config = configPath?.let { File(it) } ?: rootProject.file("config.prop")
 | 
			
		||||
        val config = rootFile(configPath ?: "config.prop")
 | 
			
		||||
        if (config.exists())
 | 
			
		||||
            config.inputStream().use { props.load(it) }
 | 
			
		||||
 | 
			
		||||
        val repo = FileRepository(rootProject.file(".git"))
 | 
			
		||||
        val repo = FileRepository(rootFile(".git"))
 | 
			
		||||
        val refId = repo.refDatabase.exactRef("HEAD").objectId
 | 
			
		||||
        commitHash = repo.newObjectReader().abbreviate(refId, 8).name()
 | 
			
		||||
    }
 | 
			
		||||
							
								
								
									
										330
									
								
								app/buildSrc/src/main/java/Setup.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										330
									
								
								app/buildSrc/src/main/java/Setup.kt
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,8 +1,11 @@
 | 
			
		||||
import com.android.build.api.artifact.SingleArtifact
 | 
			
		||||
import org.gradle.api.DefaultTask
 | 
			
		||||
import org.gradle.api.Project
 | 
			
		||||
import org.gradle.api.file.DirectoryProperty
 | 
			
		||||
import org.gradle.api.file.RegularFileProperty
 | 
			
		||||
import org.gradle.api.provider.Property
 | 
			
		||||
import org.gradle.api.tasks.CacheableTask
 | 
			
		||||
import org.gradle.api.tasks.Delete
 | 
			
		||||
import org.gradle.api.tasks.Input
 | 
			
		||||
import org.gradle.api.tasks.InputFile
 | 
			
		||||
import org.gradle.api.tasks.InputFiles
 | 
			
		||||
@@ -10,22 +13,25 @@ import org.gradle.api.tasks.OutputFile
 | 
			
		||||
import org.gradle.api.tasks.PathSensitive
 | 
			
		||||
import org.gradle.api.tasks.PathSensitivity
 | 
			
		||||
import org.gradle.api.tasks.TaskAction
 | 
			
		||||
import org.gradle.kotlin.dsl.assign
 | 
			
		||||
import org.gradle.kotlin.dsl.named
 | 
			
		||||
import java.io.ByteArrayInputStream
 | 
			
		||||
import java.io.ByteArrayOutputStream
 | 
			
		||||
import java.io.File
 | 
			
		||||
import java.io.PrintStream
 | 
			
		||||
import java.security.SecureRandom
 | 
			
		||||
import java.util.Random
 | 
			
		||||
import java.util.zip.Deflater
 | 
			
		||||
import java.util.zip.DeflaterOutputStream
 | 
			
		||||
import java.util.zip.ZipEntry
 | 
			
		||||
import java.util.zip.ZipFile
 | 
			
		||||
import java.util.zip.ZipOutputStream
 | 
			
		||||
import javax.crypto.Cipher
 | 
			
		||||
import javax.crypto.CipherOutputStream
 | 
			
		||||
import javax.crypto.spec.IvParameterSpec
 | 
			
		||||
import javax.crypto.spec.SecretKeySpec
 | 
			
		||||
import kotlin.random.asKotlinRandom
 | 
			
		||||
 | 
			
		||||
// Set non-zero value here to fix the random seed for reproducible builds
 | 
			
		||||
// CI builds are always reproducible
 | 
			
		||||
val RAND_SEED = if (System.getenv("CI") != null) 42 else 0
 | 
			
		||||
private lateinit var RANDOM: Random
 | 
			
		||||
private val kRANDOM get() = RANDOM.asKotlinRandom()
 | 
			
		||||
 | 
			
		||||
private val c1 = mutableListOf<String>()
 | 
			
		||||
@@ -72,7 +78,7 @@ private fun PrintStream.byteField(name: String, bytes: ByteArray) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@CacheableTask
 | 
			
		||||
abstract class ManifestUpdater: DefaultTask() {
 | 
			
		||||
private abstract class ManifestUpdater: DefaultTask() {
 | 
			
		||||
    @get:Input
 | 
			
		||||
    abstract val applicationId: Property<String>
 | 
			
		||||
 | 
			
		||||
@@ -182,9 +188,7 @@ abstract class ManifestUpdater: DefaultTask() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
fun genStubClasses(factoryOutDir: File, appOutDir: File) {
 | 
			
		||||
    fun String.ind(level: Int) = replaceIndentByMargin("    ".repeat(level))
 | 
			
		||||
 | 
			
		||||
private fun genStubClasses(factoryOutDir: File, appOutDir: File) {
 | 
			
		||||
    val classNameGenerator = sequence {
 | 
			
		||||
        fun notJavaKeyword(name: String) = when (name) {
 | 
			
		||||
            "do", "if", "for", "int", "new", "try" -> false
 | 
			
		||||
@@ -228,7 +232,7 @@ fun genStubClasses(factoryOutDir: File, appOutDir: File) {
 | 
			
		||||
    genClass("StubApplication", appOutDir)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fun genEncryptedResources(res: ByteArray, outDir: File) {
 | 
			
		||||
private fun genEncryptedResources(res: ByteArray, outDir: File) {
 | 
			
		||||
    val mainPkgDir = File(outDir, "com/topjohnwu/magisk")
 | 
			
		||||
    mainPkgDir.mkdirs()
 | 
			
		||||
 | 
			
		||||
@@ -259,3 +263,86 @@ fun genEncryptedResources(res: ByteArray, outDir: File) {
 | 
			
		||||
        it.println("}")
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fun Project.setupStubApk() {
 | 
			
		||||
    setupAppCommon()
 | 
			
		||||
 | 
			
		||||
    androidComponents.onVariants { variant ->
 | 
			
		||||
        val variantName = variant.name
 | 
			
		||||
        val variantCapped = variantName.replaceFirstChar { it.uppercase() }
 | 
			
		||||
        val manifestUpdater =
 | 
			
		||||
            project.tasks.register("${variantName}ManifestProducer", ManifestUpdater::class.java) {
 | 
			
		||||
                dependsOn("generate${variantCapped}ObfuscatedClass")
 | 
			
		||||
                applicationId = variant.applicationId
 | 
			
		||||
                appClassDir.set(layout.buildDirectory.dir("generated/source/app/$variantName"))
 | 
			
		||||
                factoryClassDir.set(layout.buildDirectory.dir("generated/source/factory/$variantName"))
 | 
			
		||||
            }
 | 
			
		||||
        variant.artifacts.use(manifestUpdater)
 | 
			
		||||
            .wiredWithFiles(
 | 
			
		||||
                ManifestUpdater::mergedManifest,
 | 
			
		||||
                ManifestUpdater::outputManifest)
 | 
			
		||||
            .toTransform(SingleArtifact.MERGED_MANIFEST)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    androidApp.applicationVariants.all {
 | 
			
		||||
        val variantCapped = name.replaceFirstChar { it.uppercase() }
 | 
			
		||||
        val variantLowered = name.lowercase()
 | 
			
		||||
        val outFactoryClassDir = layout.buildDirectory.file("generated/source/factory/${variantLowered}").get().asFile
 | 
			
		||||
        val outAppClassDir = layout.buildDirectory.file("generated/source/app/${variantLowered}").get().asFile
 | 
			
		||||
        val outResDir = layout.buildDirectory.dir("generated/source/res/${variantLowered}").get().asFile
 | 
			
		||||
        val aapt = File(androidApp.sdkDirectory, "build-tools/${androidApp.buildToolsVersion}/aapt2")
 | 
			
		||||
        val apk = layout.buildDirectory.file("intermediates/linked_resources_binary_format/" +
 | 
			
		||||
                "${variantLowered}/process${variantCapped}Resources/linked-resources-binary-format-${variantLowered}.ap_").get().asFile
 | 
			
		||||
 | 
			
		||||
        val genManifestTask = tasks.register("generate${variantCapped}ObfuscatedClass") {
 | 
			
		||||
            inputs.property("seed", RAND_SEED)
 | 
			
		||||
            outputs.dirs(outFactoryClassDir, outAppClassDir)
 | 
			
		||||
            doLast {
 | 
			
		||||
                outFactoryClassDir.mkdirs()
 | 
			
		||||
                outAppClassDir.mkdirs()
 | 
			
		||||
                genStubClasses(outFactoryClassDir, outAppClassDir)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        registerJavaGeneratingTask(genManifestTask, outFactoryClassDir, outAppClassDir)
 | 
			
		||||
 | 
			
		||||
        val processResourcesTask = tasks.named("process${variantCapped}Resources") {
 | 
			
		||||
            outputs.dir(outResDir)
 | 
			
		||||
            doLast {
 | 
			
		||||
                val apkTmp = File("${apk}.tmp")
 | 
			
		||||
                exec {
 | 
			
		||||
                    commandLine(aapt, "optimize", "-o", apkTmp, "--collapse-resource-names", apk)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                val bos = ByteArrayOutputStream()
 | 
			
		||||
                ZipFile(apkTmp).use { src ->
 | 
			
		||||
                    ZipOutputStream(apk.outputStream()).use {
 | 
			
		||||
                        it.setLevel(Deflater.BEST_COMPRESSION)
 | 
			
		||||
                        it.putNextEntry(ZipEntry("AndroidManifest.xml"))
 | 
			
		||||
                        src.getInputStream(src.getEntry("AndroidManifest.xml")).transferTo(it)
 | 
			
		||||
                        it.closeEntry()
 | 
			
		||||
                    }
 | 
			
		||||
                    DeflaterOutputStream(bos, Deflater(Deflater.BEST_COMPRESSION)).use {
 | 
			
		||||
                        src.getInputStream(src.getEntry("resources.arsc")).transferTo(it)
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                apkTmp.delete()
 | 
			
		||||
                genEncryptedResources(bos.toByteArray(), outResDir)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        registerJavaGeneratingTask(processResourcesTask, outResDir)
 | 
			
		||||
    }
 | 
			
		||||
    // Override optimizeReleaseResources task
 | 
			
		||||
    val apk = layout.buildDirectory.file("intermediates/linked_resources_binary_format/" +
 | 
			
		||||
            "release/processReleaseResources/linked-resources-binary-format-release.ap_").get().asFile
 | 
			
		||||
    val optRes = layout.buildDirectory.file("intermediates/optimized_processed_res/" +
 | 
			
		||||
            "release/optimizeReleaseResources/resources-release-optimize.ap_").get().asFile
 | 
			
		||||
    afterEvaluate {
 | 
			
		||||
        tasks.named("optimizeReleaseResources") {
 | 
			
		||||
            doLast { apk.copyTo(optRes, true) }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    tasks.named<Delete>("clean") {
 | 
			
		||||
        delete.addAll(listOf("src/debug/AndroidManifest.xml", "src/release/AndroidManifest.xml"))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								app/core/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								app/core/.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,4 +1,3 @@
 | 
			
		||||
/build
 | 
			
		||||
src/*/assets
 | 
			
		||||
src/*/jniLibs
 | 
			
		||||
src/*/resources
 | 
			
		||||
src/debug
 | 
			
		||||
src/release
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@ plugins {
 | 
			
		||||
    id("com.android.library")
 | 
			
		||||
    kotlin("android")
 | 
			
		||||
    kotlin("plugin.parcelize")
 | 
			
		||||
    id("dev.zacsweers.moshix")
 | 
			
		||||
    id("com.google.devtools.ksp")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -29,7 +30,7 @@ android {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dependencies {
 | 
			
		||||
    api(project(":app:shared"))
 | 
			
		||||
    api(project(":shared"))
 | 
			
		||||
 | 
			
		||||
    api(libs.timber)
 | 
			
		||||
    api(libs.markwon.core)
 | 
			
		||||
@@ -48,9 +49,6 @@ dependencies {
 | 
			
		||||
    implementation(libs.okhttp.logging)
 | 
			
		||||
    implementation(libs.okhttp.dnsoverhttps)
 | 
			
		||||
 | 
			
		||||
    implementation(libs.moshi)
 | 
			
		||||
    ksp(libs.moshi.codegen)
 | 
			
		||||
 | 
			
		||||
    implementation(libs.room.runtime)
 | 
			
		||||
    implementation(libs.room.ktx)
 | 
			
		||||
    ksp(libs.room.compiler)
 | 
			
		||||
@@ -60,5 +58,10 @@ dependencies {
 | 
			
		||||
    implementation(libs.activity)
 | 
			
		||||
    implementation(libs.collection.ktx)
 | 
			
		||||
    implementation(libs.profileinstaller)
 | 
			
		||||
    implementation(libs.lifecycle.process)
 | 
			
		||||
 | 
			
		||||
    // We also implement all our tests in this module.
 | 
			
		||||
    // However, we don't want to bundle test dependencies.
 | 
			
		||||
    // That's why we make it compileOnly.
 | 
			
		||||
    compileOnly(libs.test.junit)
 | 
			
		||||
    compileOnly(libs.test.uiautomator)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								app/core/proguard-rules.pro
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								app/core/proguard-rules.pro
									
									
									
									
										vendored
									
									
								
							@@ -37,12 +37,4 @@
 | 
			
		||||
-flattenpackagehierarchy
 | 
			
		||||
-allowaccessmodification
 | 
			
		||||
 | 
			
		||||
-dontwarn org.bouncycastle.jsse.BCSSLParameters
 | 
			
		||||
-dontwarn org.bouncycastle.jsse.BCSSLSocket
 | 
			
		||||
-dontwarn org.bouncycastle.jsse.provider.BouncyCastleJsseProvider
 | 
			
		||||
-dontwarn org.commonmark.ext.gfm.strikethrough.Strikethrough
 | 
			
		||||
-dontwarn org.conscrypt.Conscrypt*
 | 
			
		||||
-dontwarn org.conscrypt.ConscryptHostnameVerifier
 | 
			
		||||
-dontwarn org.openjsse.javax.net.ssl.SSLParameters
 | 
			
		||||
-dontwarn org.openjsse.javax.net.ssl.SSLSocket
 | 
			
		||||
-dontwarn org.openjsse.net.ssl.OpenJSSE
 | 
			
		||||
-dontwarn org.junit.**
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,6 @@
 | 
			
		||||
    <application
 | 
			
		||||
        android:name=".App"
 | 
			
		||||
        android:icon="@drawable/ic_launcher"
 | 
			
		||||
        android:multiArch="true"
 | 
			
		||||
        tools:ignore="UnusedAttribute,GoogleAppIndexingWarning"
 | 
			
		||||
        tools:remove="android:appComponentFactory">
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user