@@ -39,6 +39,11 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton
39
39
import com.google.android.material.snackbar.Snackbar
40
40
import kotlinx.coroutines.*
41
41
import kotlinx.coroutines.Dispatchers.Default
42
+ import java.io.BufferedReader
43
+ import java.io.BufferedWriter
44
+ import java.io.InputStreamReader
45
+ import java.io.OutputStreamWriter
46
+ import java.util.*
42
47
43
48
class LogcatLiveFragment : BaseFragment (), ServiceConnection, LogsReceivedListener {
44
49
companion object {
@@ -678,17 +683,11 @@ class LogcatLiveFragment : BaseFragment(), ServiceConnection, LogsReceivedListen
678
683
dialog.show(fragmentManager, AskingForRootAccessDialogFragment .TAG )
679
684
680
685
val result = withContext(Dispatchers .IO ) {
681
- val cmd = " pm grant ${BuildConfig .APPLICATION_ID } ${Manifest .permission.READ_LOGS } "
682
- try {
683
- val process = Runtime .getRuntime().exec(arrayOf(" su" , " -c" , cmd))
684
- process.waitFor()
685
- } catch (e: Exception ) {
686
- - 1
687
- }
686
+ grantPermissionWithSu()
688
687
}
689
688
690
689
dialog.dismissAllowingStateLoss()
691
- if (result == 0 ) {
690
+ if (result) {
692
691
RestartAppMessageDialogFragment .newInstance().show(fragmentManager,
693
692
RestartAppMessageDialogFragment .TAG )
694
693
} else {
@@ -699,6 +698,69 @@ class LogcatLiveFragment : BaseFragment(), ServiceConnection, LogsReceivedListen
699
698
}
700
699
}
701
700
701
+ private fun BufferedWriter.writeCmd (cmd : String ) {
702
+ write(cmd)
703
+ newLine()
704
+ flush()
705
+ }
706
+
707
+ private suspend fun grantPermissionWithSu () = coroutineScope {
708
+ try {
709
+ val processBuilder = ProcessBuilder (" su" )
710
+ val process = processBuilder.start()
711
+
712
+ val stdoutWriter = BufferedWriter (OutputStreamWriter (process.outputStream))
713
+ val stdinReader = BufferedReader (InputStreamReader (process.inputStream))
714
+ val stderrReader = BufferedReader (InputStreamReader (process.errorStream))
715
+
716
+ val marker = " RESULT>>>${UUID .randomUUID()} >>>"
717
+ val stdoutResult = async {
718
+ var result = false
719
+
720
+ try {
721
+ while (true ) {
722
+ val line = stdinReader.readLine()?.trim() ? : break
723
+
724
+ val index = line.indexOf(marker)
725
+ if (index != - 1 ) {
726
+ result = line.substring(index + marker.length) == " 0"
727
+ break
728
+ }
729
+ }
730
+ } catch (e: Exception ) {
731
+ }
732
+
733
+ result
734
+ }
735
+
736
+ val stderrReaderResult = async {
737
+ try {
738
+ while (true ) {
739
+ stderrReader.readLine()?.trim() ? : break
740
+ }
741
+ } catch (e: Exception ) {
742
+ }
743
+ }
744
+
745
+ val cmd = " pm grant ${BuildConfig .APPLICATION_ID } ${Manifest .permission.READ_LOGS } "
746
+ stdoutWriter.writeCmd(cmd)
747
+ stdoutWriter.writeCmd(" echo \" $marker $?\" " )
748
+
749
+ val finalResult = stdoutResult.await()
750
+
751
+ stdoutWriter.writeCmd(" exit" )
752
+
753
+ process.waitFor()
754
+ process.destroy()
755
+
756
+ stderrReaderResult.await()
757
+
758
+ finalResult
759
+ } catch (e: Exception ) {
760
+ false
761
+ }
762
+ }
763
+
702
764
private class LogFilter (filterInfo : FilterInfo ) : Filter {
703
765
val type = filterInfo.type
704
766
val content = filterInfo.content
0 commit comments