blob: ca5b0e005a1d21be7b527bde7377e2665ffa8478 [file] [log] [blame]
Andreas Gampe554d7ee2015-09-15 08:57:12 -07001/*
2 * Copyright (C) 2015 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
17package com.android.preload;
18
19import com.android.ddmlib.Client;
20import com.android.ddmlib.IDevice;
21import com.android.preload.actions.ClearTableAction;
22import com.android.preload.actions.ComputeThresholdAction;
23import com.android.preload.actions.ComputeThresholdXAction;
24import com.android.preload.actions.DeviceSpecific;
25import com.android.preload.actions.ExportAction;
26import com.android.preload.actions.ImportAction;
27import com.android.preload.actions.ReloadListAction;
28import com.android.preload.actions.RunMonkeyAction;
29import com.android.preload.actions.ScanAllPackagesAction;
30import com.android.preload.actions.ScanPackageAction;
31import com.android.preload.actions.ShowDataAction;
32import com.android.preload.classdataretrieval.ClassDataRetriever;
33import com.android.preload.classdataretrieval.hprof.Hprof;
34import com.android.preload.classdataretrieval.jdwp.JDWPClassDataRetriever;
35import com.android.preload.ui.UI;
36
37import java.util.ArrayList;
38import java.util.Collection;
39import java.util.List;
40import java.util.Map;
41
42import javax.swing.Action;
43import javax.swing.DefaultListModel;
44
45public class Main {
46
47 /**
48 * Enable tracing mode. This is a work-in-progress to derive compiled-methods data, so it is
49 * off for now.
50 */
51 public final static boolean ENABLE_TRACING = false;
52
53 /**
54 * Ten-second timeout.
55 */
56 public final static int DEFAULT_TIMEOUT_MILLIS = 10 * 1000;
57
58 /**
59 * Hprof timeout. Two minutes.
60 */
61 public final static int HPROF_TIMEOUT_MILLIS = 120 * 1000;
62
63 private IDevice device;
64 private static ClientUtils clientUtils;
65
66 private DumpTableModel dataTableModel;
67 private DefaultListModel<Client> clientListModel;
68
69 private UI ui;
70
71 // Actions that need to be updated once a device is selected.
72 private Collection<DeviceSpecific> deviceSpecificActions;
73
74 // Current main instance.
75 private static Main top;
76 private static boolean useJdwpClassDataRetriever = false;
77
78 public final static String CLASS_PRELOAD_BLACKLIST = "android.app.AlarmManager$" + "|"
79 + "android.app.SearchManager$" + "|" + "android.os.FileObserver$" + "|"
80 + "com.android.server.PackageManagerService\\$AppDirObserver$" + "|" +
81
82
83 // Threads
84 "android.os.AsyncTask$" + "|" + "android.pim.ContactsAsyncHelper$" + "|"
85 + "android.webkit.WebViewClassic\\$1$" + "|" + "java.lang.ProcessManager$" + "|"
86 + "(.*\\$NoPreloadHolder$)";
87
88 /**
89 * @param args
90 */
91 public static void main(String[] args) {
92 Main m = new Main();
93 top = m;
94
95 m.startUp();
96 }
97
98 public Main() {
99 clientListModel = new DefaultListModel<Client>();
100 dataTableModel = new DumpTableModel();
101
102 clientUtils = new ClientUtils(DEFAULT_TIMEOUT_MILLIS); // Client utils with 10s timeout.
103
104 List<Action> actions = new ArrayList<Action>();
105 actions.add(new ReloadListAction(clientUtils, null, clientListModel));
106 actions.add(new ClearTableAction(dataTableModel));
107 actions.add(new RunMonkeyAction(null, dataTableModel));
108 actions.add(new ScanPackageAction(clientUtils, null, dataTableModel));
109 actions.add(new ScanAllPackagesAction(clientUtils, null, dataTableModel));
110 actions.add(new ComputeThresholdAction("Compute preloaded-classes", dataTableModel, 2,
111 CLASS_PRELOAD_BLACKLIST));
112 actions.add(new ComputeThresholdAction("Compute compiled-classes", dataTableModel, 1,
113 null));
114 actions.add(new ComputeThresholdXAction("Compute(X)", dataTableModel,
115 CLASS_PRELOAD_BLACKLIST));
116 actions.add(new ShowDataAction(dataTableModel));
117 actions.add(new ImportAction(dataTableModel));
118 actions.add(new ExportAction(dataTableModel));
119
120 deviceSpecificActions = new ArrayList<DeviceSpecific>();
121 for (Action a : actions) {
122 if (a instanceof DeviceSpecific) {
123 deviceSpecificActions.add((DeviceSpecific)a);
124 }
125 }
126
127 ui = new UI(clientListModel, dataTableModel, actions);
128 ui.setVisible(true);
129 }
130
131 public static UI getUI() {
132 return top.ui;
133 }
134
135 public static ClassDataRetriever getClassDataRetriever() {
136 if (useJdwpClassDataRetriever) {
137 return new JDWPClassDataRetriever();
138 } else {
139 return new Hprof(HPROF_TIMEOUT_MILLIS);
140 }
141 }
142
143 public IDevice getDevice() {
144 return device;
145 }
146
147 public void setDevice(IDevice device) {
148 this.device = device;
149 for (DeviceSpecific ds : deviceSpecificActions) {
150 ds.setDevice(device);
151 }
152 }
153
154 public DefaultListModel<Client> getClientListModel() {
155 return clientListModel;
156 }
157
158 static class DeviceWrapper {
159 IDevice device;
160
161 public DeviceWrapper(IDevice d) {
162 device = d;
163 }
164
165 @Override
166 public String toString() {
167 return device.getName() + " (#" + device.getSerialNumber() + ")";
168 }
169 }
170
171 private void startUp() {
172 getUI().showWaitDialog();
173 initDevice();
174
175 // Load clients.
176 new ReloadListAction(clientUtils, getDevice(), clientListModel).run();
177
178 getUI().hideWaitDialog();
179 }
180
181 private void initDevice() {
182 DeviceUtils.init(DEFAULT_TIMEOUT_MILLIS);
183
184 IDevice devices[] = DeviceUtils.findDevices(DEFAULT_TIMEOUT_MILLIS);
185 if (devices == null || devices.length == 0) {
186 throw new RuntimeException("Could not find any devices...");
187 }
188
189 getUI().hideWaitDialog();
190
191 DeviceWrapper deviceWrappers[] = new DeviceWrapper[devices.length];
192 for (int i = 0; i < devices.length; i++) {
193 deviceWrappers[i] = new DeviceWrapper(devices[i]);
194 }
195
196 DeviceWrapper ret = Main.getUI().showChoiceDialog("Choose a device", "Choose device",
197 deviceWrappers);
198 if (ret != null) {
199 setDevice(ret.device);
200 } else {
201 System.exit(0);
202 }
203
204 boolean prepare = Main.getUI().showConfirmDialog("Prepare device?",
205 "Do you want to prepare the device? This is highly recommended.");
206 if (prepare) {
207 String buildType = DeviceUtils.getBuildType(device);
208 if (buildType == null || (!buildType.equals("userdebug") && !buildType.equals("eng"))) {
209 Main.getUI().showMessageDialog("Need a userdebug or eng build! (Found " + buildType
210 + ")");
211 return;
212 }
213 if (DeviceUtils.hasPrebuiltBootImage(device)) {
214 Main.getUI().showMessageDialog("Cannot prepare a device with pre-optimized boot "
215 + "image!");
216 return;
217 }
218
219 if (ENABLE_TRACING) {
220 DeviceUtils.enableTracing(device);
221 }
222
223 Main.getUI().showMessageDialog("The device will reboot. This will potentially take a "
224 + "long time. Please be patient.");
225 if (!DeviceUtils.removePreloaded(device, 15 * 60) /* 15m timeout */) {
226 Main.getUI().showMessageDialog("Removing preloaded-classes failed unexpectedly!");
227 }
228 }
229 }
230
231 public static Map<String, String> findAndGetClassData(IDevice device, String packageName)
232 throws Exception {
233 Client client = clientUtils.findClient(device, packageName, -1);
234 if (client == null) {
235 throw new RuntimeException("Could not find client...");
236 }
237 System.out.println("Found client: " + client);
238
239 return getClassDataRetriever().getClassData(client);
240 }
241
242}