IT_Programming/Android_Java

루팅 여부 판별! Runtime.getRuntime().exec() 주의

JJun ™ 2013. 7. 16. 07:25

 


 출처: http://lsit81.tistory.com/category/Android/이슈%20정리


 

 

안녕하세요... 

이번에 안드로이드에서 루팅여부를 체크하기 위해서 다음과 같이 구현을 하였습니다. 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
 * 루팅된 디바이스인지 체크.
 *
 * @return
 */
private static boolean checkRootingDevice() {
    boolean isRootingFlag = false;
 
    // 일부 내용 생략
    ...
     
    try {
        Process         process = Runtime.getRuntime().exec("find / -name su");
         
        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()), 1024);
                 
        String      result = reader.readLine();
        if (result.contains("/su") == true) {
            isRootingFlag = true;
        }
         
    } catch ( Exception e) {
        isRootingFlag = false;
    }
     
    return isRootingFlag;
}


 



그러나 정말 극히 적은 확률로 "reader.readLine()"에서 무한 루프가 발생되는 것이

확인되었습니다. 

 

이 문제가 발생된 원인은 InputStreamReader.read(char[] buffer, int offset, int length)을 보면

아래와 같이 구현된 것을 확인 할 수 있습니다. 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
@Override
public int read(char[] buffer, int offset, int length) throws IOException {
    synchronized (lock) {
        if (!isOpen()) {
            throw new IOException("InputStreamReader is closed");
        }
 
        Arrays.checkOffsetAndCount(buffer.length, offset, length);
        if (length == 0) {
            return 0;
        }
 
        CharBuffer out = CharBuffer.wrap(buffer, offset, length);
        CoderResult result = CoderResult.UNDERFLOW;
 
        // bytes.remaining() indicates number of bytes in buffer
        // when 1-st time entered, it'll be equal to zero
        boolean needInput = !bytes.hasRemaining();
 
        while (out.hasRemaining()) {
            // fill the buffer if needed
            if (needInput) {
                try {
                    if (in.available() == 0 && out.position() > offset) {
                        // we could return the result without blocking read
                        break;
                    }
                } catch (IOException e) {
                    // available didn't work so just try the read
                }
 
                // 생략
                ....
            }
 
            // 생략
            ....
        }
 
        // 이하 생략
        ....
    }
}
<textarea>



문제는 "if (in.available() == 0 && out.position() > offset) "을 보면 알겠지만 읽어올 데이터가 없고

현재까지 읽은 데이터가 없으면 무한루프에 빠질 수 있다는 것입니다. 


정확히 왜 무한루프가 발생되며, 어떤 케이스에서 무한 루프가 발생되는지는

확인이 되지는 않았지만 현재 이 문제를 해결하기위해 아래와 같이 처리하였습니다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
try {
    Process         process = Runtime.getRuntime().exec("find / -name su");
     
    /** Process가 동작될 시간적 여유를 줌. **/
    Thread.sleep(10);
     
    BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
    if (reader.ready() == false) {
        return false;
    }
     
    String      result = reader.readLine();
    if (result.contains("/su") == true) {
        isRootingFlag = true;
    }
     
} catch ( Exception e) {
    isRootingFlag = false;
}



혹시 이러한 문제가 정확히 왜 발생되는지 아시는 분 계시면 공유 부탁드립니다. ^^


참고 :

 

 

 

 

"Runtime.getRuntime().exec(String)" 명령은 비동기로 동작됩니다. 

  Runtime.getRuntime().exec()로 프로세스를 실행후 해당 결과를 얻기 위해서는

  프로세스가 종료될때까지 대기를 해주는 로직이 필요합니다.