OSDN Git Service

resolved conflicts for merge of 13ef17a3 to mnc-dr-dev
[android-x86/packages-apps-Launcher3.git] / src / com / android / launcher3 / WeightWatcher.java
1 /*
2  * Copyright (C) 2013 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 com.android.launcher3;
18
19 import android.content.ComponentName;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.ServiceConnection;
23 import android.graphics.Canvas;
24 import android.graphics.Color;
25 import android.graphics.Paint;
26 import android.os.Handler;
27 import android.os.IBinder;
28 import android.os.Message;
29 import android.util.AttributeSet;
30 import android.util.Log;
31 import android.util.TypedValue;
32 import android.view.Gravity;
33 import android.view.View;
34 import android.widget.LinearLayout;
35 import android.widget.TextView;
36
37 import com.android.launcher3.util.Thunk;
38
39 public class WeightWatcher extends LinearLayout {
40     private static final int RAM_GRAPH_RSS_COLOR = 0xFF990000;
41     private static final int RAM_GRAPH_PSS_COLOR = 0xFF99CC00;
42     private static final int TEXT_COLOR = 0xFFFFFFFF;
43     private static final int BACKGROUND_COLOR = 0xc0000000;
44
45     private static final int UPDATE_RATE = 5000;
46
47     private static final int MSG_START = 1;
48     private static final int MSG_STOP = 2;
49     private static final int MSG_UPDATE = 3;
50
51     static int indexOf(int[] a, int x) {
52         for (int i=0; i<a.length; i++) {
53             if (a[i] == x) return i;
54         }
55         return -1;
56     }
57
58     Handler mHandler = new Handler() {
59         @Override
60         public void handleMessage(Message m) {
61             switch (m.what) {
62                 case MSG_START:
63                     mHandler.sendEmptyMessage(MSG_UPDATE);
64                     break;
65                 case MSG_STOP:
66                     mHandler.removeMessages(MSG_UPDATE);
67                     break;
68                 case MSG_UPDATE:
69                     int[] pids = mMemoryService.getTrackedProcesses();
70
71                     final int N = getChildCount();
72                     if (pids.length != N) initViews();
73                     else for (int i=0; i<N; i++) {
74                         ProcessWatcher pw = ((ProcessWatcher) getChildAt(i));
75                         if (indexOf(pids, pw.getPid()) < 0) {
76                             initViews();
77                             break;
78                         }
79                         pw.update();
80                     }
81                     mHandler.sendEmptyMessageDelayed(MSG_UPDATE, UPDATE_RATE);
82                     break;
83             }
84         }
85     };
86     @Thunk MemoryTracker mMemoryService;
87
88     public WeightWatcher(Context context, AttributeSet attrs) {
89         super(context, attrs);
90
91         ServiceConnection connection = new ServiceConnection() {
92             public void onServiceConnected(ComponentName className, IBinder service) {
93                 mMemoryService = ((MemoryTracker.MemoryTrackerInterface)service).getService();
94                 initViews();
95             }
96
97             public void onServiceDisconnected(ComponentName className) {
98                 mMemoryService = null;
99             }
100         };
101         context.bindService(new Intent(context, MemoryTracker.class),
102                 connection, Context.BIND_AUTO_CREATE);
103
104         setOrientation(LinearLayout.VERTICAL);
105
106         setBackgroundColor(BACKGROUND_COLOR);
107     }
108
109     public void initViews() {
110         removeAllViews();
111         int[] processes = mMemoryService.getTrackedProcesses();
112         for (int i=0; i<processes.length; i++) {
113             final ProcessWatcher v = new ProcessWatcher(getContext());
114             v.setPid(processes[i]);
115             addView(v);
116         }
117     }
118
119     public WeightWatcher(Context context) {
120         this(context, null);
121     }
122
123     @Override
124     public void onAttachedToWindow() {
125         super.onAttachedToWindow();
126         mHandler.sendEmptyMessage(MSG_START);
127     }
128
129     @Override
130     public void onDetachedFromWindow() {
131         super.onDetachedFromWindow();
132         mHandler.sendEmptyMessage(MSG_STOP);
133     }
134
135     public class ProcessWatcher extends LinearLayout {
136         GraphView mRamGraph;
137         TextView mText;
138         int mPid;
139         @Thunk MemoryTracker.ProcessMemInfo mMemInfo;
140
141         public ProcessWatcher(Context context) {
142             this(context, null);
143         }
144
145         public ProcessWatcher(Context context, AttributeSet attrs) {
146             super(context, attrs);
147
148             final float dp = getResources().getDisplayMetrics().density;
149
150             mText = new TextView(getContext());
151             mText.setTextColor(TEXT_COLOR);
152             mText.setTextSize(TypedValue.COMPLEX_UNIT_PX, 10 * dp);
153             mText.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
154
155             final int p = (int)(2*dp);
156             setPadding(p, 0, p, 0);
157
158             mRamGraph = new GraphView(getContext());
159
160             LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
161                     0,
162                     (int)(14 * dp),
163                     1f
164             );
165
166             addView(mText, params);
167             params.leftMargin = (int)(4*dp);
168             params.weight = 0f;
169             params.width = (int)(200 * dp);
170             addView(mRamGraph, params);
171         }
172
173         public void setPid(int pid) {
174             mPid = pid;
175             mMemInfo = mMemoryService.getMemInfo(mPid);
176             if (mMemInfo == null) {
177                 Log.v("WeightWatcher", "Missing info for pid " + mPid + ", removing view: " + this);
178                 initViews();
179             }
180         }
181
182         public int getPid() {
183             return mPid;
184         }
185
186         public String getUptimeString() {
187             long sec = mMemInfo.getUptime() / 1000;
188             StringBuilder sb = new StringBuilder();
189             long days = sec / 86400;
190             if (days > 0) {
191                 sec -= days * 86400;
192                 sb.append(days);
193                 sb.append("d");
194             }
195
196             long hours = sec / 3600;
197             if (hours > 0) {
198                 sec -= hours * 3600;
199                 sb.append(hours);
200                 sb.append("h");
201             }
202
203             long mins = sec / 60;
204             if (mins > 0) {
205                 sec -= mins * 60;
206                 sb.append(mins);
207                 sb.append("m");
208             }
209
210             sb.append(sec);
211             sb.append("s");
212             return sb.toString();
213         }
214
215         public void update() {
216             //Log.v("WeightWatcher.ProcessWatcher",
217             //        "MSG_UPDATE pss=" + mMemInfo.currentPss);
218             mText.setText("(" + mPid
219                           + (mPid == android.os.Process.myPid()
220                                 ? "/A"  // app
221                                 : "/S") // service
222                           + ") up " + getUptimeString()
223                           + " P=" + mMemInfo.currentPss
224                           + " U=" + mMemInfo.currentUss
225                           );
226             mRamGraph.invalidate();
227         }
228
229         public class GraphView extends View {
230             Paint pssPaint, ussPaint, headPaint;
231
232             public GraphView(Context context, AttributeSet attrs) {
233                 super(context, attrs);
234
235                 pssPaint = new Paint();
236                 pssPaint.setColor(RAM_GRAPH_PSS_COLOR);
237                 ussPaint = new Paint();
238                 ussPaint.setColor(RAM_GRAPH_RSS_COLOR);
239                 headPaint = new Paint();
240                 headPaint.setColor(Color.WHITE);
241             }
242
243             public GraphView(Context context) {
244                 this(context, null);
245             }
246
247             @Override
248             public void onDraw(Canvas c) {
249                 int w = c.getWidth();
250                 int h = c.getHeight();
251
252                 if (mMemInfo == null) return;
253
254                 final int N = mMemInfo.pss.length;
255                 final float barStep = (float) w / N;
256                 final float barWidth = Math.max(1, barStep);
257                 final float scale = (float) h / mMemInfo.max;
258
259                 int i;
260                 float x;
261                 for (i=0; i<N; i++) {
262                     x = i * barStep;
263                     c.drawRect(x, h - scale * mMemInfo.pss[i], x + barWidth, h, pssPaint);
264                     c.drawRect(x, h - scale * mMemInfo.uss[i], x + barWidth, h, ussPaint);
265                 }
266                 x = mMemInfo.head * barStep;
267                 c.drawRect(x, 0, x + barWidth, h, headPaint);
268             }
269         }
270     }
271 }