mirror of
				https://github.com/topjohnwu/Magisk
				synced 2025-10-30 09:00:52 +01:00 
			
		
		
		
	Compare commits
	
		
			349 Commits
		
	
	
		
			canary-281
			...
			v30.3
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | f16e93c7db | ||
|   | 1b0ddec66e | ||
|   | cd8820f563 | ||
|   | b70192ca3e | ||
|   | d42ec5da9a | ||
|   | 742913ebcb | ||
|   | ed206c6480 | ||
|   | f9a8052583 | ||
|   | f4fdd516f9 | ||
|   | 5925a71f94 | ||
|   | 3cda9beb93 | ||
|   | 8b7d1ffcdd | ||
|   | 8d02d0632e | ||
|   | dd743f6f7e | ||
|   | cf483ad4d2 | ||
|   | 4aed644e08 | ||
|   | 0acc39cec0 | ||
|   | 8b3a44344f | ||
|   | 8b49eda85a | ||
|   | 7057d4c7f1 | ||
|   | aab8344058 | ||
|   | 7cccf83b37 | ||
|   | f10ad93c4e | ||
|   | f143b5df15 | ||
|   | 71213cc6f4 | ||
|   | e2a1774e5b | ||
|   | 0222527a1e | ||
|   | 312bfe1bab | ||
|   | 48c62a1dae | ||
|   | cfc2bcb665 | ||
|   | 94b1ff674f | ||
|   | 111136733a | ||
|   | c8caaa98f5 | ||
|   | 8d28f10a3f | ||
|   | 177a456d8b | ||
|   | ef4e230258 | ||
|   | 17082af438 | ||
|   | 1df5b34175 | ||
|   | ea5fe7525d | ||
|   | a75c335261 | ||
|   | 3903f42cf6 | ||
|   | fb0c4ea838 | ||
|   | bc89c60977 | ||
|   | bd657c354c | ||
|   | 675b5f9565 | ||
|   | 1b2c43268e | ||
|   | 653730d75e | ||
|   | d472e9c36e | ||
|   | 484d53ef7e | ||
|   | c4e2985677 | ||
|   | 42d9f87bc9 | ||
|   | 2e4fa6864c | ||
|   | e2abb648ac | ||
|   | 3599dcedfb | ||
|   | ea72666df8 | ||
|   | bd2a47ba18 | ||
|   | b861671391 | ||
|   | e91fc75d86 | ||
|   | 78f5cd55c7 | ||
|   | 9787a69528 | ||
|   | 87b8fe374d | ||
|   | 7b706bb0cb | ||
|   | c1491b8d2b | ||
|   | 5cbaf2ae11 | ||
|   | 8ebc6207b4 | ||
|   | 7848ee616b | ||
|   | fd193c3cae | ||
|   | 36d33c7a85 | ||
|   | 5caf28d27c | ||
|   | 2c39d0234d | ||
|   | c313812129 | ||
|   | af51880a81 | ||
|   | db8d832707 | ||
|   | 8dc23d0ead | ||
|   | b4287700d5 | ||
|   | 8d10ab89f2 | ||
|   | 49fdc1addb | ||
|   | 1333d3b986 | ||
|   | 335146a6a2 | ||
|   | eaf9527971 | ||
|   | da937a88c8 | ||
|   | 9476e7282d | ||
|   | 251c3c3e0e | ||
|   | cd0eca20b0 | ||
|   | 6839cb9ab2 | ||
|   | d11a3397d8 | ||
|   | 975120d6a6 | ||
|   | e489b3b6dd | ||
|   | 589a270b8d | ||
|   | 7961be5cfa | ||
|   | 959430e030 | ||
|   | 2923c8ccd1 | ||
|   | 7df4a9d74f | ||
|   | bf4ed295da | ||
|   | a5fca960dc | ||
|   | f99912b9db | ||
|   | a54bdb54e4 | ||
|   | cd9851a1fe | ||
|   | 9ca469898c | ||
|   | 0665549473 | ||
|   | 9d7a14b335 | ||
|   | 62e29fee74 | ||
|   | e472db552b | ||
|   | 466e4bd4e1 | ||
|   | 4cf525c588 | ||
|   | c8aec2510d | ||
|   | ccbfe0e66e | ||
|   | 23ea28de6f | ||
|   | 55c3ee3a6f | ||
|   | 2a42ca2b8f | ||
|   | a897e82fa4 | ||
|   | ffa15831d3 | ||
|   | a344ebf28c | ||
|   | 78f7fa348e | ||
|   | d8c448b99d | ||
|   | d4b83b6a44 | ||
|   | e5d36d1d24 | ||
|   | ff18cb8e70 | ||
|   | 37a9724a54 | ||
|   | d660401063 | ||
|   | 88541d6f49 | ||
|   | ecd6129fe5 | ||
|   | 6dfe9df9e2 | ||
|   | 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 | 
							
								
								
									
										6
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							| @@ -12,13 +12,11 @@ | |||||||
|  |  | ||||||
| # Denote all files that are truly binary and should not be modified. | # Denote all files that are truly binary and should not be modified. | ||||||
| tools/** binary | tools/** binary | ||||||
|  | tools/rustup-wrapper/** -binary | ||||||
|  | tools/elf-cleaner/** -binary | ||||||
| *.jar binary | *.jar binary | ||||||
| *.exe binary | *.exe binary | ||||||
| *.apk binary | *.apk binary | ||||||
| *.png binary | *.png binary | ||||||
| *.jpg binary | *.jpg binary | ||||||
| *.ttf binary | *.ttf binary | ||||||
|  |  | ||||||
| # Help GitHub detect languages |  | ||||||
| native/jni/external/** linguist-vendored |  | ||||||
| native/jni/systemproperties/** linguist-language=C++ |  | ||||||
|   | |||||||
							
								
								
									
										27
									
								
								.github/actions/setup/action.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										27
									
								
								.github/actions/setup/action.yml
									
									
									
									
										vendored
									
									
								
							| @@ -26,6 +26,15 @@ runs: | |||||||
|  |  | ||||||
|     - name: Cache sccache |     - name: Cache sccache | ||||||
|       uses: actions/cache@v4 |       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: |       with: | ||||||
|         path: .sccache |         path: .sccache | ||||||
|         key: sccache-${{ runner.os }}-${{ github.sha }} |         key: sccache-${{ runner.os }}-${{ github.sha }} | ||||||
| @@ -36,7 +45,7 @@ runs: | |||||||
|       env: |       env: | ||||||
|         SCCACHE_DIRECT: false |         SCCACHE_DIRECT: false | ||||||
|         SCCACHE_DIR: ${{ github.workspace }}/.sccache |         SCCACHE_DIR: ${{ github.workspace }}/.sccache | ||||||
|         SCCACHE_CACHE_SIZE: 2G |         SCCACHE_CACHE_SIZE: ${{ inputs.is-asset-build == 'true' && '2G' || '300M'  }} | ||||||
|         SCCACHE_IDLE_TIMEOUT: 0 |         SCCACHE_IDLE_TIMEOUT: 0 | ||||||
|       run: | |       run: | | ||||||
|         bash $GITHUB_ACTION_PATH/sccache.sh |         bash $GITHUB_ACTION_PATH/sccache.sh | ||||||
| @@ -55,18 +64,18 @@ runs: | |||||||
|  |  | ||||||
|     - name: Cache Gradle dependencies |     - name: Cache Gradle dependencies | ||||||
|       uses: actions/cache@v4 |       uses: actions/cache@v4 | ||||||
|       if: inputs.is-asset-build == 'true' |       if: ${{ inputs.is-asset-build == 'true' && github.event_name != 'pull_request' }} | ||||||
|       with: |       with: | ||||||
|         path: | |         path: | | ||||||
|           .gradle/caches |           .gradle/caches | ||||||
|           .gradle/wrapper |           .gradle/wrapper | ||||||
|           !.gradle/caches/build-cache-* |           !.gradle/caches/build-cache-* | ||||||
|         key: gradle-cache-${{ hashFiles('gradle/**') }} |         key: gradle-cache-${{ hashFiles('app/gradle/**') }} | ||||||
|         restore-keys: gradle-cache- |         restore-keys: gradle-cache- | ||||||
|  |  | ||||||
|     - name: Restore Gradle dependencies |     - name: Restore Gradle dependencies | ||||||
|       uses: actions/cache/restore@v4 |       uses: actions/cache/restore@v4 | ||||||
|       if: inputs.is-asset-build == 'false' |       if: ${{ inputs.is-asset-build == 'false' || github.event_name == 'pull_request' }} | ||||||
|       with: |       with: | ||||||
|         path: | |         path: | | ||||||
|           .gradle/caches |           .gradle/caches | ||||||
| @@ -78,19 +87,17 @@ runs: | |||||||
|  |  | ||||||
|     - name: Cache Gradle build cache |     - name: Cache Gradle build cache | ||||||
|       uses: actions/cache@v4 |       uses: actions/cache@v4 | ||||||
|       if: inputs.is-asset-build == 'true' |       if: ${{ inputs.is-asset-build == 'true' && github.event_name != 'pull_request' }} | ||||||
|       with: |       with: | ||||||
|         path: | |         path: .gradle/caches/build-cache-* | ||||||
|           .gradle/caches/build-cache-* |  | ||||||
|         key: gradle-build-cache-${{ github.sha }} |         key: gradle-build-cache-${{ github.sha }} | ||||||
|         restore-keys: gradle-build-cache- |         restore-keys: gradle-build-cache- | ||||||
|  |  | ||||||
|     - name: Restore Gradle build cache |     - name: Restore Gradle build cache | ||||||
|       uses: actions/cache/restore@v4 |       uses: actions/cache/restore@v4 | ||||||
|       if: inputs.is-asset-build == 'false' |       if: ${{ inputs.is-asset-build == 'false' || github.event_name == 'pull_request' }} | ||||||
|       with: |       with: | ||||||
|         path: | |         path: .gradle/caches/build-cache-* | ||||||
|           .gradle/caches/build-cache-* |  | ||||||
|         key: gradle-build-cache-${{ github.sha }} |         key: gradle-build-cache-${{ github.sha }} | ||||||
|         restore-keys: gradle-build-cache- |         restore-keys: gradle-build-cache- | ||||||
|         enableCrossOsArchive: true |         enableCrossOsArchive: true | ||||||
|   | |||||||
							
								
								
									
										36
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										36
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,6 +1,13 @@ | |||||||
| name: Magisk Build | name: Magisk Build | ||||||
|  |  | ||||||
| on: | on: | ||||||
|  |   push: | ||||||
|  |     branches: [master] | ||||||
|  |     paths: | ||||||
|  |       - "app/**" | ||||||
|  |       - "native/**" | ||||||
|  |       - "build.py" | ||||||
|  |       - ".github/workflows/build.yml" | ||||||
|   pull_request: |   pull_request: | ||||||
|     branches: [master] |     branches: [master] | ||||||
|   workflow_dispatch: |   workflow_dispatch: | ||||||
| @@ -29,7 +36,7 @@ jobs: | |||||||
|         run: ./build.py -v all |         run: ./build.py -v all | ||||||
|  |  | ||||||
|       - name: Stop gradle daemon |       - name: Stop gradle daemon | ||||||
|         run: ./gradlew --stop |         run: ./app/gradlew --stop | ||||||
|  |  | ||||||
|       - name: Upload build artifact |       - name: Upload build artifact | ||||||
|         uses: actions/upload-artifact@v4 |         uses: actions/upload-artifact@v4 | ||||||
| @@ -65,21 +72,20 @@ jobs: | |||||||
|         run: python build.py -v -c .github/ci.prop all |         run: python build.py -v -c .github/ci.prop all | ||||||
|  |  | ||||||
|       - name: Stop gradle daemon |       - name: Stop gradle daemon | ||||||
|         run: ./gradlew --stop |         run: ./app/gradlew --stop | ||||||
|  |  | ||||||
|   avd-test: |   avd-test: | ||||||
|     name: Test API ${{ matrix.version }} (x86_64) |     name: Test API ${{ matrix.version }} (x86_64) | ||||||
|     runs-on: ubuntu-24.04 |     runs-on: ubuntu-24.04 | ||||||
|     needs: build |     needs: build | ||||||
|  |     if: ${{ github.event_name != 'push' }} | ||||||
|     strategy: |     strategy: | ||||||
|       fail-fast: false |       fail-fast: false | ||||||
|       matrix: |       matrix: | ||||||
|         version: [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35] |         version: [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, "CANARY"] | ||||||
|         type: [""] |         type: [""] | ||||||
|         include: |         include: | ||||||
|           - version: "Baklava" |           - version: "CANARY" | ||||||
|             type: "google_apis" |  | ||||||
|           - version: "Baklava" |  | ||||||
|             type: "google_apis_ps16k" |             type: "google_apis_ps16k" | ||||||
|  |  | ||||||
|     steps: |     steps: | ||||||
| @@ -99,10 +105,10 @@ jobs: | |||||||
|           sudo udevadm trigger --name-match=kvm |           sudo udevadm trigger --name-match=kvm | ||||||
|  |  | ||||||
|       - name: Run AVD test |       - name: Run AVD test | ||||||
|         timeout-minutes: 10 |         timeout-minutes: 15 | ||||||
|         env: |         env: | ||||||
|           AVD_TEST_LOG: 1 |           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 |       - name: Upload logs on error | ||||||
|         if: ${{ failure() }} |         if: ${{ failure() }} | ||||||
| @@ -117,6 +123,7 @@ jobs: | |||||||
|     name: Test API ${{ matrix.version }} (x86) |     name: Test API ${{ matrix.version }} (x86) | ||||||
|     runs-on: ubuntu-24.04 |     runs-on: ubuntu-24.04 | ||||||
|     needs: build |     needs: build | ||||||
|  |     if: ${{ github.event_name != 'push' }} | ||||||
|     strategy: |     strategy: | ||||||
|       fail-fast: false |       fail-fast: false | ||||||
|       matrix: |       matrix: | ||||||
| @@ -139,11 +146,11 @@ jobs: | |||||||
|           sudo udevadm trigger --name-match=kvm |           sudo udevadm trigger --name-match=kvm | ||||||
|  |  | ||||||
|       - name: Run AVD test |       - name: Run AVD test | ||||||
|         timeout-minutes: 10 |         timeout-minutes: 15 | ||||||
|         env: |         env: | ||||||
|           FORCE_32_BIT: 1 |           FORCE_32_BIT: 1 | ||||||
|           AVD_TEST_LOG: 1 |           AVD_TEST_LOG: 1 | ||||||
|         run: scripts/avd_test.sh ${{ matrix.version }} |         run: scripts/avd.sh test ${{ matrix.version }} | ||||||
|  |  | ||||||
|       - name: Upload logs on error |       - name: Upload logs on error | ||||||
|         if: ${{ failure() }} |         if: ${{ failure() }} | ||||||
| @@ -158,14 +165,15 @@ jobs: | |||||||
|     name: Test ${{ matrix.device }} |     name: Test ${{ matrix.device }} | ||||||
|     runs-on: ubuntu-24.04 |     runs-on: ubuntu-24.04 | ||||||
|     needs: build |     needs: build | ||||||
|  |     if: ${{ github.event_name != 'push' }} | ||||||
|     env: |     env: | ||||||
|       CF_HOME: /home/runner/aosp_cf_phone |       CF_HOME: /home/runner/aosp_cf_phone | ||||||
|     strategy: |     strategy: | ||||||
|       fail-fast: false |       fail-fast: false | ||||||
|       matrix: |       matrix: | ||||||
|         include: |         include: | ||||||
|           - branch: "aosp-main" |           - branch: "aosp-android-latest-release" | ||||||
|             device: "aosp_cf_x86_64_phone" |             device: "aosp_cf_x86_64_only_phone" | ||||||
|  |  | ||||||
|     steps: |     steps: | ||||||
|       - name: Check out |       - name: Check out | ||||||
| @@ -183,8 +191,8 @@ jobs: | |||||||
|           scripts/cuttlefish.sh download ${{ matrix.branch }} ${{ matrix.device }} |           scripts/cuttlefish.sh download ${{ matrix.branch }} ${{ matrix.device }} | ||||||
|  |  | ||||||
|       - name: Run Cuttlefish test |       - name: Run Cuttlefish test | ||||||
|         timeout-minutes: 10 |         timeout-minutes: 15 | ||||||
|         run: su $USER -c 'scripts/cuttlefish.sh test' |         run: sudo -E -u $USER scripts/cuttlefish.sh test | ||||||
|  |  | ||||||
|       - name: Upload logs on error |       - name: Upload logs on error | ||||||
|         if: ${{ failure() }} |         if: ${{ failure() }} | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -2,19 +2,13 @@ out | |||||||
| *.zip | *.zip | ||||||
| *.jks | *.jks | ||||||
| *.apk | *.apk | ||||||
|  | *.log | ||||||
| /config.prop | /config.prop | ||||||
| /notes.md | /notes.md | ||||||
| /update.sh |  | ||||||
| /app/dict.txt |  | ||||||
|  |  | ||||||
| # Built binaries | # Built binaries | ||||||
| native/out | native/out | ||||||
|  |  | ||||||
| # Android Studio / Gradle | # Android Studio | ||||||
| *.iml | *.iml | ||||||
| .gradle |  | ||||||
| .idea | .idea | ||||||
| .kotlin |  | ||||||
| /local.properties |  | ||||||
| /build |  | ||||||
| /captures |  | ||||||
|   | |||||||
							
								
								
									
										15
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							| @@ -4,21 +4,9 @@ | |||||||
| [submodule "lz4"] | [submodule "lz4"] | ||||||
| 	path = native/src/external/lz4 | 	path = native/src/external/lz4 | ||||||
| 	url = https://github.com/lz4/lz4.git | 	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"] | [submodule "libcxx"] | ||||||
| 	path = native/src/external/libcxx | 	path = native/src/external/libcxx | ||||||
| 	url = https://github.com/topjohnwu/libcxx.git | 	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"] | [submodule "cxx-rs"] | ||||||
| 	path = native/src/external/cxx-rs | 	path = native/src/external/cxx-rs | ||||||
| 	url = https://github.com/topjohnwu/cxx.git | 	url = https://github.com/topjohnwu/cxx.git | ||||||
| @@ -31,6 +19,3 @@ | |||||||
| [submodule "crt0"] | [submodule "crt0"] | ||||||
| 	path = native/src/external/crt0 | 	path = native/src/external/crt0 | ||||||
| 	url = https://github.com/topjohnwu/crt0.git | 	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 | ## Downloads | ||||||
|  |  | ||||||
| [Github](https://github.com/topjohnwu/Magisk/) is the only source where you can get official Magisk information and downloads. | [Github](https://github.com/topjohnwu/Magisk/releases) 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/v28.1) |  | ||||||
| [](https://github.com/topjohnwu/Magisk/releases/tag/v28.1) |  | ||||||
| [](https://github.com/topjohnwu/Magisk/releases/tag/canary-28102) |  | ||||||
|  |  | ||||||
| ## Useful Links | ## 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 { | dependencies { | ||||||
|     implementation(project(":app:core")) |     implementation(project(":core")) | ||||||
|     coreLibraryDesugaring(libs.jdk.libs) |     coreLibraryDesugaring(libs.jdk.libs) | ||||||
|  |  | ||||||
|     implementation(libs.indeterminate.checkbox) |     implementation(libs.indeterminate.checkbox) | ||||||
|   | |||||||
| @@ -1,10 +1,13 @@ | |||||||
| package com.topjohnwu.magisk.arch | package com.topjohnwu.magisk.arch | ||||||
|  |  | ||||||
|  | import android.content.ContentResolver | ||||||
| import android.view.KeyEvent | import android.view.KeyEvent | ||||||
| import androidx.databinding.ViewDataBinding | import androidx.databinding.ViewDataBinding | ||||||
| import androidx.navigation.NavController | import androidx.navigation.NavController | ||||||
| import androidx.navigation.NavDirections | import androidx.navigation.NavDirections | ||||||
| import androidx.navigation.fragment.NavHostFragment | import androidx.navigation.fragment.NavHostFragment | ||||||
|  | import androidx.navigation.navOptions | ||||||
|  | import com.topjohnwu.magisk.utils.AccessibilityUtils | ||||||
|  |  | ||||||
| abstract class NavigationActivity<Binding : ViewDataBinding> : UIActivity<Binding>() { | 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() { |     fun NavDirections.navigate() { | ||||||
|         navigation.navigate(this) |         navigate(this, navigation, contentResolver) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -24,6 +24,7 @@ import androidx.core.widget.ImageViewCompat | |||||||
| import androidx.databinding.BindingAdapter | import androidx.databinding.BindingAdapter | ||||||
| import androidx.databinding.InverseBindingAdapter | import androidx.databinding.InverseBindingAdapter | ||||||
| import androidx.databinding.InverseBindingListener | import androidx.databinding.InverseBindingListener | ||||||
|  | import androidx.databinding.InverseMethod | ||||||
| import androidx.interpolator.view.animation.FastOutSlowInInterpolator | import androidx.interpolator.view.animation.FastOutSlowInInterpolator | ||||||
| import androidx.recyclerview.widget.DividerItemDecoration | import androidx.recyclerview.widget.DividerItemDecoration | ||||||
| import androidx.recyclerview.widget.GridLayoutManager | import androidx.recyclerview.widget.GridLayoutManager | ||||||
| @@ -33,9 +34,11 @@ import androidx.recyclerview.widget.StaggeredGridLayoutManager | |||||||
| import com.google.android.material.button.MaterialButton | import com.google.android.material.button.MaterialButton | ||||||
| import com.google.android.material.card.MaterialCardView | import com.google.android.material.card.MaterialCardView | ||||||
| import com.google.android.material.chip.Chip | import com.google.android.material.chip.Chip | ||||||
|  | import com.google.android.material.slider.Slider | ||||||
| import com.google.android.material.textfield.TextInputLayout | import com.google.android.material.textfield.TextInputLayout | ||||||
| import com.topjohnwu.magisk.R | import com.topjohnwu.magisk.R | ||||||
| import com.topjohnwu.magisk.core.di.ServiceLocator | import com.topjohnwu.magisk.core.di.ServiceLocator | ||||||
|  | import com.topjohnwu.magisk.core.model.su.SuPolicy | ||||||
| import com.topjohnwu.magisk.utils.TextHolder | import com.topjohnwu.magisk.utils.TextHolder | ||||||
| import com.topjohnwu.superuser.internal.UiThreadHandler | import com.topjohnwu.superuser.internal.UiThreadHandler | ||||||
| import com.topjohnwu.widget.IndeterminateCheckBox | import com.topjohnwu.widget.IndeterminateCheckBox | ||||||
| @@ -306,3 +309,38 @@ fun TextView.setText(text: TextHolder) { | |||||||
| fun Spinner.setAdapter(items: Array<Any>, layoutRes: Int) { | fun Spinner.setAdapter(items: Array<Any>, layoutRes: Int) { | ||||||
|     adapter = ArrayAdapter(context, layoutRes, items) |     adapter = ArrayAdapter(context, layoutRes, items) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @BindingAdapter("labelFormatter") | ||||||
|  | fun Slider.setLabelFormatter(formatter: (Float) -> Int) { | ||||||
|  |     setLabelFormatter { value -> resources.getString(formatter(value)) } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @InverseBindingAdapter(attribute = "android:value") | ||||||
|  | fun Slider.getValueBinding() = value | ||||||
|  |  | ||||||
|  | @BindingAdapter("android:valueAttrChanged") | ||||||
|  | fun Slider.setListener(attrChange: InverseBindingListener) { | ||||||
|  |     addOnSliderTouchListener(object : Slider.OnSliderTouchListener { | ||||||
|  |         override fun onStartTrackingTouch(slider: Slider) = Unit | ||||||
|  |         override fun onStopTrackingTouch(slider: Slider) = attrChange.onChange() | ||||||
|  |     }) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @InverseMethod("sliderValueToPolicy") | ||||||
|  | fun policyToSliderValue(policy: Int): Float { | ||||||
|  |     return when (policy) { | ||||||
|  |         SuPolicy.DENY -> 1f | ||||||
|  |         SuPolicy.RESTRICT -> 2f | ||||||
|  |         SuPolicy.ALLOW -> 3f | ||||||
|  |         else -> 1f | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fun sliderValueToPolicy(value: Float): Int { | ||||||
|  |     return when (value) { | ||||||
|  |         1f -> SuPolicy.DENY | ||||||
|  |         2f -> SuPolicy.RESTRICT | ||||||
|  |         3f -> SuPolicy.ALLOW | ||||||
|  |         else -> SuPolicy.DENY | ||||||
|  |     } | ||||||
|  | } | ||||||
|   | |||||||
| @@ -3,7 +3,6 @@ package com.topjohnwu.magisk.dialog | |||||||
| import com.topjohnwu.magisk.core.AppContext | import com.topjohnwu.magisk.core.AppContext | ||||||
| import com.topjohnwu.magisk.core.Info | import com.topjohnwu.magisk.core.Info | ||||||
| import com.topjohnwu.magisk.core.R | 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.DownloadEngine | ||||||
| import com.topjohnwu.magisk.core.download.Subject | import com.topjohnwu.magisk.core.download.Subject | ||||||
| import com.topjohnwu.magisk.view.MagiskDialog | import com.topjohnwu.magisk.view.MagiskDialog | ||||||
| @@ -11,15 +10,10 @@ import java.io.File | |||||||
|  |  | ||||||
| class ManagerInstallDialog : MarkDownDialog() { | class ManagerInstallDialog : MarkDownDialog() { | ||||||
|  |  | ||||||
|     private val svc get() = ServiceLocator.networkService |  | ||||||
|  |  | ||||||
|     override suspend fun getMarkdownText(): String { |     override suspend fun getMarkdownText(): String { | ||||||
|         val text = svc.fetchString(Info.remote.magisk.note) |         val text = Info.update.note | ||||||
|         // Cache the changelog |         // Cache the changelog | ||||||
|         AppContext.cacheDir.listFiles { _, name -> name.endsWith(".md") }.orEmpty().forEach { |         File(AppContext.cacheDir, "${Info.update.versionCode}.md").writeText(text) | ||||||
|             it.delete() |  | ||||||
|         } |  | ||||||
|         File(AppContext.cacheDir, "${Info.remote.magisk.versionCode}.md").writeText(text) |  | ||||||
|         return text |         return text | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -17,6 +17,8 @@ import com.topjohnwu.magisk.core.Info | |||||||
| import com.topjohnwu.magisk.core.download.DownloadEngine | import com.topjohnwu.magisk.core.download.DownloadEngine | ||||||
| import com.topjohnwu.magisk.databinding.FragmentHomeMd2Binding | import com.topjohnwu.magisk.databinding.FragmentHomeMd2Binding | ||||||
| import com.topjohnwu.magisk.core.R as CoreR | import com.topjohnwu.magisk.core.R as CoreR | ||||||
|  | import androidx.navigation.findNavController | ||||||
|  | import com.topjohnwu.magisk.arch.NavigationActivity | ||||||
|  |  | ||||||
| class HomeFragment : BaseFragment<FragmentHomeMd2Binding>(), MenuProvider { | class HomeFragment : BaseFragment<FragmentHomeMd2Binding>(), MenuProvider { | ||||||
|  |  | ||||||
| @@ -68,7 +70,13 @@ class HomeFragment : BaseFragment<FragmentHomeMd2Binding>(), MenuProvider { | |||||||
|     override fun onMenuItemSelected(item: MenuItem): Boolean { |     override fun onMenuItemSelected(item: MenuItem): Boolean { | ||||||
|         when (item.itemId) { |         when (item.itemId) { | ||||||
|             R.id.action_settings -> |             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() } |             R.id.action_reboot -> activity?.let { RebootMenu.inflate(it).show() } | ||||||
|             else -> return super.onOptionsItemSelected(item) |             else -> return super.onOptionsItemSelected(item) | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -91,16 +91,15 @@ class HomeViewModel( | |||||||
|  |  | ||||||
|     override suspend fun doLoadWork() { |     override suspend fun doLoadWork() { | ||||||
|         appState = State.LOADING |         appState = State.LOADING | ||||||
|         Info.getRemote(svc)?.apply { |         Info.fetchUpdate(svc)?.apply { | ||||||
|             appState = when { |             appState = when { | ||||||
|                 BuildConfig.APP_VERSION_CODE < magisk.versionCode -> State.OUTDATED |                 BuildConfig.APP_VERSION_CODE < versionCode -> State.OUTDATED | ||||||
|                 else -> State.UP_TO_DATE |                 else -> State.UP_TO_DATE | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             val isDebug = Config.updateChannel == Config.Value.DEBUG_CHANNEL |             val isDebug = Config.updateChannel == Config.Value.DEBUG_CHANNEL | ||||||
|             managerRemoteVersion = |             managerRemoteVersion = | ||||||
|                 ("${magisk.version} (${magisk.versionCode})" + |                 ("$version (${versionCode})" + if (isDebug) " (D)" else "").asText() | ||||||
|                     if (isDebug) " (D)" else "").asText() |  | ||||||
|         } ?: run { |         } ?: run { | ||||||
|             appState = State.INVALID |             appState = State.INVALID | ||||||
|             managerRemoteVersion = CoreR.string.not_available.asText() |             managerRemoteVersion = CoreR.string.not_available.asText() | ||||||
|   | |||||||
| @@ -41,7 +41,7 @@ object RebootMenu { | |||||||
|             activity.getSystemService<PowerManager>()?.isRebootingUserspaceSupported == true) { |             activity.getSystemService<PowerManager>()?.isRebootingUserspaceSupported == true) { | ||||||
|             menu.menu.findItem(R.id.action_reboot_userspace).isVisible = 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 |             menu.menu.findItem(R.id.action_reboot_safe_mode).isChecked = Config.bootloop >= 2 | ||||||
|         } else { |         } else { | ||||||
|             menu.menu.findItem(R.id.action_reboot_safe_mode).isVisible = false |             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.R | ||||||
| import com.topjohnwu.magisk.arch.BaseViewModel | import com.topjohnwu.magisk.arch.BaseViewModel | ||||||
| import com.topjohnwu.magisk.core.AppContext | 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.Config | ||||||
| import com.topjohnwu.magisk.core.Const |  | ||||||
| import com.topjohnwu.magisk.core.Info | import com.topjohnwu.magisk.core.Info | ||||||
| import com.topjohnwu.magisk.core.base.ContentResultCallback | import com.topjohnwu.magisk.core.base.ContentResultCallback | ||||||
| import com.topjohnwu.magisk.core.ktx.toast | import com.topjohnwu.magisk.core.ktx.toast | ||||||
| @@ -70,17 +69,16 @@ class InstallViewModel(svc: NetworkService, markwon: Markwon) : BaseViewModel() | |||||||
|     init { |     init { | ||||||
|         viewModelScope.launch(Dispatchers.IO) { |         viewModelScope.launch(Dispatchers.IO) { | ||||||
|             try { |             try { | ||||||
|                 val file = File(AppContext.cacheDir, "${BuildConfig.APP_VERSION_CODE}.md") |                 val noteFile = File(AppContext.cacheDir, "${APP_VERSION_CODE}.md") | ||||||
|                 val text = when { |                 val noteText = when { | ||||||
|                     file.exists() -> file.readText() |                     noteFile.exists() -> noteFile.readText() | ||||||
|                     Const.Url.CHANGELOG_URL.isEmpty() -> "" |  | ||||||
|                     else -> { |                     else -> { | ||||||
|                         val str = svc.fetchString(Const.Url.CHANGELOG_URL) |                         val note = svc.fetchUpdate(APP_VERSION_CODE).note | ||||||
|                         file.writeText(str) |                         noteFile.writeText(note) | ||||||
|                         str |                         note | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 val spanned = markwon.toMarkdown(text) |                 val spanned = markwon.toMarkdown(noteText) | ||||||
|                 withContext(Dispatchers.Main) { |                 withContext(Dispatchers.Main) { | ||||||
|                     notes = spanned |                     notes = spanned | ||||||
|                 } |                 } | ||||||
| @@ -100,13 +98,15 @@ class InstallViewModel(svc: NetworkService, markwon: Markwon) : BaseViewModel() | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     override fun onSaveState(state: Bundle) { |     override fun onSaveState(state: Bundle) { | ||||||
|         state.putParcelable(INSTALL_STATE_KEY, InstallState( |         state.putParcelable( | ||||||
|             methodId, |             INSTALL_STATE_KEY, InstallState( | ||||||
|             step, |                 methodId, | ||||||
|             Config.keepVerity, |                 step, | ||||||
|             Config.keepEnc, |                 Config.keepVerity, | ||||||
|             Config.recovery |                 Config.keepEnc, | ||||||
|         )) |                 Config.recovery | ||||||
|  |             ) | ||||||
|  |         ) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     override fun onRestoreState(state: Bundle) { |     override fun onRestoreState(state: Bundle) { | ||||||
| @@ -124,6 +124,7 @@ class InstallViewModel(svc: NetworkService, markwon: Markwon) : BaseViewModel() | |||||||
|         override fun onActivityLaunch() { |         override fun onActivityLaunch() { | ||||||
|             AppContext.toast(CoreR.string.patch_file_msg, Toast.LENGTH_LONG) |             AppContext.toast(CoreR.string.patch_file_msg, Toast.LENGTH_LONG) | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         override fun onActivityResult(result: Uri) { |         override fun onActivityResult(result: Uri) { | ||||||
|             uri.value = result |             uri.value = result | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ import android.view.Menu | |||||||
| import android.view.MenuInflater | import android.view.MenuInflater | ||||||
| import android.view.MenuItem | import android.view.MenuItem | ||||||
| import android.view.View | import android.view.View | ||||||
|  | import android.widget.HorizontalScrollView | ||||||
| import androidx.core.view.MenuProvider | import androidx.core.view.MenuProvider | ||||||
| import androidx.core.view.isVisible | import androidx.core.view.isVisible | ||||||
| import com.topjohnwu.magisk.R | 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.arch.viewModel | ||||||
| import com.topjohnwu.magisk.databinding.FragmentLogMd2Binding | import com.topjohnwu.magisk.databinding.FragmentLogMd2Binding | ||||||
| import com.topjohnwu.magisk.ui.MainActivity | import com.topjohnwu.magisk.ui.MainActivity | ||||||
|  | import com.topjohnwu.magisk.utils.AccessibilityUtils | ||||||
| import com.topjohnwu.magisk.utils.MotionRevealHelper | import com.topjohnwu.magisk.utils.MotionRevealHelper | ||||||
| import rikka.recyclerview.addEdgeSpacing | import rikka.recyclerview.addEdgeSpacing | ||||||
| import rikka.recyclerview.addItemSpacing | import rikka.recyclerview.addItemSpacing | ||||||
| @@ -56,6 +58,11 @@ class LogFragment : BaseFragment<FragmentLogMd2Binding>(), MenuProvider { | |||||||
|             addItemSpacing(R.dimen.l1, R.dimen.l_50, R.dimen.l1) |             addItemSpacing(R.dimen.l1, R.dimen.l_50, R.dimen.l1) | ||||||
|             fixEdgeEffect() |             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 |         get() = Config.updateChannel | ||||||
|         set(value) { |         set(value) { | ||||||
|             Config.updateChannel = value |             Config.updateChannel = value | ||||||
|             Info.remote = Info.EMPTY_REMOTE |             Info.resetUpdate() | ||||||
|         } |         } | ||||||
|  |  | ||||||
|     override val title = CoreR.string.settings_update_channel_title.asText() |     override val title = CoreR.string.settings_update_channel_title.asText() | ||||||
|  |  | ||||||
|     override val entryRes = CoreR.array.update_channel |     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() { | object UpdateChannelUrl : BaseSettingsItem.Input() { | ||||||
| @@ -169,7 +161,7 @@ object UpdateChannelUrl : BaseSettingsItem.Input() { | |||||||
|         get() = Config.customChannelUrl |         get() = Config.customChannelUrl | ||||||
|         set(value) { |         set(value) { | ||||||
|             Config.customChannelUrl = value |             Config.customChannelUrl = value | ||||||
|             Info.remote = Info.EMPTY_REMOTE |             Info.resetUpdate() | ||||||
|             notifyPropertyChanged(BR.description) |             notifyPropertyChanged(BR.description) | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -330,6 +322,12 @@ object Reauthenticate : BaseSettingsItem.Toggle() { | |||||||
|     override var value by Config::suReAuth |     override var value by Config::suReAuth | ||||||
|  |  | ||||||
|     override fun refresh() { |     override fun refresh() { | ||||||
|         isEnabled = Build.VERSION.SDK_INT < Build.VERSION_CODES.O && Info.showSuperUser |         isEnabled = Build.VERSION.SDK_INT < Build.VERSION_CODES.O | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | object Restrict : BaseSettingsItem.Toggle() { | ||||||
|  |     override val title = CoreR.string.settings_su_restrict_title.asText() | ||||||
|  |     override val description = CoreR.string.settings_su_restrict_summary.asText() | ||||||
|  |     override var value by Config::suRestrict | ||||||
|  | } | ||||||
|   | |||||||
| @@ -22,11 +22,11 @@ import com.topjohnwu.magisk.core.ktx.activity | |||||||
| import com.topjohnwu.magisk.core.ktx.toast | import com.topjohnwu.magisk.core.ktx.toast | ||||||
| import com.topjohnwu.magisk.core.tasks.AppMigration | import com.topjohnwu.magisk.core.tasks.AppMigration | ||||||
| import com.topjohnwu.magisk.core.utils.LocaleSetting | import com.topjohnwu.magisk.core.utils.LocaleSetting | ||||||
|  | import com.topjohnwu.magisk.core.utils.RootUtils | ||||||
| import com.topjohnwu.magisk.databinding.bindExtra | import com.topjohnwu.magisk.databinding.bindExtra | ||||||
| import com.topjohnwu.magisk.events.AddHomeIconEvent | import com.topjohnwu.magisk.events.AddHomeIconEvent | ||||||
| import com.topjohnwu.magisk.events.AuthEvent | import com.topjohnwu.magisk.events.AuthEvent | ||||||
| import com.topjohnwu.magisk.events.SnackbarEvent | import com.topjohnwu.magisk.events.SnackbarEvent | ||||||
| import com.topjohnwu.superuser.Shell |  | ||||||
| import kotlinx.coroutines.launch | import kotlinx.coroutines.launch | ||||||
|  |  | ||||||
| class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Handler { | class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Handler { | ||||||
| @@ -83,6 +83,9 @@ class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Handler { | |||||||
|                 // Can hide overlay windows on 12.0+ |                 // Can hide overlay windows on 12.0+ | ||||||
|                 list.remove(Tapjack) |                 list.remove(Tapjack) | ||||||
|             } |             } | ||||||
|  |             if (Const.Version.atLeast_30_1()) { | ||||||
|  |                 list.add(Restrict) | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         return list |         return list | ||||||
| @@ -127,7 +130,8 @@ class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Handler { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     private fun createHosts() { |     private fun createHosts() { | ||||||
|         Shell.cmd("add_hosts_module").submit { |         viewModelScope.launch { | ||||||
|  |             RootUtils.addSystemlessHosts() | ||||||
|             AppContext.toast(R.string.settings_hosts_toast, Toast.LENGTH_SHORT) |             AppContext.toast(R.string.settings_hosts_toast, Toast.LENGTH_SHORT) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -4,11 +4,13 @@ import android.graphics.drawable.Drawable | |||||||
| import androidx.databinding.Bindable | import androidx.databinding.Bindable | ||||||
| import com.topjohnwu.magisk.BR | import com.topjohnwu.magisk.BR | ||||||
| import com.topjohnwu.magisk.R | import com.topjohnwu.magisk.R | ||||||
|  | import com.topjohnwu.magisk.core.Config | ||||||
| import com.topjohnwu.magisk.core.model.su.SuPolicy | import com.topjohnwu.magisk.core.model.su.SuPolicy | ||||||
| import com.topjohnwu.magisk.databinding.DiffItem | import com.topjohnwu.magisk.databinding.DiffItem | ||||||
| import com.topjohnwu.magisk.databinding.ItemWrapper | import com.topjohnwu.magisk.databinding.ItemWrapper | ||||||
| import com.topjohnwu.magisk.databinding.ObservableRvItem | import com.topjohnwu.magisk.databinding.ObservableRvItem | ||||||
| import com.topjohnwu.magisk.databinding.set | import com.topjohnwu.magisk.databinding.set | ||||||
|  | import com.topjohnwu.magisk.core.R as CoreR | ||||||
|  |  | ||||||
| class PolicyRvItem( | class PolicyRvItem( | ||||||
|     private val viewModel: SuperuserViewModel, |     private val viewModel: SuperuserViewModel, | ||||||
| @@ -33,14 +35,34 @@ class PolicyRvItem( | |||||||
|     var isExpanded = false |     var isExpanded = false | ||||||
|         set(value) = set(value, field, { field = it }, BR.expanded) |         set(value) = set(value, field, { field = it }, BR.expanded) | ||||||
|  |  | ||||||
|  |     val showSlider = Config.suRestrict || item.policy == SuPolicy.RESTRICT | ||||||
|  |  | ||||||
|     @get:Bindable |     @get:Bindable | ||||||
|     var isEnabled |     var isEnabled | ||||||
|         get() = item.policy == SuPolicy.ALLOW |         get() = item.policy >= SuPolicy.ALLOW | ||||||
|         set(value) = setImpl(value, isEnabled) { |         set(value) = setImpl(value, isEnabled) { | ||||||
|             notifyPropertyChanged(BR.enabled) |             notifyPropertyChanged(BR.enabled) | ||||||
|             viewModel.togglePolicy(this, value) |             viewModel.updatePolicy(this, if (it) SuPolicy.ALLOW else SuPolicy.DENY) | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |     @get:Bindable | ||||||
|  |     var sliderValue | ||||||
|  |         get() = item.policy | ||||||
|  |         set(value) = setImpl(value, sliderValue) { | ||||||
|  |             notifyPropertyChanged(BR.sliderValue) | ||||||
|  |             notifyPropertyChanged(BR.enabled) | ||||||
|  |             viewModel.updatePolicy(this, it) | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     val sliderValueToPolicyString: (Float) -> Int = { value -> | ||||||
|  |         when (value.toInt()) { | ||||||
|  |             1 -> CoreR.string.deny | ||||||
|  |             2 -> CoreR.string.restrict | ||||||
|  |             3 -> CoreR.string.grant | ||||||
|  |             else -> CoreR.string.deny | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     @get:Bindable |     @get:Bindable | ||||||
|     var shouldNotify |     var shouldNotify | ||||||
|         get() = item.notification |         get() = item.notification | ||||||
|   | |||||||
| @@ -156,15 +156,16 @@ class SuperuserViewModel( | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fun togglePolicy(item: PolicyRvItem, enable: Boolean) { |     fun updatePolicy(item: PolicyRvItem, policy: Int) { | ||||||
|         val items = itemsPolicies.filter { it.item.uid == item.item.uid } |         val items = itemsPolicies.filter { it.item.uid == item.item.uid } | ||||||
|         fun updateState() { |         fun updateState() { | ||||||
|             viewModelScope.launch { |             viewModelScope.launch { | ||||||
|                 val res = if (enable) R.string.su_snack_grant else R.string.su_snack_deny |                 val res = if (policy >= SuPolicy.ALLOW) R.string.su_snack_grant else R.string.su_snack_deny | ||||||
|                 item.item.policy = if (enable) SuPolicy.ALLOW else SuPolicy.DENY |                 item.item.policy = policy | ||||||
|                 db.update(item.item) |                 db.update(item.item) | ||||||
|                 items.forEach { |                 items.forEach { | ||||||
|                     it.notifyPropertyChanged(BR.enabled) |                     it.notifyPropertyChanged(BR.enabled) | ||||||
|  |                     it.notifyPropertyChanged(BR.sliderValue) | ||||||
|                 } |                 } | ||||||
|                 SnackbarEvent(res.asText(item.appName)).publish() |                 SnackbarEvent(res.asText(item.appName)).publish() | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -43,10 +43,6 @@ enum class Theme( | |||||||
|  |  | ||||||
|     val isSelected get() = Config.themeOrdinal == ordinal |     val isSelected get() = Config.themeOrdinal == ordinal | ||||||
|  |  | ||||||
|     fun select() { |  | ||||||
|         Config.themeOrdinal = ordinal |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     companion object { |     companion object { | ||||||
|         val selected get() = values().getOrNull(Config.themeOrdinal) ?: Piplup |         val selected get() = values().getOrNull(Config.themeOrdinal) ?: Piplup | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -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"> |         android:layout_height="match_parent"> | ||||||
|  |  | ||||||
|         <HorizontalScrollView |         <HorizontalScrollView | ||||||
|  |             android:id="@+id/log_scroll_magisk" | ||||||
|             gone="@{viewModel.loading}" |             gone="@{viewModel.loading}" | ||||||
|             android:layout_width="match_parent" |             android:layout_width="match_parent" | ||||||
|             android:layout_height="match_parent" |             android:layout_height="match_parent" | ||||||
|   | |||||||
| @@ -25,7 +25,7 @@ | |||||||
|  |  | ||||||
|         <include |         <include | ||||||
|             android:id="@+id/log_track_container" |             android:id="@+id/log_track_container" | ||||||
|             bullet="@{item.log.action == 2 ? R.drawable.ic_check_md2 : R.drawable.ic_close_md2}" |             bullet="@{item.log.action >= 2 ? R.drawable.ic_check_md2 : R.drawable.ic_close_md2}" | ||||||
|             isBottom="@{item.isBottom}" |             isBottom="@{item.isBottom}" | ||||||
|             isSelected="@{item.log.action != 2}" |             isSelected="@{item.log.action != 2}" | ||||||
|             isTop="@{item.isTop}" |             isTop="@{item.isTop}" | ||||||
|   | |||||||
| @@ -5,6 +5,8 @@ | |||||||
|  |  | ||||||
|     <data> |     <data> | ||||||
|  |  | ||||||
|  |         <import type="com.topjohnwu.magisk.databinding.DataBindingAdaptersKt" /> | ||||||
|  |  | ||||||
|         <variable |         <variable | ||||||
|             name="item" |             name="item" | ||||||
|             type="com.topjohnwu.magisk.ui.superuser.PolicyRvItem" /> |             type="com.topjohnwu.magisk.ui.superuser.PolicyRvItem" /> | ||||||
| @@ -85,16 +87,32 @@ | |||||||
|                         app:layout_constraintVertical_bias="0" |                         app:layout_constraintVertical_bias="0" | ||||||
|                         tools:text="com.topjohnwu.magisk" /> |                         tools:text="com.topjohnwu.magisk" /> | ||||||
|  |  | ||||||
|                     <com.google.android.material.switchmaterial.SwitchMaterial |                     <FrameLayout | ||||||
|                         android:id="@+id/policy_indicator" |                         android:id="@+id/policy_indicator" | ||||||
|                         android:layout_width="wrap_content" |                         android:layout_width="wrap_content" | ||||||
|                         android:layout_height="wrap_content" |                         android:layout_height="wrap_content" | ||||||
|                         android:layout_marginEnd="@dimen/l1" |                         android:layout_marginEnd="@dimen/l1" | ||||||
|                         android:checked="@={item.enabled}" |  | ||||||
|                         android:nextFocusLeft="@id/policy" |                         android:nextFocusLeft="@id/policy" | ||||||
|                         app:layout_constraintBottom_toBottomOf="parent" |                         app:layout_constraintBottom_toBottomOf="parent" | ||||||
|                         app:layout_constraintEnd_toEndOf="parent" |                         app:layout_constraintEnd_toEndOf="parent" | ||||||
|                         app:layout_constraintTop_toTopOf="parent" /> |                         app:layout_constraintTop_toTopOf="parent"> | ||||||
|  |  | ||||||
|  |                         <com.google.android.material.switchmaterial.SwitchMaterial | ||||||
|  |                             gone="@{item.showSlider}" | ||||||
|  |                             android:layout_width="wrap_content" | ||||||
|  |                             android:layout_height="wrap_content" | ||||||
|  |                             android:checked="@={item.enabled}" /> | ||||||
|  |  | ||||||
|  |                         <com.google.android.material.slider.Slider | ||||||
|  |                             goneUnless="@{item.showSlider}" | ||||||
|  |                             labelFormatter="@{item.sliderValueToPolicyString}" | ||||||
|  |                             android:layout_width="96dp" | ||||||
|  |                             android:layout_height="wrap_content" | ||||||
|  |                             android:stepSize="1" | ||||||
|  |                             android:value="@={DataBindingAdaptersKt.policyToSliderValue(item.sliderValue)}" | ||||||
|  |                             android:valueFrom="1" | ||||||
|  |                             android:valueTo="3" /> | ||||||
|  |                     </FrameLayout> | ||||||
|  |  | ||||||
|                 </androidx.constraintlayout.widget.ConstraintLayout> |                 </androidx.constraintlayout.widget.ConstraintLayout> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,5 +1,11 @@ | |||||||
| tasks.register("clean") { | plugins { | ||||||
|  |     id("MagiskPlugin") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | tasks.register("clean", Delete::class) { | ||||||
|  |     delete(rootProject.layout.buildDirectory) | ||||||
|  |  | ||||||
|     subprojects.forEach { |     subprojects.forEach { | ||||||
|         dependsOn(":app:${it.name}:clean") |         dependsOn(":${it.name}:clean") | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -18,17 +18,12 @@ gradlePlugin { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| kotlin { |  | ||||||
|     compilerOptions { |  | ||||||
|         languageVersion = KotlinVersion.KOTLIN_2_0 |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| dependencies { | dependencies { | ||||||
|     implementation(kotlin("gradle-plugin", libs.versions.kotlin.get())) |     implementation(kotlin("gradle-plugin", libs.versions.kotlin.get())) | ||||||
|     implementation(libs.android.gradle.plugin) |     implementation(libs.android.gradle.plugin) | ||||||
|     implementation(libs.ksp.plugin) |     implementation(libs.ksp.plugin) | ||||||
|     implementation(libs.navigation.safe.args.plugin) |     implementation(libs.navigation.safe.args.plugin) | ||||||
|     implementation(libs.lsparanoid.plugin) |     implementation(libs.lsparanoid.plugin) | ||||||
|  |     implementation(libs.moshi.plugin) | ||||||
|     implementation(libs.jgit) |     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 | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -5,6 +5,12 @@ import org.gradle.api.Project | |||||||
| import org.gradle.kotlin.dsl.provideDelegate | import org.gradle.kotlin.dsl.provideDelegate | ||||||
| import java.io.File | import java.io.File | ||||||
| import java.util.Properties | 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 val props = Properties() | ||||||
| private var commitHash = "" | private var commitHash = "" | ||||||
| @@ -14,7 +20,7 @@ private val defaultAbis = setOf("armeabi-v7a", "x86", "arm64-v8a", "x86_64") | |||||||
| object Config { | object Config { | ||||||
|     operator fun get(key: String): String? { |     operator fun get(key: String): String? { | ||||||
|         val v = props[key] as? String ?: return null |         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 |     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> { | class MagiskPlugin : Plugin<Project> { | ||||||
|     override fun apply(project: Project) = project.applyPlugin() |     override fun apply(project: Project) = project.applyPlugin() | ||||||
|  |  | ||||||
|     private fun Project.applyPlugin() { |     private fun Project.applyPlugin() { | ||||||
|         initRandom(rootProject.file("app/dict.txt")) |         initRandom(rootProject.file("dict.txt")) | ||||||
|         props.clear() |         props.clear() | ||||||
|         rootProject.file("gradle.properties").inputStream().use { props.load(it) } |         rootProject.file("gradle.properties").inputStream().use { props.load(it) } | ||||||
|         val configPath: String? by this |         val configPath: String? by this | ||||||
|         val config = configPath?.let { File(it) } ?: rootProject.file("config.prop") |         val config = rootFile(configPath ?: "config.prop") | ||||||
|         if (config.exists()) |         if (config.exists()) | ||||||
|             config.inputStream().use { props.load(it) } |             config.inputStream().use { props.load(it) } | ||||||
|  |  | ||||||
|         val repo = FileRepository(rootProject.file(".git")) |         val repo = FileRepository(rootFile(".git")) | ||||||
|         val refId = repo.refDatabase.exactRef("HEAD").objectId |         val refId = repo.refDatabase.exactRef("HEAD").objectId | ||||||
|         commitHash = repo.newObjectReader().abbreviate(refId, 8).name() |         commitHash = repo.newObjectReader().abbreviate(refId, 8).name() | ||||||
|     } |     } | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user