From 700ccfcc01d3081ff74ef5006e8f0dec5ac52a96 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Wed, 18 Mar 2009 22:20:25 -0700 Subject: [PATCH] auto import //branches/master/...@140412 --- pdk/docs/source_setup_guide.jd | 97 ++++++++++ simulator/wrapsim/Android.mk | 3 +- simulator/wrapsim/FakeDev.c | 3 + simulator/wrapsim/FakeDev.h | 1 + simulator/wrapsim/SysPower.c | 140 +++++++++++++++ .../android/ddmlib/AndroidDebugBridge.java | 1 + .../src/com/android/ddmlib/HandleHeap.java | 41 +++++ .../src/com/android/ddmlib/HandleHello.java | 37 +++- .../com/android/ddmlib/HandleProfiling.java | 166 ++++++++++++++++++ 9 files changed, 487 insertions(+), 2 deletions(-) create mode 100755 pdk/docs/source_setup_guide.jd create mode 100644 simulator/wrapsim/SysPower.c create mode 100644 tools/ddms/libs/ddmlib/src/com/android/ddmlib/HandleProfiling.java diff --git a/pdk/docs/source_setup_guide.jd b/pdk/docs/source_setup_guide.jd new file mode 100755 index 000000000..af63edb8e --- /dev/null +++ b/pdk/docs/source_setup_guide.jd @@ -0,0 +1,97 @@ +page.title=Android - Source Setup Guide +pdk.version=.4 + +@jd:body + +

This section provides instructions on how to configure your host system to build Android for mobile devices. While Android is designed as host-environment agnostic, it has been tested and is known to work on the following Linux operating system; Ubuntu 6.06 (Dapper), 7.10 (Gutsy), and 8.04. Cygwin is not recommended.

+ + +

Installing Packages

+

Required Packages

+ +

Android requires the following system packages:

+

+ +

Ubuntu 6.06 (Dapper)

+ +

On a clean Dapper system, type the following:

+
 
+% sudo apt-get install flex bison gperf libesd0-dev libwxgtk2.6-dev zlib1g-dev 
+   build-essential
+
+

This snippet includes an artificial line break to maintain a print-friendly document.

+ +

Ubuntu 7.10

+ +
  1. The libwxgtk2.6-dev package will only work if the following code is included in your /etc/apt/source file. +

     
    +## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
    +## team, and may not be under a free license. Please satisfy yourself as to
    +## your rights to use the software. Also, please note that software in
    +## universe WILL NOT receive any review or updates from the Ubuntu security
    +## team.
    +# Line commented out by installer because it failed to verify:
    +deb http://us.archive.ubuntu.com/ubuntu/ gutsy universe
    +# Line commented out by installer because it failed to verify:
    +deb-src http://us.archive.ubuntu.com/ubuntu/ gutsy universe
    +# Line commented out by installer because it failed to verify:
    +deb http://us.archive.ubuntu.com/ubuntu/ gutsy-updates universe
    +# Line commented out by installer because it failed to verify:
    +deb-src http://us.archive.ubuntu.com/ubuntu/ gutsy-updates universe
    +

  2. +
  3. Install required packages with the following command: +

     
    +% sudo apt-get install flex bison gperf libesd0-dev libwxgtk2.6-dev zlib1g-dev
    +   build-essential
    +

    +This snippet includes an artificial line break to maintain a print-friendly document. +
  4. +
  5. +

    Install the X11 development environment with the following commands:

    +

     
    +% sudo apt-get install x-dev
    +% sudo apt-get install libx11-dev
    +% sudo apt-get install libncurses5-dev
    +

    +
  6. +
+ + +

Ubuntu 8.04

+ +

On a clean system, type the following:

+
 
+% sudo apt-get install flex bison gperf libesd0-dev libwxgtk2.6-dev
+zlib1g-dev build-essential
+% sudo apt-get install x-dev
+% sudo apt-get install libx11-dev
+% sudo apt-get install libncurses5-dev
+% sudo apt-get install sun-java5-jdk
+
+ +

Installing Java

+ +

Android source code includes a hard dependency on the Java Developer Kit (JDK) 5.0 Update 12 or greater. The specific file name of the Update 12 package is jdk-1_5_0_12-linux-i586.bin. To download this version of the Java JDK:

+

    +
  1. Navigate to: http://java.sun.com/products/archive/.
  2. +
  3. Select '5.0 Update 12' from the 'Java 2 Platform Standard Edition (J2SE)' -> 'JDK/JRE - 5.0' field and click 'Go.'
  4. +
  5. Click 'Download JDK.'
  6. +
  7. In the 'Linux Platform' section, click 'Linux self-extracting file' associated with the jdk-1_5_0_12-linux-i586.bin package.
  8. +
  9. Follow the installation instructions.
  10. +
+

+ +

Once you have cleanly installed the JDK, modify your PATH environment variable to include <jdk-install-dir>/jdk1.5.0_12/bin at its beginning so that Dapper will use the correct installation.

+

Ubuntu 7.10

+

An alternative method to quickly install Java is to enable multiverse repo in /etc/apt/sources.list and then execute:

+
 
+% sudo apt-get install sun-java5-jdk
+
+ diff --git a/simulator/wrapsim/Android.mk b/simulator/wrapsim/Android.mk index ca9a5928c..0b7890d23 100644 --- a/simulator/wrapsim/Android.mk +++ b/simulator/wrapsim/Android.mk @@ -22,7 +22,8 @@ LOCAL_SRC_FILES := \ Init.c \ Intercept.c \ Log.c \ - SimMgr.c + SimMgr.c \ + SysPower.c LOCAL_C_INCLUDES += prebuilt/common/esd diff --git a/simulator/wrapsim/FakeDev.c b/simulator/wrapsim/FakeDev.c index 3e223d363..7d2494eb4 100644 --- a/simulator/wrapsim/FakeDev.c +++ b/simulator/wrapsim/FakeDev.c @@ -67,6 +67,9 @@ FakedPath fakedpaths[] = { "/dev/input/*", NULL }, { "/dev/log/*", wsOpenDevLog }, { "/sys/class/power_supply/*", wsOpenDevPower }, + { "/sys/power/state", wsOpenSysPower }, + { "/sys/power/wake_lock", wsOpenSysPower }, + { "/sys/power/wake_unlock", wsOpenSysPower }, { "/sys/devices/platform/android-vibrator/enable", wsOpenDevVibrator }, { "/sys/qemu_trace/*", NULL }, { NULL, NULL } diff --git a/simulator/wrapsim/FakeDev.h b/simulator/wrapsim/FakeDev.h index eacbbf55d..4781cfc4d 100644 --- a/simulator/wrapsim/FakeDev.h +++ b/simulator/wrapsim/FakeDev.h @@ -108,6 +108,7 @@ FakeDev* wsOpenDevEvent(const char* pathName, int flags); FakeDev* wsOpenDevFb(const char* pathName, int flags); FakeDev* wsOpenDevLog(const char* pathName, int flags); FakeDev* wsOpenDevPower(const char* pathName, int flags); +FakeDev* wsOpenSysPower(const char* pathName, int flags); FakeDev* wsOpenDevVibrator(const char* pathName, int flags); /* diff --git a/simulator/wrapsim/SysPower.c b/simulator/wrapsim/SysPower.c new file mode 100644 index 000000000..fa7ae0ad3 --- /dev/null +++ b/simulator/wrapsim/SysPower.c @@ -0,0 +1,140 @@ +/* + * Copyright 2009 The Android Open Source Project + * + * Magic entries in /sys/power/. + */ +#include "Common.h" + +#include +#include +#include + +/* + * Map filename to device index. + * + * [ not using DeviceIndex -- would be useful if we need to return something + * other than a static string ] + */ +static const struct { + const char* name; + //DeviceIndex idx; + const char* data; +} gDeviceMap[] = { + { "state", + "mem\n" }, + { "wake_lock", + "\n" }, + { "wake_unlock", + "KeyEvents PowerManagerService radio-interface\n" }, +}; + +/* + * Power driver state. + * + * Right now we just ignore everything written. + */ +typedef struct PowerState { + int which; +} PowerState; + + +/* + * Figure out who we are, based on "pathName". + */ +static void configureInitialState(const char* pathName, PowerState* powerState) +{ + const char* cp = pathName + strlen("/sys/power/"); + int i; + + powerState->which = -1; + for (i = 0; i < (int) (sizeof(gDeviceMap) / sizeof(gDeviceMap[0])); i++) { + if (strcmp(cp, gDeviceMap[i].name) == 0) { + powerState->which = i; + break; + } + } + + if (powerState->which == -1) { + wsLog("Warning: access to unknown power device '%s'\n", pathName); + return; + } +} + +/* + * Free up the state structure. + */ +static void freeState(PowerState* powerState) +{ + free(powerState); +} + +/* + * Read data from the device. + * + * We don't try to keep track of how much was read -- existing clients just + * try to read into a large buffer. + */ +static ssize_t readPower(FakeDev* dev, int fd, void* buf, size_t count) +{ + PowerState* state = (PowerState*) dev->state; + int dataLen; + + wsLog("%s: read %d\n", dev->debugName, count); + + if (state->which < 0 || + state->which >= (int) (sizeof(gDeviceMap)/sizeof(gDeviceMap[0]))) + { + return 0; + } + + const char* data = gDeviceMap[state->which].data; + size_t strLen = strlen(data); + + while(strLen == 0) + sleep(10); // block forever + + ssize_t copyCount = (strLen < count) ? strLen : count; + memcpy(buf, data, copyCount); + return copyCount; +} + +/* + * Ignore the request. + */ +static ssize_t writePower(FakeDev* dev, int fd, const void* buf, size_t count) +{ + wsLog("%s: write %d bytes\n", dev->debugName, count); + return count; +} + +/* + * Free up our state before closing down the fake descriptor. + */ +static int closePower(FakeDev* dev, int fd) +{ + freeState((PowerState*)dev->state); + dev->state = NULL; + return 0; +} + +/* + * Open a power device. + */ +FakeDev* wsOpenSysPower(const char* pathName, int flags) +{ + FakeDev* newDev = wsCreateFakeDev(pathName); + if (newDev != NULL) { + newDev->read = readPower; + newDev->write = writePower; + newDev->ioctl = NULL; + newDev->close = closePower; + + PowerState* powerState = calloc(1, sizeof(PowerState)); + + configureInitialState(pathName, powerState); + newDev->state = powerState; + } + + return newDev; +} + diff --git a/tools/ddms/libs/ddmlib/src/com/android/ddmlib/AndroidDebugBridge.java b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/AndroidDebugBridge.java index 795bf886a..0957171c6 100644 --- a/tools/ddms/libs/ddmlib/src/com/android/ddmlib/AndroidDebugBridge.java +++ b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/AndroidDebugBridge.java @@ -194,6 +194,7 @@ public final class AndroidDebugBridge { HandleThread.register(monitorThread); HandleHeap.register(monitorThread); HandleWait.register(monitorThread); + HandleProfiling.register(monitorThread); } /** diff --git a/tools/ddms/libs/ddmlib/src/com/android/ddmlib/HandleHeap.java b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/HandleHeap.java index 5752b861a..51116387e 100644 --- a/tools/ddms/libs/ddmlib/src/com/android/ddmlib/HandleHeap.java +++ b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/HandleHeap.java @@ -32,6 +32,7 @@ final class HandleHeap extends ChunkHandler { public static final int CHUNK_HPEN = type("HPEN"); public static final int CHUNK_HPSG = type("HPSG"); public static final int CHUNK_HPGC = type("HPGC"); + public static final int CHUNK_HPDU = type("HPDU"); public static final int CHUNK_REAE = type("REAE"); public static final int CHUNK_REAQ = type("REAQ"); public static final int CHUNK_REAL = type("REAL"); @@ -98,6 +99,8 @@ final class HandleHeap extends ChunkHandler { client.update(Client.CHANGE_HEAP_DATA); } else if (type == CHUNK_HPSG) { handleHPSG(client, data); + } else if (type == CHUNK_HPDU) { + handleHPDU(client, data); } else if (type == CHUNK_REAQ) { handleREAQ(client, data); client.update(Client.CHANGE_HEAP_ALLOCATION_STATUS); @@ -220,6 +223,44 @@ final class HandleHeap extends ChunkHandler { client.sendAndConsume(packet, mInst); } + /** + * Sends an HPDU request to the client. + * + * We will get an HPDU response when the heap dump has completed. On + * failure we get a generic failure response. + * + * @param fileName name of output file (on device) + */ + public static void sendHPDU(Client client, String fileName) + throws IOException { + ByteBuffer rawBuf = allocBuffer(4 + fileName.length() * 2); + JdwpPacket packet = new JdwpPacket(rawBuf); + ByteBuffer buf = getChunkDataBuf(rawBuf); + + buf.putInt(fileName.length()); + putString(buf, fileName); + + finishChunkPacket(packet, CHUNK_HPDU, buf.position()); + Log.d("ddm-heap", "Sending " + name(CHUNK_HPDU) + " '" + fileName +"'"); + client.sendAndConsume(packet, mInst); + } + + /* + * Handle notification of completion of a HeaP DUmp. + */ + private void handleHPDU(Client client, ByteBuffer data) { + byte result; + + result = data.get(); + + if (result == 0) { + Log.i("ddm-heap", "Heap dump request has finished"); + // TODO: stuff + } else { + Log.w("ddm-heap", "Heap dump request failed (check device log)"); + } + } + /** * Sends a REAE (REcent Allocation Enable) request to the client. */ diff --git a/tools/ddms/libs/ddmlib/src/com/android/ddmlib/HandleHello.java b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/HandleHello.java index 5ba5aeb8f..fb9697cce 100644 --- a/tools/ddms/libs/ddmlib/src/com/android/ddmlib/HandleHello.java +++ b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/HandleHello.java @@ -20,11 +20,12 @@ import java.io.IOException; import java.nio.ByteBuffer; /** - * Handle the "hello" chunk (HELO). + * Handle the "hello" chunk (HELO) and feature discovery. */ final class HandleHello extends ChunkHandler { public static final int CHUNK_HELO = ChunkHandler.type("HELO"); + public static final int CHUNK_FEAT = ChunkHandler.type("FEAT"); private static final HandleHello mInst = new HandleHello(); @@ -65,6 +66,8 @@ final class HandleHello extends ChunkHandler { if (type == CHUNK_HELO) { assert isReply; handleHELO(client, data); + } else if (type == CHUNK_FEAT) { + handleFEAT(client, data); } else { handleUnknownChunk(client, type, data, isReply, msgId); } @@ -126,5 +129,37 @@ final class HandleHello extends ChunkHandler { + " ID=0x" + Integer.toHexString(packet.getId())); client.sendAndConsume(packet, mInst); } + + /** + * Handle a reply to our FEAT request. + */ + private static void handleFEAT(Client client, ByteBuffer data) { + int featureCount; + int i; + + featureCount = data.getInt(); + for (i = 0; i < featureCount; i++) { + int len = data.getInt(); + String feature = getString(data, len); + + Log.d("ddm-hello", "Feature: " + feature); + } + } + + /** + * Send a FEAT request to the client. + */ + public static void sendFEAT(Client client) throws IOException { + ByteBuffer rawBuf = allocBuffer(0); + JdwpPacket packet = new JdwpPacket(rawBuf); + ByteBuffer buf = getChunkDataBuf(rawBuf); + + // no data + + finishChunkPacket(packet, CHUNK_FEAT, buf.position()); + Log.d("ddm-heap", "Sending " + name(CHUNK_FEAT)); + client.sendAndConsume(packet, mInst); + } + } diff --git a/tools/ddms/libs/ddmlib/src/com/android/ddmlib/HandleProfiling.java b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/HandleProfiling.java new file mode 100644 index 000000000..078965565 --- /dev/null +++ b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/HandleProfiling.java @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.ddmlib; + +import java.io.IOException; +import java.nio.ByteBuffer; + +/** + * Handle heap status updates. + */ +final class HandleProfiling extends ChunkHandler { + + public static final int CHUNK_MPRS = type("MPRS"); + public static final int CHUNK_MPRE = type("MPRE"); + public static final int CHUNK_MPRQ = type("MPRQ"); + + private static final HandleProfiling mInst = new HandleProfiling(); + + private HandleProfiling() {} + + /** + * Register for the packets we expect to get from the client. + */ + public static void register(MonitorThread mt) { + mt.registerChunkHandler(CHUNK_MPRE, mInst); + mt.registerChunkHandler(CHUNK_MPRQ, mInst); + } + + /** + * Client is ready. + */ + @Override + public void clientReady(Client client) throws IOException {} + + /** + * Client went away. + */ + @Override + public void clientDisconnected(Client client) {} + + /** + * Chunk handler entry point. + */ + @Override + public void handleChunk(Client client, int type, ByteBuffer data, + boolean isReply, int msgId) { + + Log.d("ddm-prof", "handling " + ChunkHandler.name(type)); + + if (type == CHUNK_MPRE) { + handleMPRE(client, data); + } else if (type == CHUNK_MPRQ) { + handleMPRQ(client, data); + } else { + handleUnknownChunk(client, type, data, isReply, msgId); + } + } + + /** + * Send a MPRS (Method PRofiling Start) request to the client. + * + * The arguments to this method will eventually be passed to + * android.os.Debug.startMethodTracing() on the device. + * + * @param fileName is the name of the file to which profiling data + * will be written (on the device); it will have ".trace" + * appended if necessary + * @param bufferSize is the desired buffer size in bytes (8MB is good) + * @param flags see startMethodTracing() docs; use 0 for default behavior + */ + public static void sendMPRS(Client client, String fileName, int bufferSize, + int flags) throws IOException { + + ByteBuffer rawBuf = allocBuffer(3*4 + fileName.length() * 2); + JdwpPacket packet = new JdwpPacket(rawBuf); + ByteBuffer buf = getChunkDataBuf(rawBuf); + + buf.putInt(bufferSize); + buf.putInt(flags); + buf.putInt(fileName.length()); + putString(buf, fileName); + + finishChunkPacket(packet, CHUNK_MPRS, buf.position()); + Log.d("ddm-prof", "Sending " + name(CHUNK_MPRS) + " '" + fileName + + "', size=" + bufferSize + ", flags=" + flags); + client.sendAndConsume(packet, mInst); + } + + /** + * Send a MPRE (Method PRofiling End) request to the client. + */ + public static void sendMPRE(Client client) throws IOException { + ByteBuffer rawBuf = allocBuffer(0); + JdwpPacket packet = new JdwpPacket(rawBuf); + ByteBuffer buf = getChunkDataBuf(rawBuf); + + // no data + + finishChunkPacket(packet, CHUNK_MPRE, buf.position()); + Log.d("ddm-prof", "Sending " + name(CHUNK_MPRE)); + client.sendAndConsume(packet, mInst); + } + + /** + * Handle notification that method profiling has finished writing + * data to disk. + */ + private void handleMPRE(Client client, ByteBuffer data) { + byte result; + + result = data.get(); + + if (result == 0) { + Log.i("ddm-prof", "Method profiling has finished"); + } else { + Log.w("ddm-prof", "Method profiling has failed (check device log)"); + } + + // TODO: stuff + } + + /** + * Send a MPRQ (Method PRofiling Query) request to the client. + */ + public static void sendMPRQ(Client client) throws IOException { + ByteBuffer rawBuf = allocBuffer(0); + JdwpPacket packet = new JdwpPacket(rawBuf); + ByteBuffer buf = getChunkDataBuf(rawBuf); + + // no data + + finishChunkPacket(packet, CHUNK_MPRQ, buf.position()); + Log.d("ddm-prof", "Sending " + name(CHUNK_MPRQ)); + client.sendAndConsume(packet, mInst); + } + + /** + * Receive response to query. + */ + private void handleMPRQ(Client client, ByteBuffer data) { + byte result; + + result = data.get(); + + if (result == 0) { + Log.i("ddm-prof", "Method profiling is not running"); + } else { + Log.i("ddm-prof", "Method profiling is running"); + } + } +} +