내 앱에서 글로벌 su
인스턴스를 사용할 수있게하려고합니다. 나는 그것을하는 코드를 가지고 있지만, 나는 경쟁 조건에 부딪쳤다 고 나는 믿는다.Java 런타임 .exec 사용자 입력 경쟁 조건
public static List<Object> rootObjects = Collections.synchronizedList(new ArrayList<>());
protected void onCreate(Bundle savedInstanceState) {
...
if(PreferenceManager.getDefaultSharedPreferences(
getApplicationContext()).getBoolean("use_su", false) && rootObjects.isEmpty())
{
try {
Process process = Runtime.getRuntime().exec("su");
rootObjects.add(process);
InputStream inputStream = new DataInputStream(process.getInputStream());
rootObjects.add(inputStream);
OutputStream outputStream = new DataOutputStream(process.getOutputStream());
rootObjects.add(outputStream);
} catch (IOException e) {
Log.d(MainActivity.mainActivity.getPackageName(), e.getLocalizedMessage());
}
finally {
synchronized (rootObjects) {
rootObjects.notifyAll();
}
}
}
}
을 등처럼 그들을 사용 :
그래서 같은 su
에 대한 몇 가지 변수를 저장하고
byte[] getPrivateKeyAsSuperUser() {
byte[] data = null;
DataInputStream inputStream = null;
DataOutputStream outputStream = null;
if(MainActivity.rootObjects.size() != 3)
synchronized (MainActivity.rootObjects)
{
try {
MainActivity.rootObjects.wait();
} catch (InterruptedException e) {
Log.d(MainActivity.mainActivity.getPackageName(), e.getLocalizedMessage());
}
}
for(Object rootObj : MainActivity.rootObjects)
{
if(rootObj instanceof DataInputStream)
inputStream = (DataInputStream) rootObj;
else if(rootObj instanceof DataOutputStream)
outputStream = (DataOutputStream) rootObj;
}
try {
outputStream.writeBytes(String.format("cat \"%s\"\n", sshPrivateKey.getAbsolutePath()));
outputStream.flush();
data = readStream(inputStream);
} catch (IOException e) {
Log.d(MainActivity.mainActivity.getPackageName(), e.getLocalizedMessage());
}
return data;
}
private byte[] readStream(InputStream stream) {
byte[] data = null;
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte buff[] = new byte[1024];
int count = 0;
while (stream.available() != 0 && (count = stream.read(buff)) != -1) {
bos.write(buff, 0, count);
}
data = bos.toByteArray();
//System.out.println(new String(data));
} catch (IOException e) {
Log.d(MainActivity.mainActivity.getPackageName(), e.getLocalizedMessage());
}
return data;
}
를하지만 기대처럼 기다리지 않습니다, 나는 즉시 Toast
을 받도록 반환 된 비공개 키가 내 성성 검사에 유효하지 않습니다 (아마도 null 일 것입니다).
Process
초기화가 완료되면 코드가 작동하지만 프로그램에서 저를 대신 수행하고 싶습니다.
나는 잠금과 같은 다른 동기화 기술을 시도해 보았지만, 오브젝트에 잠금 기능이 있는지 알게되면 정보가 오래되었습니다.
Process
이 제대로 초기화되지 않은 경우 호출자에게 getPrivateKeyAsSuperUser()
대기를 허용하는 가장 안전한 스레드 접근 방식은 무엇입니까?
편집 :
내가 디버깅을 통해이를 추가 할, 나는 발견했다 나는 (내가 무엇을해야하는 것이 없기 때문에) 프로세스가 초기화 될 때까지 기다리는 것이 아니라는 것을 할 싶지 않아 su
에 의해 생성 된 셸은 추가 명령을 받아 들일 수 있습니다. 나는 내가 DONE
을 얻을 때까지 echo DONE
과 같은 스레드 파이프를 가질 수 있다고 생각하지만, CPU 마력을 낭비하는 것처럼 보입니다. 누군가 주제에 대해 지식을 빌려줄 수 있다면 매우 감사하게 생각합니다.
당신은 절대적으로 정확합니다. 그래서 당신은 상향 투표권을 가질 자격이 있습니다. 나는 싱글 톤을 사용해야한다.내 애플 리케이션에서 다른 곳에서, 그리고 내가 왜 여기에 없었는지 모르겠다. 그러나, 나는'su '가 말하는 "대화 형"이되도록 내 쉘을 기다리는 데 도움이 필요하다 (실제 질문). 그것에 대한 제안이 있습니까? – MeetTitan