1 package com.android.internal.os; 2 3 import android.os.StrictMode; 4 import android.os.SystemClock; 5 import android.text.TextUtils; 6 import android.util.LongSparseLongArray; 7 import android.util.Slog; 8 9 import com.android.internal.annotations.VisibleForTesting; 10 11 import java.io.BufferedReader; 12 import java.io.FileNotFoundException; 13 import java.io.FileReader; 14 import java.io.IOException; 15 16 /** 17 * Reads DDR time spent at various frequencies and stores the data. Supports diff comparison with 18 * other KernelMemoryBandwidthStats objects. The sysfs file has the format: 19 * 20 * freq time_in_bucket ... time_in_bucket 21 * ... 22 * freq time_in_bucket ... time_in_bucket 23 * 24 * where time is measured in nanoseconds. 25 */ 26 public class KernelMemoryBandwidthStats { 27 private static final String TAG = "KernelMemoryBandwidthStats"; 28 29 private static final String mSysfsFile = "/sys/kernel/memory_state_time/show_stat"; 30 private static final boolean DEBUG = false; 31 32 protected final LongSparseLongArray mBandwidthEntries = new LongSparseLongArray(); 33 private boolean mStatsDoNotExist = false; 34 updateStats()35 public void updateStats() { 36 if (mStatsDoNotExist) { 37 // Skip reading. 38 return; 39 } 40 41 final long startTime = SystemClock.uptimeMillis(); 42 43 StrictMode.ThreadPolicy policy = StrictMode.allowThreadDiskReads(); 44 try (BufferedReader reader = new BufferedReader(new FileReader(mSysfsFile))) { 45 parseStats(reader); 46 } catch (FileNotFoundException e) { 47 Slog.w(TAG, "No kernel memory bandwidth stats available"); 48 mBandwidthEntries.clear(); 49 mStatsDoNotExist = true; 50 } catch (IOException e) { 51 Slog.e(TAG, "Failed to read memory bandwidth: " + e.getMessage()); 52 mBandwidthEntries.clear(); 53 } finally { 54 StrictMode.setThreadPolicy(policy); 55 } 56 57 final long readTime = SystemClock.uptimeMillis() - startTime; 58 if (DEBUG || readTime > 100) { 59 Slog.w(TAG, "Reading memory bandwidth file took " + readTime + "ms"); 60 } 61 } 62 63 @VisibleForTesting parseStats(BufferedReader reader)64 public void parseStats(BufferedReader reader) throws IOException { 65 String line; 66 TextUtils.SimpleStringSplitter splitter = new TextUtils.SimpleStringSplitter(' '); 67 mBandwidthEntries.clear(); 68 while ((line = reader.readLine()) != null) { 69 splitter.setString(line); 70 splitter.next(); 71 int bandwidth = 0; 72 int index; 73 do { 74 if ((index = mBandwidthEntries.indexOfKey(bandwidth)) >= 0) { 75 mBandwidthEntries.put(bandwidth, mBandwidthEntries.valueAt(index) 76 + Long.parseLong(splitter.next()) / 1000000); 77 } else { 78 mBandwidthEntries.put(bandwidth, Long.parseLong(splitter.next()) / 1000000); 79 } 80 if (DEBUG) { 81 Slog.d(TAG, String.format("bandwidth: %s time: %s", bandwidth, 82 mBandwidthEntries.get(bandwidth))); 83 } 84 bandwidth++; 85 } while(splitter.hasNext()); 86 } 87 } 88 getBandwidthEntries()89 public LongSparseLongArray getBandwidthEntries() { 90 return mBandwidthEntries; 91 } 92 } 93