1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.net.wifi.mts; 18 19 import android.util.Log; 20 21 import java.io.BufferedReader; 22 import java.io.IOException; 23 import java.io.InputStreamReader; 24 25 /** 26 * Reads from the given BufferedReader and saves the output to a string. 27 */ 28 public class StreamReader extends Thread { 29 private static final String TAG = "ConnMetrics:" + StreamReader.class.getSimpleName(); 30 private BufferedReader mSource; 31 private String mOutput; 32 StreamReader(BufferedReader source)33 public StreamReader(BufferedReader source) { 34 mSource = source; 35 } 36 getOutput()37 public String getOutput() { 38 if (mOutput == null) { 39 throw new IllegalStateException( 40 "Should call start and join before trying to get output"); 41 } 42 return mOutput; 43 } 44 45 @Override run()46 public void run() { 47 StringBuilder sb = new StringBuilder(); 48 String s; 49 try { 50 while ((s = mSource.readLine()) != null) { 51 sb.append(s); 52 sb.append("\n"); 53 } 54 } catch (IOException e) { 55 Log.e(TAG, "Error reading input", e); 56 } finally { 57 try { 58 mSource.close(); 59 } catch (IOException e) { 60 Log.e(TAG, "Error closing reader", e); 61 } 62 } 63 mOutput = sb.toString(); 64 } 65 66 /** 67 * Runs the specified process command and returns the results of the input and error streams. 68 * 69 * @return The output of the input stream, or null if there was an exception. 70 */ runProcessCommand(String command)71 public static String runProcessCommand(String command) { 72 try { 73 Process process = Runtime.getRuntime().exec(command); 74 75 BufferedReader stdInput = new BufferedReader( 76 new InputStreamReader(process.getInputStream())); 77 BufferedReader stdError = new BufferedReader( 78 new InputStreamReader(process.getErrorStream())); 79 StreamReader inputReader = new StreamReader(stdInput); 80 StreamReader errorReader = new StreamReader(stdError); 81 82 inputReader.start(); 83 errorReader.start(); 84 85 process.waitFor(); 86 try { 87 inputReader.join(); 88 } catch (InterruptedException e) { 89 Thread.currentThread().interrupt(); 90 Log.e(TAG, "Error joining thread", e); 91 } 92 try { 93 errorReader.join(); 94 } catch (InterruptedException e) { 95 Thread.currentThread().interrupt(); 96 Log.e(TAG, "Error joining thread", e); 97 } 98 99 // Some commands will return some valid data while also printing a message in 100 // the error stream, so returning result of the input stream regardless of if 101 // there's a message in the error stream. 102 if (errorReader.getOutput().length() > 0) { 103 Log.e(TAG, errorReader.getOutput()); 104 } 105 return inputReader.getOutput(); 106 } catch (IOException e) { 107 Log.e(TAG, "Error running command", e); 108 return null; 109 } catch (InterruptedException e) { 110 Log.e(TAG, "Process was interrupted", e); 111 Thread.currentThread().interrupt(); 112 return null; 113 } 114 } 115 } 116