summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThe Android Open Source Project2008-12-17 20:08:08 -0600
committerThe Android Open Source Project2008-12-17 20:08:08 -0600
commit35237d135807af84bf9b0e5b8d7f8633e58db6f5 (patch)
treed8bcf3ada2182d248604728285dd80abb466f22a
parent4f6e8d7a00cbeda1e70cc15be9c4af1018bdad53 (diff)
downloadplatform-system-core-35237d135807af84bf9b0e5b8d7f8633e58db6f5.tar.gz
platform-system-core-35237d135807af84bf9b0e5b8d7f8633e58db6f5.tar.xz
platform-system-core-35237d135807af84bf9b0e5b8d7f8633e58db6f5.zip
Code drop from //branches/cupcake/...@124589
-rw-r--r--Android.mk3
-rw-r--r--adb/Android.mk48
-rw-r--r--adb/OVERVIEW.TXT139
-rw-r--r--adb/SERVICES.TXT245
-rw-r--r--adb/adb.c108
-rw-r--r--adb/adb.h23
-rw-r--r--adb/adb_client.c26
-rw-r--r--adb/commandline.c56
-rw-r--r--adb/file_sync_client.c26
-rw-r--r--adb/file_sync_service.c6
-rw-r--r--adb/framebuffer_service.c9
-rw-r--r--adb/get_my_path_windows.c12
-rw-r--r--adb/jdwp_service.c4
-rw-r--r--adb/sockets.c162
-rw-r--r--adb/sysdeps_win32.c116
-rw-r--r--adb/transport_local.c15
-rw-r--r--adb/transport_usb.c12
-rw-r--r--adb/usb_linux_client.c2
-rw-r--r--adb/usb_osx.c22
-rw-r--r--adb/usb_windows.c18
-rw-r--r--adb/utils.c106
-rw-r--r--adb/utils.h68
-rw-r--r--cpio/Android.mk2
-rw-r--r--debuggerd/Android.mk4
-rw-r--r--debuggerd/unwind-arm.c50
-rw-r--r--debuggerd/utility.c7
-rw-r--r--debuggerd/utility.h2
-rw-r--r--fastboot/Android.mk2
-rw-r--r--fastboot/fastboot.c15
-rw-r--r--include/arch/linux-arm/AndroidConfig.h6
-rw-r--r--include/arch/target_linux-x86/AndroidConfig.h296
-rw-r--r--include/cutils/tztime.h15
-rw-r--r--include/pixelflinger/format.h5
-rw-r--r--include/private/android_filesystem_config.h4
-rw-r--r--include/private/pixelflinger/ggl_context.h10
-rw-r--r--init/README.BOOTCHART44
-rw-r--r--init/bootchart.c73
-rw-r--r--init/bootchart.h36
-rw-r--r--init/builtins.c46
-rw-r--r--init/devices.c21
-rwxr-xr-xinit/grab-bootchart.sh4
-rw-r--r--init/init.c21
-rw-r--r--init/keywords.h2
-rw-r--r--init/parser.c1
-rw-r--r--init/property_service.c2
-rw-r--r--init/readme.txt3
-rw-r--r--libcutils/Android.mk11
-rw-r--r--libcutils/atomic-android-arm.S52
-rw-r--r--libcutils/tzstrftime.c834
-rw-r--r--libnetutils/dhcp_utils.c16
-rw-r--r--libpixelflinger/Android.mk3
-rw-r--r--libpixelflinger/codeflinger/GGLAssembler.cpp63
-rw-r--r--libpixelflinger/codeflinger/GGLAssembler.h5
-rw-r--r--libpixelflinger/codeflinger/blending.cpp6
-rw-r--r--libpixelflinger/codeflinger/load_store.cpp2
-rw-r--r--libpixelflinger/codeflinger/texturing.cpp43
-rw-r--r--libpixelflinger/format.cpp4
-rw-r--r--libpixelflinger/scanline.cpp15
-rw-r--r--libpixelflinger/tests/Android.mk1
-rw-r--r--libpixelflinger/tests/codegen/Android.mk15
-rw-r--r--libpixelflinger/tests/codegen/codegen.cpp21
-rw-r--r--logcat/event-log-tags20
-rw-r--r--logwrapper/logwrapper.c99
-rw-r--r--mkbootimg/Android.mk2
-rw-r--r--mountd/ASEC.c770
-rw-r--r--mountd/ASEC.h66
-rw-r--r--mountd/Android.mk3
-rw-r--r--mountd/AutoMount.c210
-rw-r--r--mountd/ProcessKiller.c19
-rw-r--r--mountd/Server.c81
-rw-r--r--mountd/dm-ioctl.h304
-rw-r--r--mountd/mountd.c76
-rw-r--r--mountd/mountd.h37
-rw-r--r--rootdir/Android.mk6
-rw-r--r--rootdir/etc/dbus.conf50
-rw-r--r--rootdir/etc/hcid.conf64
-rw-r--r--rootdir/etc/init.goldfish.rc9
-rw-r--r--rootdir/etc/mountd.conf6
-rw-r--r--rootdir/init.rc12
-rw-r--r--toolbox/Android.mk5
80 files changed, 4248 insertions, 579 deletions
diff --git a/Android.mk b/Android.mk
index 44ea560be..8b79cebad 100644
--- a/Android.mk
+++ b/Android.mk
@@ -19,8 +19,9 @@ ifneq ($(TARGET_SIMULATOR),true)
19 include $(call first-makefiles-under,$(LOCAL_PATH)) 19 include $(call first-makefiles-under,$(LOCAL_PATH))
20else 20else
21 include $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \ 21 include $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \
22 adb \
22 libcutils \ 23 libcutils \
23 liblog \ 24 liblog \
24 libnetutils \ 25 libnetutils \
25 libpixelflinger \ 26 libpixelflinger \
26 libzipfile \ 27 libzipfile \
diff --git a/adb/Android.mk b/adb/Android.mk
index 8ac5eb437..c06485fbb 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -7,6 +7,7 @@ LOCAL_PATH:= $(call my-dir)
7 7
8# adb host tool 8# adb host tool
9# ========================================================= 9# =========================================================
10ifneq ($(TARGET_SIMULATOR),true) # not 64 bit clean (also unused with the sim)
10include $(CLEAR_VARS) 11include $(CLEAR_VARS)
11 12
12# Default to a virtual (sockets) usb interface 13# Default to a virtual (sockets) usb interface
@@ -29,7 +30,7 @@ ifeq ($(HOST_OS),windows)
29 USB_SRCS := usb_windows.c 30 USB_SRCS := usb_windows.c
30 EXTRA_SRCS := get_my_path_windows.c 31 EXTRA_SRCS := get_my_path_windows.c
31 EXTRA_STATIC_LIBS := AdbWinApi 32 EXTRA_STATIC_LIBS := AdbWinApi
32 LOCAL_C_INCLUDES += /usr/include/w32api/ddk $(LOCAL_PATH)/../windows/usb/api 33 LOCAL_C_INCLUDES += /usr/include/w32api/ddk development/host/windows/usb/api/
33 ifneq ($(strip $(USE_CYGWIN)),) 34 ifneq ($(strip $(USE_CYGWIN)),)
34 LOCAL_LDLIBS += -lpthread 35 LOCAL_LDLIBS += -lpthread
35 else 36 else
@@ -51,7 +52,8 @@ LOCAL_SRC_FILES := \
51 file_sync_client.c \ 52 file_sync_client.c \
52 $(EXTRA_SRCS) \ 53 $(EXTRA_SRCS) \
53 $(USB_SRCS) \ 54 $(USB_SRCS) \
54 shlist.c 55 shlist.c \
56 utils.c \
55 57
56 58
57ifneq ($(USE_SYSDEPS_WIN32),) 59ifneq ($(USE_SYSDEPS_WIN32),)
@@ -69,6 +71,8 @@ endif
69 71
70include $(BUILD_HOST_EXECUTABLE) 72include $(BUILD_HOST_EXECUTABLE)
71 73
74$(call dist-for-goals,droid,$(LOCAL_BUILT_MODULE))
75
72ifeq ($(HOST_OS),windows) 76ifeq ($(HOST_OS),windows)
73$(LOCAL_INSTALLED_MODULE): $(HOST_OUT_EXECUTABLES)/AdbWinApi.dll 77$(LOCAL_INSTALLED_MODULE): $(HOST_OUT_EXECUTABLES)/AdbWinApi.dll
74endif 78endif
@@ -81,10 +85,25 @@ LOCAL_MODULE := kdbg
81include $(BUILD_HOST_EXECUTABLE) 85include $(BUILD_HOST_EXECUTABLE)
82endif 86endif
83 87
88endif
84 89
85# adbd device daemon 90# adbd device daemon
86# ========================================================= 91# =========================================================
87ifeq ($(TARGET_ARCH),arm) 92
93# build adbd in all non-simulator builds
94BUILD_ADBD := false
95ifneq ($(TARGET_SIMULATOR),true)
96 BUILD_ADBD := true
97endif
98
99# build adbd for the Linux simulator build
100# so we can use it to test the adb USB gadget driver on x86
101ifeq ($(HOST_OS),linux)
102 BUILD_ADBD := true
103endif
104
105
106ifeq ($(BUILD_ADBD),true)
88include $(CLEAR_VARS) 107include $(CLEAR_VARS)
89 108
90LOCAL_SRC_FILES := \ 109LOCAL_SRC_FILES := \
@@ -99,18 +118,31 @@ LOCAL_SRC_FILES := \
99 framebuffer_service.c \ 118 framebuffer_service.c \
100 remount_service.c \ 119 remount_service.c \
101 usb_linux_client.c \ 120 usb_linux_client.c \
102 log_service.c 121 log_service.c \
122 utils.c \
103 123
104 124LOCAL_CFLAGS := -O2 -g -DADB_HOST=0 -Wall -Wno-unused-parameter
105LOCAL_CFLAGS := -O2 -g -DADB_HOST=0 -DANDROID_GADGET=1 -Wall -Wno-unused-parameter
106LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE 125LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE
126
127# TODO: This should probably be board specific, whether or not the kernel has
128# the gadget driver; rather than relying on the architecture type.
129ifeq ($(TARGET_ARCH),arm)
130LOCAL_CFLAGS += -DANDROID_GADGET=1
131endif
132
107LOCAL_MODULE := adbd 133LOCAL_MODULE := adbd
108 134
109LOCAL_FORCE_STATIC_EXECUTABLE := true 135LOCAL_FORCE_STATIC_EXECUTABLE := true
110LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN) 136LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN)
111LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED) 137LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED)
112 138
113LOCAL_STATIC_LIBRARIES := libcutils libc 139ifeq ($(TARGET_SIMULATOR),true)
140 LOCAL_STATIC_LIBRARIES := libcutils
141 LOCAL_LDLIBS += -lpthread
142 include $(BUILD_HOST_EXECUTABLE)
143else
144 LOCAL_STATIC_LIBRARIES := libcutils libc
145 include $(BUILD_EXECUTABLE)
146endif
114 147
115include $(BUILD_EXECUTABLE)
116endif 148endif
diff --git a/adb/OVERVIEW.TXT b/adb/OVERVIEW.TXT
new file mode 100644
index 000000000..6a5191aee
--- /dev/null
+++ b/adb/OVERVIEW.TXT
@@ -0,0 +1,139 @@
1Implementation notes regarding ADB.
2
3I. General Overview:
4
5The Android Debug Bridge (ADB) is used to:
6
7- keep track of all Android devices and emulators instances
8 connected to or running on a given host developer machine
9
10- implement various control commands (e.g. "adb shell", "adb pull", etc..)
11 for the benefit of clients (command-line users, or helper programs like
12 DDMS). These commands are what is called a 'service' in ADB.
13
14As a whole, everything works through the following components:
15
16 1. The ADB server
17
18 This is a background process that runs on the host machine. Its purpose
19 if to sense the USB ports to know when devices are attached/removed,
20 as well as when emulator instances start/stop.
21
22 It thus maintains a list of "connected devices" and assigns a 'state'
23 to each one of them: OFFLINE, BOOTLOADER, RECOVERY or ONLINE (more on
24 this below).
25
26 The ADB server is really one giant multiplexing loop whose purpose is
27 to orchestrate the exchange of data (packets, really) between clients,
28 services and devices.
29
30
31 2. The ADB daemon (adbd)
32
33 The 'adbd' program runs as a background process within an Android device
34 or emulated system. Its purpose is to connect to the ADB server
35 (through USB for devices, through TCP for emulators) and provide a
36 few services for clients that run on the host.
37
38 The ADB server considers that a device is ONLINE when it has succesfully
39 connected to the adbd program within it. Otherwise, the device is OFFLINE,
40 meaning that the ADB server detected a new device/emulator, but could not
41 connect to the adbd daemon.
42
43 the BOOTLOADER and RECOVERY states correspond to alternate states of
44 devices when they are in the bootloader or recovery mode.
45
46 3. The ADB command-line client
47
48 The 'adb' command-line program is used to run adb commands from a shell
49 or a script. It first tries to locate the ADB server on the host machine,
50 and will start one automatically if none is found.
51
52 then, the client sends its service requests to the ADB server. It doesn't
53 need to know.
54
55 Currently, a single 'adb' binary is used for both the server and client.
56 this makes distribution and starting the server easier.
57
58
59 4. Services
60
61 There are essentially two kinds of services that a client can talk to.
62
63 Host Services:
64 these services run within the ADB Server and thus do not need to
65 communicate with a device at all. A typical example is "adb devices"
66 which is used to return the list of currently known devices and their
67 state. They are a few couple other services though.
68
69 Local Services:
70 these services either run within the adbd daemon, or are started by
71 it on the device. The ADB server is used to multiplex streams
72 between the client and the service running in adbd. In this case
73 its role is to initiate the connection, then of being a pass-through
74 for the data.
75
76
77II. Protocol details:
78
79 1. Client <-> Server protocol:
80
81 This details the protocol used between ADB clients and the ADB
82 server itself. The ADB server listens on TCP:localhost:5037.
83
84 A client sends a request using the following format:
85
86 1. A 4-byte hexadecimal string giving the length of the payload
87 2. Followed by the payload itself.
88
89 For example, to query the ADB server for its internal version number,
90 the client will do the following:
91
92 1. Connect to tcp:localhost:5037
93 2. Send the string "000Chost:version" to the corresponding socket
94
95 The 'host:' prefix is used to indicate that the request is addressed
96 to the server itself (we will talk about other kinds of requests later).
97 The content length is encoded in ASCII for easier debugging.
98
99 The server should answer a request with one of the following:
100
101 1. For success, the 4-byte "OKAY" string
102
103 2. For failure, the 4-byte "FAIL" string, followed by a
104 4-byte hex length, followed by a string giving the reason
105 for failure.
106
107 3. As a special exception, for 'host:version', a 4-byte
108 hex string corresponding to the server's internal version number
109
110 Note that the connection is still alive after an OKAY, which allows the
111 client to make other requests. But in certain cases, an OKAY will even
112 change the state of the connection.
113
114 For example, the case of the 'host:transport:<serialnumber>' request,
115 where '<serialnumber>' is used to identify a given device/emulator; after
116 the "OKAY" answer, all further requests made by the client will go
117 directly to the corresponding adbd daemon.
118
119 The file SERVICES.TXT lists all services currently implemented by ADB.
120
121
122 2. Transports:
123
124 An ADB transport models a connection between the ADB server and one device
125 or emulator. There are currently two kinds of transports:
126
127 - USB transports, for physical devices through USB
128
129 - Local transports, for emulators running on the host, connected to
130 the server through TCP
131
132 In theory, it should be possible to write a local transport that proxies
133 a connection between an ADB server and a device/emulator connected to/
134 running on another machine. This hasn't been done yet though.
135
136 Each transport can carry one or more multiplexed streams between clients
137 and the device/emulator they point to. The ADB server must handle
138 unexpected transport disconnections (e.g. when a device is physically
139 unplugged) properly.
diff --git a/adb/SERVICES.TXT b/adb/SERVICES.TXT
new file mode 100644
index 000000000..d059e181f
--- /dev/null
+++ b/adb/SERVICES.TXT
@@ -0,0 +1,245 @@
1This file tries to document all requests a client can make
2to the ADB server of an adbd daemon. See the OVERVIEW.TXT document
3to understand what's going on here.
4
5HOST SERVICES:
6
7host:version
8 Ask the ADB server for its internal version number.
9
10 As a special exception, the server will respond with a 4-byte
11 hex string corresponding to its internal version number, without
12 any OKAY or FAIL.
13
14host:kill
15 Ask the ADB server to quit immediately. This is used when the
16 ADB client detects that an obsolete server is running after an
17 upgrade.
18
19host:devices
20 Ask to return the list of available Android devices and their
21 state. After the OKAY, this is followed by a 4-byte hex len,
22 and a string that will be dumped as-is by the client, then
23 the connection is closed
24
25host:track-devices
26 This is a variant of host:devices which doesn't close the
27 connection. Instead, a new device list description is sent
28 each time a device is added/removed or the state of a given
29 device changes (hex4 + content). This allows tools like DDMS
30 to track the state of connected devices in real-time without
31 polling the server repeatedly.
32
33host:emulator:<port>
34 This is a special query that is sent to the ADB server when a
35 new emulator starts up. <port> is a decimal number corresponding
36 to the emulator's ADB control port, i.e. the TCP port that the
37 emulator will forward automatically to the adbd daemon running
38 in the emulator system.
39
40 This mechanism allows the ADB server to know when new emulator
41 instances start.
42
43host:transport:<serial-number>
44 Ask to switch the connection to the device/emulator identified by
45 <serial-number>. After the OKAY response, every client request will
46 be sent directly to the adbd daemon running on the device.
47 (Used to implement the -s option)
48
49host:transport-usb
50 Ask to switch the connection to one device connected through USB
51 to the host machine. This will fail if there are more than one such
52 devices. (Used to implement the -d convenience option)
53
54host:transport-local
55 Ask to switch the connection to one emulator connected through TCP.
56 This will fail if there is more than one such emulator instance
57 running. (Used to implement the -e convenience option)
58
59host:transport-any
60 Another host:transport variant. Ask to switch the connection to
61 either the device or emulator connect to/running on the host.
62 Will fail if there is more than one such device/emulator available.
63 (Used when neither -s, -d or -e are provided)
64
65host-serial:<serial-number>:<request>
66 This is a special form of query, where the 'host-serial:<serial-number>:'
67 prefix can be used to indicate that the client is asking the ADB server
68 for information related to a specific device. <request> can be in one
69 of the format described below.
70
71host-usb:<request>
72 A variant of host-serial used to target the single USB device connected
73 to the host. This will fail if there is none or more than one.
74
75host-local:<request>
76 A variant of host-serial used to target the single emulator instance
77 running on the host. This will fail if therre is none or more than one.
78
79host:<request>
80 When asking for information related to a device, 'host:' can also be
81 interpreted as 'any single device or emulator connected to/running on
82 the host'.
83
84<host-prefix>:get-product
85 XXX
86
87<host-prefix>:get-serialno
88 Returns the serial number of the corresponding device/emulator.
89 Note that emulator serial numbers are of the form "emulator-5554"
90
91<host-prefix>:get-state
92 Returns the state of a given device as a string.
93
94<host-prefix>:forward:<local>:<remote>
95 Asks the ADB server to forward local connections from <local>
96 to the <remote> address on a given device.
97
98 There, <host-prefix> can be one of the
99 host-serial/host-usb/host-local/host prefixes as described previously
100 and indicates which device/emulator to target.
101
102 the format of <local> is one of:
103
104 tcp:<port> -> TCP connection on localhost:<port>
105 local:<path> -> Unix local domain socket on <path>
106
107 the format of <remote> is one of:
108
109 tcp:<port> -> TCP localhost:<port> on device
110 local:<path> -> Unix local domain socket on device
111 jdwp:<pid> -> JDWP thread on VM process <pid>
112
113 or even any one of the local services described below.
114
115
116
117LOCAL SERVICES:
118
119All the queries below assumed that you already switched the transport
120to a real device, or that you have used a query prefix as described
121above.
122
123shell:command arg1 arg2 ...
124 Run 'command arg1 arg2 ...' in a shell on the device, and return
125 its output and error streams. Note that arguments must be separated
126 by spaces. If an argument contains a space, it must be quoted with
127 double-quotes. Arguments cannot contain double quotes or things
128 will go very wrong.
129
130 Note that this is the non-interactive version of "adb shell"
131
132shell:
133 Start an interactive shell session on the device. Redirect
134 stdin/stdout/stderr as appropriate. Note that the ADB server uses
135 this to implement "adb shell", but will also cook the input before
136 sending it to the device (see interactive_shell() in commandline.c)
137
138bootdebug:
139 Ask debugging information to the bootloader. The adbd daemon will
140 respond with FAIL to this request.
141
142bootloader:<command>
143 Send a request to the bootloader. This can also work if the device
144 is currently in the bootloader state. The adbd daemon will respond
145 with FAIL to such requests.
146
147remount:
148 Ask adbd to remount the device's filesystem in read-write mode,
149 instead of read-only. This is usually necessary before performing
150 an "adb sync" or "adb push" request.
151
152 This request may not succeed on certain builds which do not allow
153 that.
154
155dev:<path>
156 Opens a device file and connects the client directly to it for
157 read/write purposes. Useful for debugging, but may require special
158 priviledges and thus may not run on all devices. <path> is a full
159 path from the root of the filesystem.
160
161tcp:<port>
162 Tries to connect to tcp port <port> on localhost.
163
164tcp:<port>:<server-name>
165 Tries to connect to tcp port <port> on machine <server-name> from
166 the device. This can be useful to debug some networking/proxy
167 issues that can only be revealed on the device itself.
168
169local:<path>
170 Tries to connect to a Unix domain socket <path> on the device
171
172localreserved:<path>
173localabstract:<path>
174localfilesystem:<path>
175 Variants of local:<path> that are used to access other Android
176 socket namespaces.
177
178log:<name>
179 Opens one of the system logs (/dev/log/<name>) and allows the client
180 to read them directly. Used to implement 'adb logcat'. The stream
181 will be read-only for the client.
182
183framebuffer:
184 This service is used to send snapshots of the framebuffer to a client.
185 It requires sufficient priviledges but works as follow:
186
187 After the OKAY, the service sends 16-byte binary structure
188 containing the following fields (little-endian format):
189
190 depth: uint32_t: framebuffer depth
191 size: uint32_t: framebuffer size in bytes
192 width: uint32_t: framebuffer width in pixels
193 height: uint32_t: framebuffer height in pixels
194
195 With the current implementation, depth is always 16, and
196 size is always width*height*2
197
198 Then, each time the client wants a snapshot, it should send
199 one byte through the channel, which will trigger the service
200 to send it 'size' bytes of framebuffer data.
201
202 If the adbd daemon doesn't have sufficient priviledges to open
203 the framebuffer device, the connection is simply closed immediately.
204
205dns:<server-name>
206 This service is an exception because it only runs within the ADB server.
207 It is used to implement USB networking, i.e. to provide a network connection
208 to the device through the host machine (note: this is the exact opposite of
209 network thetering).
210
211 It is used to perform a gethostbyname(<address>) on the host and return
212 the corresponding IP address as a 4-byte string.
213
214recover:<size>
215 This service is used to upload a recovery image to the device. <size>
216 must be a number corresponding to the size of the file. The service works
217 by:
218
219 - creating a file named /tmp/update
220 - reading 'size' bytes from the client and writing them to /tmp/update
221 - when everything is read succesfully, create a file named /tmp/update.start
222
223 This service can only work when the device is in recovery mode. Otherwise,
224 the /tmp directory doesn't exist and the connection will be closed immediately.
225
226jdwp:<pid>
227 Connects to the JDWP thread running in the VM of process <pid>.
228
229track-jdwp
230 This is used to send the list of JDWP pids periodically to the client.
231 The format of the returned data is the following:
232
233 <hex4>: the length of all content as a 4-char hexadecimal string
234 <content>: a series of ASCII lines of the following format:
235 <pid> "\n"
236
237 This service is used by DDMS to know which debuggable processes are running
238 on the device/emulator.
239
240 Note that there is no single-shot service to retrieve the list only once.
241
242sync:
243 This starts the file synchronisation service, used to implement "adb push"
244 and "adb pull". Since this service is pretty complex, it will be detailed
245 in a companion document named SYNC.TXT
diff --git a/adb/adb.c b/adb/adb.c
index a50ef334b..27d0c8156 100644
--- a/adb/adb.c
+++ b/adb/adb.c
@@ -67,59 +67,59 @@ int adb_trace_mask;
67 */ 67 */
68void adb_trace_init(void) 68void adb_trace_init(void)
69{ 69{
70 const char* p = getenv("ADB_TRACE"); 70 const char* p = getenv("ADB_TRACE");
71 const char* q; 71 const char* q;
72 72
73 static const struct { 73 static const struct {
74 const char* tag; 74 const char* tag;
75 int flag; 75 int flag;
76 } tags[] = { 76 } tags[] = {
77 { "1", 0 }, 77 { "1", 0 },
78 { "all", 0 }, 78 { "all", 0 },
79 { "adb", TRACE_ADB }, 79 { "adb", TRACE_ADB },
80 { "sockets", TRACE_SOCKETS }, 80 { "sockets", TRACE_SOCKETS },
81 { "packets", TRACE_PACKETS }, 81 { "packets", TRACE_PACKETS },
82 { "rwx", TRACE_RWX }, 82 { "rwx", TRACE_RWX },
83 { "usb", TRACE_USB }, 83 { "usb", TRACE_USB },
84 { "sync", TRACE_SYNC }, 84 { "sync", TRACE_SYNC },
85 { "sysdeps", TRACE_SYSDEPS }, 85 { "sysdeps", TRACE_SYSDEPS },
86 { "transport", TRACE_TRANSPORT }, 86 { "transport", TRACE_TRANSPORT },
87 { "jdwp", TRACE_JDWP }, 87 { "jdwp", TRACE_JDWP },
88 { NULL, 0 } 88 { NULL, 0 }
89 }; 89 };
90 90
91 if (p == NULL) 91 if (p == NULL)
92 return; 92 return;
93 93
94 /* use a comma/column/semi-colum/space separated list */ 94 /* use a comma/column/semi-colum/space separated list */
95 while (*p) { 95 while (*p) {
96 int len, tagn; 96 int len, tagn;
97 97
98 q = strpbrk(p, " ,:;"); 98 q = strpbrk(p, " ,:;");
99 if (q == NULL) { 99 if (q == NULL) {
100 q = p + strlen(p); 100 q = p + strlen(p);
101 } 101 }
102 len = q - p; 102 len = q - p;
103 103
104 for (tagn = 0; tags[tagn].tag != NULL; tagn++) 104 for (tagn = 0; tags[tagn].tag != NULL; tagn++)
105 { 105 {
106 int taglen = strlen(tags[tagn].tag); 106 int taglen = strlen(tags[tagn].tag);
107 107
108 if (len == taglen && !memcmp(tags[tagn].tag, p, len) ) 108 if (len == taglen && !memcmp(tags[tagn].tag, p, len) )
109 { 109 {
110 int flag = tags[tagn].flag; 110 int flag = tags[tagn].flag;
111 if (flag == 0) { 111 if (flag == 0) {
112 adb_trace_mask = ~0; 112 adb_trace_mask = ~0;
113 return; 113 return;
114 } 114 }
115 adb_trace_mask |= (1 << flag); 115 adb_trace_mask |= (1 << flag);
116 break; 116 break;
117 } 117 }
118 } 118 }
119 p = q; 119 p = q;
120 if (*p) 120 if (*p)
121 p++; 121 p++;
122 } 122 }
123} 123}
124 124
125 125
@@ -783,8 +783,8 @@ int launch_server()
783 783
784 // child process 784 // child process
785 int result = execl(path, "adb", "fork-server", "server", NULL); 785 int result = execl(path, "adb", "fork-server", "server", NULL);
786 // this should not return 786 // this should not return
787 fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno); 787 fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno);
788 } else { 788 } else {
789 // parent side of the fork 789 // parent side of the fork
790 790
@@ -894,7 +894,7 @@ int adb_main(int is_daemon)
894 if(access("/dev/android_adb", F_OK) == 0 || 894 if(access("/dev/android_adb", F_OK) == 0 ||
895 access("/dev/android", F_OK) == 0) { 895 access("/dev/android", F_OK) == 0) {
896 usb_init(); 896 usb_init();
897 } else { 897 } else {
898 local_init(); 898 local_init();
899 } 899 }
900 init_jdwp(); 900 init_jdwp();
diff --git a/adb/adb.h b/adb/adb.h
index 5a74b7b9a..a17c8ddc5 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -79,6 +79,11 @@ struct asocket {
79 */ 79 */
80 unsigned id; 80 unsigned id;
81 81
82 /* flag: set when the socket's peer has closed
83 ** but packets are still queued for delivery
84 */
85 int closing;
86
82 /* the asocket we are connected to 87 /* the asocket we are connected to
83 */ 88 */
84 89
@@ -309,15 +314,15 @@ int writex(int fd, const void *ptr, size_t len);
309 * the adb_trace_init() function implemented in adb.c 314 * the adb_trace_init() function implemented in adb.c
310 */ 315 */
311typedef enum { 316typedef enum {
312 TRACE_ADB = 0, 317 TRACE_ADB = 0,
313 TRACE_SOCKETS, 318 TRACE_SOCKETS,
314 TRACE_PACKETS, 319 TRACE_PACKETS,
315 TRACE_TRANSPORT, 320 TRACE_TRANSPORT,
316 TRACE_RWX, 321 TRACE_RWX,
317 TRACE_USB, 322 TRACE_USB,
318 TRACE_SYNC, 323 TRACE_SYNC,
319 TRACE_SYSDEPS, 324 TRACE_SYSDEPS,
320 TRACE_JDWP, 325 TRACE_JDWP,
321} AdbTrace; 326} AdbTrace;
322 327
323#if ADB_TRACE 328#if ADB_TRACE
diff --git a/adb/adb_client.c b/adb/adb_client.c
index c1b87ee51..586874480 100644
--- a/adb/adb_client.c
+++ b/adb/adb_client.c
@@ -211,7 +211,7 @@ int adb_connect(const char *service)
211 return -1; 211 return -1;
212 } else { 212 } else {
213 fprintf(stdout,"* daemon started successfully *\n"); 213 fprintf(stdout,"* daemon started successfully *\n");
214 } 214 }
215 /* give the server some time to start properly and detect devices */ 215 /* give the server some time to start properly and detect devices */
216 adb_sleep_ms(2000); 216 adb_sleep_ms(2000);
217 // fall through to _adb_connect 217 // fall through to _adb_connect
@@ -223,13 +223,13 @@ int adb_connect(const char *service)
223 223
224 // if we have a file descriptor, then parse version result 224 // if we have a file descriptor, then parse version result
225 if(fd >= 0) { 225 if(fd >= 0) {
226 if(readx(fd, buf, 4)) goto error; 226 if(readx(fd, buf, 4)) goto error;
227 227
228 buf[4] = 0; 228 buf[4] = 0;
229 n = strtoul(buf, 0, 16); 229 n = strtoul(buf, 0, 16);
230 if(n > (int)sizeof(buf)) goto error; 230 if(n > (int)sizeof(buf)) goto error;
231 if(readx(fd, buf, n)) goto error; 231 if(readx(fd, buf, n)) goto error;
232 adb_close(fd); 232 adb_close(fd);
233 233
234 if (sscanf(buf, "%04x", &version) != 1) goto error; 234 if (sscanf(buf, "%04x", &version) != 1) goto error;
235 } else { 235 } else {
@@ -240,14 +240,14 @@ int adb_connect(const char *service)
240 } 240 }
241 241
242 if(version != ADB_SERVER_VERSION) { 242 if(version != ADB_SERVER_VERSION) {
243 printf("adb server is out of date. killing...\n"); 243 printf("adb server is out of date. killing...\n");
244 fd = _adb_connect("host:kill"); 244 fd = _adb_connect("host:kill");
245 adb_close(fd); 245 adb_close(fd);
246 246
247 /* XXX can we better detect its death? */ 247 /* XXX can we better detect its death? */
248 adb_sleep_ms(2000); 248 adb_sleep_ms(2000);
249 goto start_server; 249 goto start_server;
250 } 250 }
251 } 251 }
252 252
253 // if the command is start-server, we are done. 253 // if the command is start-server, we are done.
diff --git a/adb/commandline.c b/adb/commandline.c
index c1ef8b011..cbf079c40 100644
--- a/adb/commandline.c
+++ b/adb/commandline.c
@@ -296,8 +296,8 @@ static void *stdin_read_thread(void *x)
296 buf_ptr[cmdlen] = '\0'; 296 buf_ptr[cmdlen] = '\0';
297 if( (item = shListFindItem( &history, (void *)buf_ptr, shItemCmp )) == NULL ) { 297 if( (item = shListFindItem( &history, (void *)buf_ptr, shItemCmp )) == NULL ) {
298 shListInsFirstItem( &history, (void *)buf_ptr ); 298 shListInsFirstItem( &history, (void *)buf_ptr );
299 item = &history; 299 item = &history;
300 } 300 }
301 } 301 }
302 } 302 }
303 cmdlen = 0; 303 cmdlen = 0;
@@ -322,8 +322,8 @@ static void *stdin_read_thread(void *x)
322 default: 322 default:
323#ifdef SH_HISTORY 323#ifdef SH_HISTORY
324 if( buf[n] == SH_DEL_CHAR ) { 324 if( buf[n] == SH_DEL_CHAR ) {
325 if( cmdlen > 0 ) 325 if( cmdlen > 0 )
326 cmdlen--; 326 cmdlen--;
327 } 327 }
328 else { 328 else {
329 realbuf[cmdlen] = buf[n]; 329 realbuf[cmdlen] = buf[n];
@@ -478,7 +478,7 @@ static void status_window(transport_type ttype, const char* serial)
478#ifdef _WIN32 478#ifdef _WIN32
479 /* XXX: TODO */ 479 /* XXX: TODO */
480#else 480#else
481 int fd; 481 int fd;
482 fd = unix_open("/dev/null", O_WRONLY); 482 fd = unix_open("/dev/null", O_WRONLY);
483 dup2(fd, 2); 483 dup2(fd, 2);
484 adb_close(fd); 484 adb_close(fd);
@@ -512,7 +512,7 @@ static void status_window(transport_type ttype, const char* serial)
512 } 512 }
513} 513}
514 514
515/** duplicate string and quote all \ " ( ) chars */ 515/** duplicate string and quote all \ " ( ) chars + space character. */
516static char * 516static char *
517dupAndQuote(const char *s) 517dupAndQuote(const char *s)
518{ 518{
@@ -527,7 +527,7 @@ dupAndQuote(const char *s)
527 527
528 for( ;*ts != '\0'; ts++) { 528 for( ;*ts != '\0'; ts++) {
529 alloc_len++; 529 alloc_len++;
530 if (*ts == '"' || *ts == '\\') { 530 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
531 alloc_len++; 531 alloc_len++;
532 } 532 }
533 } 533 }
@@ -538,7 +538,7 @@ dupAndQuote(const char *s)
538 dest = ret; 538 dest = ret;
539 539
540 for ( ;*ts != '\0'; ts++) { 540 for ( ;*ts != '\0'; ts++) {
541 if (*ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') { 541 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
542 *dest++ = '\\'; 542 *dest++ = '\\';
543 } 543 }
544 544
@@ -561,7 +561,7 @@ int ppp(int argc, char **argv)
561{ 561{
562#ifdef HAVE_WIN32_PROC 562#ifdef HAVE_WIN32_PROC
563 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]); 563 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
564 return -1; 564 return -1;
565#else 565#else
566 char *adb_service_name; 566 char *adb_service_name;
567 pid_t pid; 567 pid_t pid;
@@ -657,8 +657,8 @@ static int logcat(transport_type transport, char* serial, int argc, char **argv)
657 quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags); 657 quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags);
658 658
659 snprintf(buf, sizeof(buf), 659 snprintf(buf, sizeof(buf),
660 "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat", 660 "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
661 quoted_log_tags); 661 quoted_log_tags);
662 662
663 free(quoted_log_tags); 663 free(quoted_log_tags);
664 664
@@ -847,7 +847,7 @@ int adb_commandline(int argc, char **argv)
847 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') { 847 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
848 gProductOutPath = NULL; 848 gProductOutPath = NULL;
849 } 849 }
850 // TODO: also try TARGET_PRODUCT as a hint 850 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
851 851
852 /* modifiers and flags */ 852 /* modifiers and flags */
853 while(argc > 0) { 853 while(argc > 0) {
@@ -1077,15 +1077,15 @@ top:
1077 return 1; 1077 return 1;
1078 } 1078 }
1079 1079
1080 /* Allow a command to be run after wait-for-device, 1080 /* Allow a command to be run after wait-for-device,
1081 * e.g. 'adb wait-for-device shell'. 1081 * e.g. 'adb wait-for-device shell'.
1082 */ 1082 */
1083 if(argc > 1) { 1083 if(argc > 1) {
1084 argc--; 1084 argc--;
1085 argv++; 1085 argv++;
1086 goto top; 1086 goto top;
1087 } 1087 }
1088 return 0; 1088 return 0;
1089 } 1089 }
1090 1090
1091 if(!strcmp(argv[0], "forward")) { 1091 if(!strcmp(argv[0], "forward")) {
@@ -1299,7 +1299,7 @@ static int pm_command(transport_type transport, char* serial,
1299 while(argc-- > 0) { 1299 while(argc-- > 0) {
1300 char *quoted; 1300 char *quoted;
1301 1301
1302 quoted = dupAndQuote (*argv++); 1302 quoted = dupAndQuote(*argv++);
1303 1303
1304 strncat(buf, " ", sizeof(buf)-1); 1304 strncat(buf, " ", sizeof(buf)-1);
1305 strncat(buf, quoted, sizeof(buf)-1); 1305 strncat(buf, quoted, sizeof(buf)-1);
@@ -1312,6 +1312,18 @@ static int pm_command(transport_type transport, char* serial,
1312 1312
1313int uninstall_app(transport_type transport, char* serial, int argc, char** argv) 1313int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1314{ 1314{
1315 /* if the user choose the -k option, we refuse to do it until devices are
1316 out with the option to uninstall the remaining data somehow (adb/ui) */
1317 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1318 {
1319 printf(
1320 "The -k option uninstalls the application while retaining the data/cache.\n"
1321 "At the moment, there is no way to remove the remaining data.\n"
1322 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1323 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1324 return -1;
1325 }
1326
1315 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */ 1327 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1316 return pm_command(transport, serial, argc, argv); 1328 return pm_command(transport, serial, argc, argv);
1317} 1329}
diff --git a/adb/file_sync_client.c b/adb/file_sync_client.c
index f9e80edbf..4e6d38591 100644
--- a/adb/file_sync_client.c
+++ b/adb/file_sync_client.c
@@ -55,7 +55,7 @@ static void END()
55 if(total_bytes == 0) return; 55 if(total_bytes == 0) return;
56 56
57 if (t == 0) /* prevent division by 0 :-) */ 57 if (t == 0) /* prevent division by 0 :-) */
58 t = 1000000; 58 t = 1000000;
59 59
60 fprintf(stderr,"%lld KB/s (%d bytes in %lld.%03llds)\n", 60 fprintf(stderr,"%lld KB/s (%d bytes in %lld.%03llds)\n",
61 ((((long long) total_bytes) * 1000000LL) / t) / 1024LL, 61 ((((long long) total_bytes) * 1000000LL) / t) / 1024LL,
@@ -227,14 +227,14 @@ static int write_data_file(int fd, const char *path, syncsendbuf *sbuf)
227 227
228 if(ret < 0) { 228 if(ret < 0) {
229 if(errno == EINTR) 229 if(errno == EINTR)
230 continue; 230 continue;
231 fprintf(stderr,"cannot read '%s': %s\n", path, strerror(errno)); 231 fprintf(stderr,"cannot read '%s': %s\n", path, strerror(errno));
232 break; 232 break;
233 } 233 }
234 234
235 sbuf->size = htoll(ret); 235 sbuf->size = htoll(ret);
236 if(writex(fd, sbuf, sizeof(unsigned) * 2 + ret)){ 236 if(writex(fd, sbuf, sizeof(unsigned) * 2 + ret)){
237 err = -1; 237 err = -1;
238 break; 238 break;
239 } 239 }
240 total_bytes += ret; 240 total_bytes += ret;
@@ -259,7 +259,7 @@ static int write_data_buffer(int fd, char* file_buffer, int size, syncsendbuf *s
259 memcpy(sbuf->data, &file_buffer[total], count); 259 memcpy(sbuf->data, &file_buffer[total], count);
260 sbuf->size = htoll(count); 260 sbuf->size = htoll(count);
261 if(writex(fd, sbuf, sizeof(unsigned) * 2 + count)){ 261 if(writex(fd, sbuf, sizeof(unsigned) * 2 + count)){
262 err = -1; 262 err = -1;
263 break; 263 break;
264 } 264 }
265 total += count; 265 total += count;
@@ -277,7 +277,7 @@ static int write_data_link(int fd, const char *path, syncsendbuf *sbuf)
277 len = readlink(path, sbuf->data, SYNC_DATA_MAX-1); 277 len = readlink(path, sbuf->data, SYNC_DATA_MAX-1);
278 if(len < 0) { 278 if(len < 0) {
279 fprintf(stderr, "error reading link '%s': %s\n", path, strerror(errno)); 279 fprintf(stderr, "error reading link '%s': %s\n", path, strerror(errno));
280 return -1; 280 return -1;
281 } 281 }
282 sbuf->data[len] = '\0'; 282 sbuf->data[len] = '\0';
283 283
@@ -377,10 +377,10 @@ static int sync_send(int fd, const char *lpath, const char *rpath,
377 } 377 }
378 378
379 if (file_buffer) { 379 if (file_buffer) {
380 write_data_buffer(fd, file_buffer, size, sbuf); 380 write_data_buffer(fd, file_buffer, size, sbuf);
381 free(file_buffer); 381 free(file_buffer);
382 } else if (S_ISREG(mode)) 382 } else if (S_ISREG(mode))
383 write_data_file(fd, lpath, sbuf); 383 write_data_file(fd, lpath, sbuf);
384#ifdef HAVE_SYMLINKS 384#ifdef HAVE_SYMLINKS
385 else if (S_ISLNK(mode)) 385 else if (S_ISLNK(mode))
386 write_data_link(fd, lpath, sbuf); 386 write_data_link(fd, lpath, sbuf);
@@ -641,7 +641,7 @@ static int local_build_list(copyinfo **filelist,
641 } else { 641 } else {
642 ci = mkcopyinfo(lpath, rpath, name, 0); 642 ci = mkcopyinfo(lpath, rpath, name, 0);
643 if(lstat(ci->src, &st)) { 643 if(lstat(ci->src, &st)) {
644 closedir(d); 644 closedir(d);
645 fprintf(stderr,"cannot stat '%s': %s\n", ci->src, strerror(errno)); 645 fprintf(stderr,"cannot stat '%s': %s\n", ci->src, strerror(errno));
646 return -1; 646 return -1;
647 } 647 }
@@ -651,7 +651,7 @@ static int local_build_list(copyinfo **filelist,
651 } else { 651 } else {
652 ci->time = st.st_mtime; 652 ci->time = st.st_mtime;
653 ci->mode = st.st_mode; 653 ci->mode = st.st_mode;
654 ci->size = st.st_size; 654 ci->size = st.st_size;
655 ci->next = *filelist; 655 ci->next = *filelist;
656 *filelist = ci; 656 *filelist = ci;
657 } 657 }
@@ -707,12 +707,12 @@ static int copy_local_dir_remote(int fd, const char *lpath, const char *rpath, i
707 unsigned int timestamp, mode, size; 707 unsigned int timestamp, mode, size;
708 if(sync_finish_readtime(fd, &timestamp, &mode, &size)) 708 if(sync_finish_readtime(fd, &timestamp, &mode, &size))
709 return 1; 709 return 1;
710 if(size == ci->size) { 710 if(size == ci->size) {
711 /* for links, we cannot update the atime/mtime */ 711 /* for links, we cannot update the atime/mtime */
712 if((S_ISREG(ci->mode & mode) && timestamp == ci->time) || 712 if((S_ISREG(ci->mode & mode) && timestamp == ci->time) ||
713 (S_ISLNK(ci->mode & mode) && timestamp >= ci->time)) 713 (S_ISLNK(ci->mode & mode) && timestamp >= ci->time))
714 ci->flag = 1; 714 ci->flag = 1;
715 } 715 }
716 } 716 }
717 } 717 }
718 for(ci = filelist; ci != 0; ci = next) { 718 for(ci = filelist; ci != 0; ci = next) {
diff --git a/adb/file_sync_service.c b/adb/file_sync_service.c
index 21f8af775..a231e93d6 100644
--- a/adb/file_sync_service.c
+++ b/adb/file_sync_service.c
@@ -164,12 +164,12 @@ static int handle_send_file(int s, char *path, mode_t mode, char *buffer)
164 } 164 }
165 if(fd < 0) { 165 if(fd < 0) {
166 if(fail_errno(s)) 166 if(fail_errno(s))
167 return -1; 167 return -1;
168 fd = -1; 168 fd = -1;
169 } 169 }
170 170
171 for(;;) { 171 for(;;) {
172 unsigned int len; 172 unsigned int len;
173 173
174 if(readx(s, &msg.data, sizeof(msg.data))) 174 if(readx(s, &msg.data, sizeof(msg.data)))
175 goto fail; 175 goto fail;
@@ -264,7 +264,7 @@ static int handle_send_link(int s, char *path, char *buffer)
264 return -1; 264 return -1;
265 } else { 265 } else {
266 fail_message(s, "invalid data message: expected ID_DONE"); 266 fail_message(s, "invalid data message: expected ID_DONE");
267 return -1; 267 return -1;
268 } 268 }
269 269
270 return 0; 270 return 0;
diff --git a/adb/framebuffer_service.c b/adb/framebuffer_service.c
index 1d2c4b56b..0de0dd5e6 100644
--- a/adb/framebuffer_service.c
+++ b/adb/framebuffer_service.c
@@ -24,6 +24,7 @@
24#include "adb.h" 24#include "adb.h"
25 25
26#include <linux/fb.h> 26#include <linux/fb.h>
27#include <sys/ioctl.h>
27#include <sys/mman.h> 28#include <sys/mman.h>
28 29
29/* TODO: 30/* TODO:
@@ -37,9 +38,9 @@ void framebuffer_service(int fd, void *cookie)
37 int fb; 38 int fb;
38 void *ptr = MAP_FAILED; 39 void *ptr = MAP_FAILED;
39 char x; 40 char x;
40 41
41 unsigned fbinfo[4]; 42 unsigned fbinfo[4];
42 43
43 fb = open("/dev/graphics/fb0", O_RDONLY); 44 fb = open("/dev/graphics/fb0", O_RDONLY);
44 if(fb < 0) goto done; 45 if(fb < 0) goto done;
45 46
@@ -53,14 +54,14 @@ void framebuffer_service(int fd, void *cookie)
53 54
54 ptr = mmap(0, fbinfo[1], PROT_READ, MAP_SHARED, fb, 0); 55 ptr = mmap(0, fbinfo[1], PROT_READ, MAP_SHARED, fb, 0);
55 if(ptr == MAP_FAILED) goto done; 56 if(ptr == MAP_FAILED) goto done;
56 57
57 if(writex(fd, fbinfo, sizeof(unsigned) * 4)) goto done; 58 if(writex(fd, fbinfo, sizeof(unsigned) * 4)) goto done;
58 59
59 for(;;) { 60 for(;;) {
60 if(readx(fd, &x, 1)) goto done; 61 if(readx(fd, &x, 1)) goto done;
61 if(writex(fd, ptr, fbinfo[1])) goto done; 62 if(writex(fd, ptr, fbinfo[1])) goto done;
62 } 63 }
63 64
64done: 65done:
65 if(ptr != MAP_FAILED) munmap(ptr, fbinfo[1]); 66 if(ptr != MAP_FAILED) munmap(ptr, fbinfo[1]);
66 if(fb >= 0) close(fb); 67 if(fb >= 0) close(fb);
diff --git a/adb/get_my_path_windows.c b/adb/get_my_path_windows.c
index 64a597d3c..fc7143c10 100644
--- a/adb/get_my_path_windows.c
+++ b/adb/get_my_path_windows.c
@@ -20,12 +20,12 @@
20 20
21void get_my_path(char exe[PATH_MAX]) 21void get_my_path(char exe[PATH_MAX])
22{ 22{
23 char* r; 23 char* r;
24 24
25 GetModuleFileName( NULL, exe, PATH_MAX-1 ); 25 GetModuleFileName( NULL, exe, PATH_MAX-1 );
26 exe[PATH_MAX-1] = 0; 26 exe[PATH_MAX-1] = 0;
27 r = strrchr( exe, '\\' ); 27 r = strrchr( exe, '\\' );
28 if (r) 28 if (r)
29 *r = 0; 29 *r = 0;
30} 30}
31 31
diff --git a/adb/jdwp_service.c b/adb/jdwp_service.c
index 43dc69eb4..ae7f12dfd 100644
--- a/adb/jdwp_service.c
+++ b/adb/jdwp_service.c
@@ -287,7 +287,7 @@ jdwp_process_event( int socket, unsigned events, void* _proc )
287 if (len <= 0) { 287 if (len <= 0) {
288 if (len < 0 && errno == EINTR) 288 if (len < 0 && errno == EINTR)
289 continue; 289 continue;
290 if (len < 0 && errno == EAGAIN) 290 if (len < 0 && errno == EAGAIN)
291 return; 291 return;
292 else { 292 else {
293 D("terminating JDWP %d connection: %s\n", proc->pid, 293 D("terminating JDWP %d connection: %s\n", proc->pid,
@@ -295,7 +295,7 @@ jdwp_process_event( int socket, unsigned events, void* _proc )
295 break; 295 break;
296 } 296 }
297 } 297 }
298 else { 298 else {
299 D( "ignoring unexpected JDWP %d control socket activity (%d bytes)\n", 299 D( "ignoring unexpected JDWP %d control socket activity (%d bytes)\n",
300 proc->pid, len ); 300 proc->pid, len );
301 } 301 }
diff --git a/adb/sockets.c b/adb/sockets.c
index b9c9ae1cf..9f1b59870 100644
--- a/adb/sockets.c
+++ b/adb/sockets.c
@@ -50,6 +50,15 @@ static asocket local_socket_list = {
50 .prev = &local_socket_list, 50 .prev = &local_socket_list,
51}; 51};
52 52
53/* the the list of currently closing local sockets.
54** these have no peer anymore, but still packets to
55** write to their fd.
56*/
57static asocket local_socket_closing_list = {
58 .next = &local_socket_closing_list,
59 .prev = &local_socket_closing_list,
60};
61
53asocket *find_local_socket(unsigned id) 62asocket *find_local_socket(unsigned id)
54{ 63{
55 asocket *s; 64 asocket *s;
@@ -64,16 +73,22 @@ asocket *find_local_socket(unsigned id)
64 return result; 73 return result;
65} 74}
66 75
76static void
77insert_local_socket(asocket* s, asocket* list)
78{
79 s->next = list;
80 s->prev = s->next->prev;
81 s->prev->next = s;
82 s->next->prev = s;
83}
84
85
67void install_local_socket(asocket *s) 86void install_local_socket(asocket *s)
68{ 87{
69 adb_mutex_lock(&socket_list_lock); 88 adb_mutex_lock(&socket_list_lock);
70 89
71 s->id = local_socket_next_id++; 90 s->id = local_socket_next_id++;
72 91 insert_local_socket(s, &local_socket_list);
73 s->next = &local_socket_list;
74 s->prev = local_socket_list.prev;
75 s->prev->next = s;
76 s->next->prev = s;
77 92
78 adb_mutex_unlock(&socket_list_lock); 93 adb_mutex_unlock(&socket_list_lock);
79} 94}
@@ -177,19 +192,11 @@ static void local_socket_close(asocket *s)
177 adb_mutex_unlock(&socket_list_lock); 192 adb_mutex_unlock(&socket_list_lock);
178} 193}
179 194
180static void local_socket_close_locked(asocket *s) 195// be sure to hold the socket list lock when calling this
196static void local_socket_destroy(asocket *s)
181{ 197{
182 apacket *p, *n; 198 apacket *p, *n;
183 199
184 if(s->peer) {
185 s->peer->peer = 0;
186 // tweak to avoid deadlock
187 if (s->peer->close == local_socket_close)
188 local_socket_close_locked(s->peer);
189 else
190 s->peer->close(s->peer);
191 }
192
193 /* IMPORTANT: the remove closes the fd 200 /* IMPORTANT: the remove closes the fd
194 ** that belongs to this socket 201 ** that belongs to this socket
195 */ 202 */
@@ -201,16 +208,94 @@ static void local_socket_close_locked(asocket *s)
201 n = p->next; 208 n = p->next;
202 put_apacket(p); 209 put_apacket(p);
203 } 210 }
204
205 D("LS(%d): closed\n", s->id);
206 remove_socket(s); 211 remove_socket(s);
207 free(s); 212 free(s);
208} 213}
209 214
215
216static void local_socket_close_locked(asocket *s)
217{
218 if(s->peer) {
219 s->peer->peer = 0;
220 // tweak to avoid deadlock
221 if (s->peer->close == local_socket_close)
222 local_socket_close_locked(s->peer);
223 else
224 s->peer->close(s->peer);
225 }
226
227 /* If we are already closing, or if there are no
228 ** pending packets, destroy immediately
229 */
230 if (s->closing || s->pkt_first == NULL) {
231 int id = s->id;
232 local_socket_destroy(s);
233 D("LS(%d): closed\n", id);
234 return;
235 }
236
237 /* otherwise, put on the closing list
238 */
239 D("LS(%d): closing\n", s->id);
240 s->closing = 1;
241 fdevent_del(&s->fde, FDE_READ);
242 remove_socket(s);
243 insert_local_socket(s, &local_socket_closing_list);
244}
245
210static void local_socket_event_func(int fd, unsigned ev, void *_s) 246static void local_socket_event_func(int fd, unsigned ev, void *_s)
211{ 247{
212 asocket *s = _s; 248 asocket *s = _s;
213 249
250 /* put the FDE_WRITE processing before the FDE_READ
251 ** in order to simplify the code.
252 */
253 if(ev & FDE_WRITE){
254 apacket *p;
255
256 while((p = s->pkt_first) != 0) {
257 while(p->len > 0) {
258 int r = adb_write(fd, p->ptr, p->len);
259 if(r > 0) {
260 p->ptr += r;
261 p->len -= r;
262 continue;
263 }
264 if(r < 0) {
265 /* returning here is ok because FDE_READ will
266 ** be processed in the next iteration loop
267 */
268 if(errno == EAGAIN) return;
269 if(errno == EINTR) continue;
270 }
271 s->close(s);
272 return;
273 }
274
275 if(p->len == 0) {
276 s->pkt_first = p->next;
277 if(s->pkt_first == 0) s->pkt_last = 0;
278 put_apacket(p);
279 }
280 }
281
282 /* if we sent the last packet of a closing socket,
283 ** we can now destroy it.
284 */
285 if (s->closing) {
286 s->close(s);
287 return;
288 }
289
290 /* no more packets queued, so we can ignore
291 ** writable events again and tell our peer
292 ** to resume writing
293 */
294 fdevent_del(&s->fde, FDE_WRITE);
295 s->peer->ready(s->peer);
296 }
297
298
214 if(ev & FDE_READ){ 299 if(ev & FDE_READ){
215 apacket *p = get_apacket(); 300 apacket *p = get_apacket();
216 unsigned char *x = p->data; 301 unsigned char *x = p->data;
@@ -244,7 +329,12 @@ static void local_socket_event_func(int fd, unsigned ev, void *_s)
244 329
245 if(r < 0) { 330 if(r < 0) {
246 /* error return means they closed us as a side-effect 331 /* error return means they closed us as a side-effect
247 ** and we must retutn immediately 332 ** and we must return immediately.
333 **
334 ** note that if we still have buffered packets, the
335 ** socket will be placed on the closing socket list.
336 ** this handler function will be called again
337 ** to process FDE_WRITE events.
248 */ 338 */
249 return; 339 return;
250 } 340 }
@@ -261,42 +351,6 @@ static void local_socket_event_func(int fd, unsigned ev, void *_s)
261 if(is_eof) { 351 if(is_eof) {
262 s->close(s); 352 s->close(s);
263 } 353 }
264 return;
265 }
266
267 if(ev & FDE_WRITE){
268 apacket *p;
269
270 while((p = s->pkt_first) != 0) {
271 while(p->len > 0) {
272 int r = adb_write(fd, p->ptr, p->len);
273 if(r > 0) {
274 p->ptr += r;
275 p->len -= r;
276 continue;
277 }
278 if(r < 0) {
279 if(errno == EAGAIN) return;
280 if(errno == EINTR) continue;
281 }
282 s->close(s);
283 return;
284 }
285
286 if(p->len == 0) {
287 s->pkt_first = p->next;
288 if(s->pkt_first == 0) s->pkt_last = 0;
289 put_apacket(p);
290 }
291 }
292
293 /* no more packets queued, so we can ignore
294 ** writable events again and tell our peer
295 ** to resume writing
296 */
297 fdevent_del(&s->fde, FDE_WRITE);
298 s->peer->ready(s->peer);
299 return;
300 } 354 }
301 355
302 if(ev & FDE_ERROR){ 356 if(ev & FDE_ERROR){
diff --git a/adb/sysdeps_win32.c b/adb/sysdeps_win32.c
index 9d6a596cf..c2a9a985f 100644
--- a/adb/sysdeps_win32.c
+++ b/adb/sysdeps_win32.c
@@ -940,12 +940,12 @@ bip_buffer_write( BipBuffer bip, const void* src, int len )
940 /* we can append to region A */ 940 /* we can append to region A */
941 if (avail > len) 941 if (avail > len)
942 avail = len; 942 avail = len;
943 943
944 memcpy( bip->buff + bip->a_end, src, avail ); 944 memcpy( bip->buff + bip->a_end, src, avail );
945 src += avail; 945 src += avail;
946 count += avail; 946 count += avail;
947 len -= avail; 947 len -= avail;
948 948
949 bip->a_end += avail; 949 bip->a_end += avail;
950 if (bip->a_end == BIP_BUFFER_SIZE && bip->a_start == 0) { 950 if (bip->a_end == BIP_BUFFER_SIZE && bip->a_start == 0) {
951 bip->can_write = 0; 951 bip->can_write = 0;
@@ -953,25 +953,25 @@ bip_buffer_write( BipBuffer bip, const void* src, int len )
953 goto Exit; 953 goto Exit;
954 } 954 }
955 } 955 }
956 956
957 if (len == 0) 957 if (len == 0)
958 goto Exit; 958 goto Exit;
959 959
960 avail = bip->a_start - bip->b_end; 960 avail = bip->a_start - bip->b_end;
961 assert( avail > 0 ); /* since can_write is TRUE */ 961 assert( avail > 0 ); /* since can_write is TRUE */
962 962
963 if (avail > len) 963 if (avail > len)
964 avail = len; 964 avail = len;
965 965
966 memcpy( bip->buff + bip->b_end, src, avail ); 966 memcpy( bip->buff + bip->b_end, src, avail );
967 count += avail; 967 count += avail;
968 bip->b_end += avail; 968 bip->b_end += avail;
969 969
970 if (bip->b_end == bip->a_start) { 970 if (bip->b_end == bip->a_start) {
971 bip->can_write = 0; 971 bip->can_write = 0;
972 ResetEvent( bip->evt_write ); 972 ResetEvent( bip->evt_write );
973 } 973 }
974 974
975Exit: 975Exit:
976 assert( count > 0 ); 976 assert( count > 0 );
977 977
@@ -979,7 +979,7 @@ Exit:
979 bip->can_read = 1; 979 bip->can_read = 1;
980 SetEvent( bip->evt_read ); 980 SetEvent( bip->evt_read );
981 } 981 }
982 982
983 BIPD(( "bip_buffer_write: exit %d->%d count %d (as=%d ae=%d be=%d cw=%d cr=%d\n", 983 BIPD(( "bip_buffer_write: exit %d->%d count %d (as=%d ae=%d be=%d cw=%d cr=%d\n",
984 bip->fdin, bip->fdout, count, bip->a_start, bip->a_end, bip->b_end, bip->can_write, bip->can_read )); 984 bip->fdin, bip->fdout, count, bip->a_start, bip->a_end, bip->b_end, bip->can_write, bip->can_read ));
985 LeaveCriticalSection( &bip->lock ); 985 LeaveCriticalSection( &bip->lock );
@@ -991,12 +991,12 @@ static int
991bip_buffer_read( BipBuffer bip, void* dst, int len ) 991bip_buffer_read( BipBuffer bip, void* dst, int len )
992{ 992{
993 int avail, count = 0; 993 int avail, count = 0;
994 994
995 if (len <= 0) 995 if (len <= 0)
996 return 0; 996 return 0;
997 997
998 BIPD(( "bip_buffer_read: enter %d->%d len %d\n", bip->fdin, bip->fdout, len )); 998 BIPD(( "bip_buffer_read: enter %d->%d len %d\n", bip->fdin, bip->fdout, len ));
999 999
1000 EnterCriticalSection( &bip->lock ); 1000 EnterCriticalSection( &bip->lock );
1001 while ( !bip->can_read ) 1001 while ( !bip->can_read )
1002 { 1002 {
@@ -1007,7 +1007,7 @@ bip_buffer_read( BipBuffer bip, void* dst, int len )
1007#else 1007#else
1008 int ret; 1008 int ret;
1009 LeaveCriticalSection( &bip->lock ); 1009 LeaveCriticalSection( &bip->lock );
1010 1010
1011 if (bip->closed) { 1011 if (bip->closed) {
1012 errno = EPIPE; 1012 errno = EPIPE;
1013 return -1; 1013 return -1;
@@ -1023,30 +1023,30 @@ bip_buffer_read( BipBuffer bip, void* dst, int len )
1023 return -1; 1023 return -1;
1024 } 1024 }
1025 EnterCriticalSection( &bip->lock ); 1025 EnterCriticalSection( &bip->lock );
1026#endif 1026#endif
1027 } 1027 }
1028 1028
1029 BIPD(( "bip_buffer_read: exec %d->%d len %d\n", bip->fdin, bip->fdout, len )); 1029 BIPD(( "bip_buffer_read: exec %d->%d len %d\n", bip->fdin, bip->fdout, len ));
1030 1030
1031 avail = bip->a_end - bip->a_start; 1031 avail = bip->a_end - bip->a_start;
1032 assert( avail > 0 ); /* since can_read is TRUE */ 1032 assert( avail > 0 ); /* since can_read is TRUE */
1033 1033
1034 if (avail > len) 1034 if (avail > len)
1035 avail = len; 1035 avail = len;
1036 1036
1037 memcpy( dst, bip->buff + bip->a_start, avail ); 1037 memcpy( dst, bip->buff + bip->a_start, avail );
1038 dst += avail; 1038 dst += avail;
1039 count += avail; 1039 count += avail;
1040 len -= avail; 1040 len -= avail;
1041 1041
1042 bip->a_start += avail; 1042 bip->a_start += avail;
1043 if (bip->a_start < bip->a_end) 1043 if (bip->a_start < bip->a_end)
1044 goto Exit; 1044 goto Exit;
1045 1045
1046 bip->a_start = 0; 1046 bip->a_start = 0;
1047 bip->a_end = bip->b_end; 1047 bip->a_end = bip->b_end;
1048 bip->b_end = 0; 1048 bip->b_end = 0;
1049 1049
1050 avail = bip->a_end; 1050 avail = bip->a_end;
1051 if (avail > 0) { 1051 if (avail > 0) {
1052 if (avail > len) 1052 if (avail > len)
@@ -1054,13 +1054,13 @@ bip_buffer_read( BipBuffer bip, void* dst, int len )
1054 memcpy( dst, bip->buff, avail ); 1054 memcpy( dst, bip->buff, avail );
1055 count += avail; 1055 count += avail;
1056 bip->a_start += avail; 1056 bip->a_start += avail;
1057 1057
1058 if ( bip->a_start < bip->a_end ) 1058 if ( bip->a_start < bip->a_end )
1059 goto Exit; 1059 goto Exit;
1060 1060
1061 bip->a_start = bip->a_end = 0; 1061 bip->a_start = bip->a_end = 0;
1062 } 1062 }
1063 1063
1064 bip->can_read = 0; 1064 bip->can_read = 0;
1065 ResetEvent( bip->evt_read ); 1065 ResetEvent( bip->evt_read );
1066 1066
@@ -1071,22 +1071,22 @@ Exit:
1071 bip->can_write = 1; 1071 bip->can_write = 1;
1072 SetEvent( bip->evt_write ); 1072 SetEvent( bip->evt_write );
1073 } 1073 }
1074 1074
1075 BIPDUMP( (const unsigned char*)dst - count, count ); 1075 BIPDUMP( (const unsigned char*)dst - count, count );
1076 BIPD(( "bip_buffer_read: exit %d->%d count %d (as=%d ae=%d be=%d cw=%d cr=%d\n", 1076 BIPD(( "bip_buffer_read: exit %d->%d count %d (as=%d ae=%d be=%d cw=%d cr=%d\n",
1077 bip->fdin, bip->fdout, count, bip->a_start, bip->a_end, bip->b_end, bip->can_write, bip->can_read )); 1077 bip->fdin, bip->fdout, count, bip->a_start, bip->a_end, bip->b_end, bip->can_write, bip->can_read ));
1078 LeaveCriticalSection( &bip->lock ); 1078 LeaveCriticalSection( &bip->lock );
1079 1079
1080 return count; 1080 return count;
1081} 1081}
1082 1082
1083typedef struct SocketPairRec_ 1083typedef struct SocketPairRec_
1084{ 1084{
1085 BipBufferRec a2b_bip; 1085 BipBufferRec a2b_bip;
1086 BipBufferRec b2a_bip; 1086 BipBufferRec b2a_bip;
1087 FH a_fd; 1087 FH a_fd;
1088 int used; 1088 int used;
1089 1089
1090} SocketPairRec; 1090} SocketPairRec;
1091 1091
1092void _fh_socketpair_init( FH f ) 1092void _fh_socketpair_init( FH f )
@@ -1103,7 +1103,7 @@ _fh_socketpair_close( FH f )
1103 if ( f == pair->a_fd ) { 1103 if ( f == pair->a_fd ) {
1104 pair->a_fd = NULL; 1104 pair->a_fd = NULL;
1105 } 1105 }
1106 1106
1107 bip_buffer_close( &pair->b2a_bip ); 1107 bip_buffer_close( &pair->b2a_bip );
1108 bip_buffer_close( &pair->a2b_bip ); 1108 bip_buffer_close( &pair->a2b_bip );
1109 1109
@@ -1199,7 +1199,7 @@ int adb_socketpair( int sv[2] )
1199 1199
1200 sv[0] = _fh_to_int(fa); 1200 sv[0] = _fh_to_int(fa);
1201 sv[1] = _fh_to_int(fb); 1201 sv[1] = _fh_to_int(fb);
1202 1202
1203 pair->a2b_bip.fdin = sv[0]; 1203 pair->a2b_bip.fdin = sv[0];
1204 pair->a2b_bip.fdout = sv[1]; 1204 pair->a2b_bip.fdout = sv[1];
1205 pair->b2a_bip.fdin = sv[1]; 1205 pair->b2a_bip.fdin = sv[1];
@@ -1303,7 +1303,7 @@ event_hook_alloc( FH fh )
1303 hook->stop = NULL; 1303 hook->stop = NULL;
1304 hook->check = NULL; 1304 hook->check = NULL;
1305 hook->peek = NULL; 1305 hook->peek = NULL;
1306 1306
1307 return hook; 1307 return hook;
1308} 1308}
1309 1309
@@ -1324,7 +1324,7 @@ event_hook_signal( EventHook hook )
1324 FH f = hook->fh; 1324 FH f = hook->fh;
1325 int fd = _fh_to_int(f); 1325 int fd = _fh_to_int(f);
1326 fdevent* fde = fd_table[ fd - WIN32_FH_BASE ]; 1326 fdevent* fde = fd_table[ fd - WIN32_FH_BASE ];
1327 1327
1328 if (fde != NULL && fde->fd == fd) { 1328 if (fde != NULL && fde->fd == fd) {
1329 if ((fde->state & FDE_PENDING) == 0) { 1329 if ((fde->state & FDE_PENDING) == 0) {
1330 fde->state |= FDE_PENDING; 1330 fde->state |= FDE_PENDING;
@@ -1365,7 +1365,7 @@ event_looper_hook( EventLooper looper, int fd, int events )
1365 FH f = _fh_from_int(fd); 1365 FH f = _fh_from_int(fd);
1366 EventHook *pnode; 1366 EventHook *pnode;
1367 EventHook node; 1367 EventHook node;
1368 1368
1369 if (f == NULL) /* invalid arg */ { 1369 if (f == NULL) /* invalid arg */ {
1370 D("event_looper_hook: invalid fd=%d\n", fd); 1370 D("event_looper_hook: invalid fd=%d\n", fd);
1371 return; 1371 return;
@@ -1397,7 +1397,7 @@ event_looper_unhook( EventLooper looper, int fd, int events )
1397 FH fh = _fh_from_int(fd); 1397 FH fh = _fh_from_int(fd);
1398 EventHook *pnode = event_looper_find_p( looper, fh ); 1398 EventHook *pnode = event_looper_find_p( looper, fh );
1399 EventHook node = *pnode; 1399 EventHook node = *pnode;
1400 1400
1401 if (node != NULL) { 1401 if (node != NULL) {
1402 int events2 = events & node->wanted; 1402 int events2 = events & node->wanted;
1403 if ( events2 == 0 ) { 1403 if ( events2 == 0 ) {
@@ -1424,7 +1424,7 @@ static void fdevent_connect(fdevent *fde)
1424{ 1424{
1425 EventLooper looper = &win32_looper; 1425 EventLooper looper = &win32_looper;
1426 int events = fde->state & FDE_EVENTMASK; 1426 int events = fde->state & FDE_EVENTMASK;
1427 1427
1428 if (events != 0) 1428 if (events != 0)
1429 event_looper_hook( looper, fde->fd, events ); 1429 event_looper_hook( looper, fde->fd, events );
1430} 1430}
@@ -1433,7 +1433,7 @@ static void fdevent_disconnect(fdevent *fde)
1433{ 1433{
1434 EventLooper looper = &win32_looper; 1434 EventLooper looper = &win32_looper;
1435 int events = fde->state & FDE_EVENTMASK; 1435 int events = fde->state & FDE_EVENTMASK;
1436 1436
1437 if (events != 0) 1437 if (events != 0)
1438 event_looper_unhook( looper, fde->fd, events ); 1438 event_looper_unhook( looper, fde->fd, events );
1439} 1439}
@@ -1462,7 +1462,7 @@ static void fdevent_process()
1462 EventLooper looper = &win32_looper; 1462 EventLooper looper = &win32_looper;
1463 EventHook hook; 1463 EventHook hook;
1464 int gotone = 0; 1464 int gotone = 0;
1465 1465
1466 /* if we have at least one ready hook, execute it/them */ 1466 /* if we have at least one ready hook, execute it/them */
1467 for (hook = looper->hooks; hook; hook = hook->next) { 1467 for (hook = looper->hooks; hook; hook = hook->next) {
1468 hook->ready = 0; 1468 hook->ready = 0;
@@ -1479,7 +1479,7 @@ static void fdevent_process()
1479 if (!gotone) 1479 if (!gotone)
1480 { 1480 {
1481 looper->htab_count = 0; 1481 looper->htab_count = 0;
1482 1482
1483 for (hook = looper->hooks; hook; hook = hook->next) 1483 for (hook = looper->hooks; hook; hook = hook->next)
1484 { 1484 {
1485 if (hook->start && !hook->start(hook)) { 1485 if (hook->start && !hook->start(hook)) {
@@ -1519,7 +1519,7 @@ static void fdevent_process()
1519 D( "adb_win32: wait failed, error %ld\n", GetLastError() ); 1519 D( "adb_win32: wait failed, error %ld\n", GetLastError() );
1520 } else { 1520 } else {
1521 D( "adb_win32: got one (index %d)\n", wait_ret ); 1521 D( "adb_win32: got one (index %d)\n", wait_ret );
1522 1522
1523 /* according to Cygwin, some objects like consoles wake up on "inappropriate" events 1523 /* according to Cygwin, some objects like consoles wake up on "inappropriate" events
1524 * like mouse movements. we need to filter these with the "check" function 1524 * like mouse movements. we need to filter these with the "check" function
1525 */ 1525 */
@@ -1561,7 +1561,7 @@ static void fdevent_register(fdevent *fde)
1561 if(fd < 0) { 1561 if(fd < 0) {
1562 FATAL("bogus negative fd (%d)\n", fde->fd); 1562 FATAL("bogus negative fd (%d)\n", fde->fd);
1563 } 1563 }
1564 1564
1565 if(fd >= fd_table_max) { 1565 if(fd >= fd_table_max) {
1566 int oldmax = fd_table_max; 1566 int oldmax = fd_table_max;
1567 if(fde->fd > 32000) { 1567 if(fde->fd > 32000) {
@@ -1587,7 +1587,7 @@ static void fdevent_register(fdevent *fde)
1587static void fdevent_unregister(fdevent *fde) 1587static void fdevent_unregister(fdevent *fde)
1588{ 1588{
1589 int fd = fde->fd - WIN32_FH_BASE; 1589 int fd = fde->fd - WIN32_FH_BASE;
1590 1590
1591 if((fd < 0) || (fd >= fd_table_max)) { 1591 if((fd < 0) || (fd >= fd_table_max)) {
1592 FATAL("fd out of range (%d)\n", fde->fd); 1592 FATAL("fd out of range (%d)\n", fde->fd);
1593 } 1593 }
@@ -1626,9 +1626,9 @@ static fdevent *fdevent_plist_dequeue(void)
1626{ 1626{
1627 fdevent *list = &list_pending; 1627 fdevent *list = &list_pending;
1628 fdevent *node = list->next; 1628 fdevent *node = list->next;
1629 1629
1630 if(node == list) return 0; 1630 if(node == list) return 0;
1631 1631
1632 list->next = node->next; 1632 list->next = node->next;
1633 list->next->prev = list; 1633 list->next->prev = list;
1634 node->next = 0; 1634 node->next = 0;
@@ -1689,9 +1689,9 @@ void fdevent_remove(fdevent *fde)
1689void fdevent_set(fdevent *fde, unsigned events) 1689void fdevent_set(fdevent *fde, unsigned events)
1690{ 1690{
1691 events &= FDE_EVENTMASK; 1691 events &= FDE_EVENTMASK;
1692 1692
1693 if((fde->state & FDE_EVENTMASK) == (int)events) return; 1693 if((fde->state & FDE_EVENTMASK) == (int)events) return;
1694 1694
1695 if(fde->state & FDE_ACTIVE) { 1695 if(fde->state & FDE_ACTIVE) {
1696 fdevent_update(fde, events); 1696 fdevent_update(fde, events);
1697 dump_fde(fde, "update"); 1697 dump_fde(fde, "update");
@@ -1727,13 +1727,13 @@ void fdevent_del(fdevent *fde, unsigned events)
1727void fdevent_loop() 1727void fdevent_loop()
1728{ 1728{
1729 fdevent *fde; 1729 fdevent *fde;
1730 1730
1731 for(;;) { 1731 for(;;) {
1732#if DEBUG 1732#if DEBUG
1733 fprintf(stderr,"--- ---- waiting for events\n"); 1733 fprintf(stderr,"--- ---- waiting for events\n");
1734#endif 1734#endif
1735 fdevent_process(); 1735 fdevent_process();
1736 1736
1737 while((fde = fdevent_plist_dequeue())) { 1737 while((fde = fdevent_plist_dequeue())) {
1738 unsigned events = fde->events; 1738 unsigned events = fde->events;
1739 fde->events = 0; 1739 fde->events = 0;
@@ -1793,7 +1793,7 @@ static void _event_socket_verify( EventHook hook, WSANETWORKEVENTS* evts )
1793static void _event_socket_prepare( EventHook hook ) 1793static void _event_socket_prepare( EventHook hook )
1794{ 1794{
1795 WSANETWORKEVENTS evts; 1795 WSANETWORKEVENTS evts;
1796 1796
1797 /* look if some of the events we want already happened ? */ 1797 /* look if some of the events we want already happened ? */
1798 if (!WSAEnumNetworkEvents( hook->fh->fh_socket, NULL, &evts )) 1798 if (!WSAEnumNetworkEvents( hook->fh->fh_socket, NULL, &evts ))
1799 _event_socket_verify( hook, &evts ); 1799 _event_socket_verify( hook, &evts );
@@ -1819,13 +1819,13 @@ static int _event_socket_start( EventHook hook )
1819 /* create an event which we're going to wait for */ 1819 /* create an event which we're going to wait for */
1820 FH fh = hook->fh; 1820 FH fh = hook->fh;
1821 long flags = _socket_wanted_to_flags( hook->wanted ); 1821 long flags = _socket_wanted_to_flags( hook->wanted );
1822 1822
1823 hook->h = fh->event; 1823 hook->h = fh->event;
1824 if (hook->h == INVALID_HANDLE_VALUE) { 1824 if (hook->h == INVALID_HANDLE_VALUE) {
1825 D( "_event_socket_start: no event for %s\n", fh->name ); 1825 D( "_event_socket_start: no event for %s\n", fh->name );
1826 return 0; 1826 return 0;
1827 } 1827 }
1828 1828
1829 if ( flags != fh->mask ) { 1829 if ( flags != fh->mask ) {
1830 D( "_event_socket_start: hooking %s for %x (flags %ld)\n", hook->fh->name, hook->wanted, flags ); 1830 D( "_event_socket_start: hooking %s for %x (flags %ld)\n", hook->fh->name, hook->wanted, flags );
1831 if ( WSAEventSelect( fh->fh_socket, hook->h, flags ) ) { 1831 if ( WSAEventSelect( fh->fh_socket, hook->h, flags ) ) {
@@ -1850,7 +1850,7 @@ static int _event_socket_check( EventHook hook )
1850 int result = 0; 1850 int result = 0;
1851 FH fh = hook->fh; 1851 FH fh = hook->fh;
1852 WSANETWORKEVENTS evts; 1852 WSANETWORKEVENTS evts;
1853 1853
1854 if (!WSAEnumNetworkEvents( fh->fh_socket, hook->h, &evts ) ) { 1854 if (!WSAEnumNetworkEvents( fh->fh_socket, hook->h, &evts ) ) {
1855 _event_socket_verify( hook, &evts ); 1855 _event_socket_verify( hook, &evts );
1856 result = (hook->ready != 0); 1856 result = (hook->ready != 0);
@@ -1866,7 +1866,7 @@ static int _event_socket_peek( EventHook hook )
1866{ 1866{
1867 WSANETWORKEVENTS evts; 1867 WSANETWORKEVENTS evts;
1868 FH fh = hook->fh; 1868 FH fh = hook->fh;
1869 1869
1870 /* look if some of the events we want already happened ? */ 1870 /* look if some of the events we want already happened ? */
1871 if (!WSAEnumNetworkEvents( fh->fh_socket, NULL, &evts )) { 1871 if (!WSAEnumNetworkEvents( fh->fh_socket, NULL, &evts )) {
1872 _event_socket_verify( hook, &evts ); 1872 _event_socket_verify( hook, &evts );
@@ -1886,40 +1886,40 @@ static void _fh_socket_hook( FH f, int events, EventHook hook )
1886 hook->stop = _event_socket_stop; 1886 hook->stop = _event_socket_stop;
1887 hook->check = _event_socket_check; 1887 hook->check = _event_socket_check;
1888 hook->peek = _event_socket_peek; 1888 hook->peek = _event_socket_peek;
1889 1889
1890 _event_socket_start( hook ); 1890 _event_socket_start( hook );
1891} 1891}
1892 1892
1893/** SOCKETPAIR EVENT HOOKS 1893/** SOCKETPAIR EVENT HOOKS
1894 **/ 1894 **/
1895 1895
1896static void _event_socketpair_prepare( EventHook hook ) 1896static void _event_socketpair_prepare( EventHook hook )
1897{ 1897{
1898 FH fh = hook->fh; 1898 FH fh = hook->fh;
1899 SocketPair pair = fh->fh_pair; 1899 SocketPair pair = fh->fh_pair;
1900 BipBuffer rbip = (pair->a_fd == fh) ? &pair->b2a_bip : &pair->a2b_bip; 1900 BipBuffer rbip = (pair->a_fd == fh) ? &pair->b2a_bip : &pair->a2b_bip;
1901 BipBuffer wbip = (pair->a_fd == fh) ? &pair->a2b_bip : &pair->b2a_bip; 1901 BipBuffer wbip = (pair->a_fd == fh) ? &pair->a2b_bip : &pair->b2a_bip;
1902 1902
1903 if (hook->wanted & FDE_READ && rbip->can_read) 1903 if (hook->wanted & FDE_READ && rbip->can_read)
1904 hook->ready |= FDE_READ; 1904 hook->ready |= FDE_READ;
1905 1905
1906 if (hook->wanted & FDE_WRITE && wbip->can_write) 1906 if (hook->wanted & FDE_WRITE && wbip->can_write)
1907 hook->ready |= FDE_WRITE; 1907 hook->ready |= FDE_WRITE;
1908 } 1908 }
1909 1909
1910 static int _event_socketpair_start( EventHook hook ) 1910 static int _event_socketpair_start( EventHook hook )
1911 { 1911 {
1912 FH fh = hook->fh; 1912 FH fh = hook->fh;
1913 SocketPair pair = fh->fh_pair; 1913 SocketPair pair = fh->fh_pair;
1914 BipBuffer rbip = (pair->a_fd == fh) ? &pair->b2a_bip : &pair->a2b_bip; 1914 BipBuffer rbip = (pair->a_fd == fh) ? &pair->b2a_bip : &pair->a2b_bip;
1915 BipBuffer wbip = (pair->a_fd == fh) ? &pair->a2b_bip : &pair->b2a_bip; 1915 BipBuffer wbip = (pair->a_fd == fh) ? &pair->a2b_bip : &pair->b2a_bip;
1916 1916
1917 if (hook->wanted == FDE_READ) 1917 if (hook->wanted == FDE_READ)
1918 hook->h = rbip->evt_read; 1918 hook->h = rbip->evt_read;
1919 1919
1920 else if (hook->wanted == FDE_WRITE) 1920 else if (hook->wanted == FDE_WRITE)
1921 hook->h = wbip->evt_write; 1921 hook->h = wbip->evt_write;
1922 1922
1923 else { 1923 else {
1924 D("_event_socketpair_start: can't handle FDE_READ+FDE_WRITE\n" ); 1924 D("_event_socketpair_start: can't handle FDE_READ+FDE_WRITE\n" );
1925 return 0; 1925 return 0;
diff --git a/adb/transport_local.c b/adb/transport_local.c
index 0e8b73246..be01f290c 100644
--- a/adb/transport_local.c
+++ b/adb/transport_local.c
@@ -76,7 +76,7 @@ static int remote_read(apacket *p, atransport *t)
76 } 76 }
77 77
78 if(check_data(p)) { 78 if(check_data(p)) {
79 D("bad data: terminated (data)\n"); 79 D("bad data: terminated (data)\n");
80 return -1; 80 return -1;
81 } 81 }
82 82
@@ -107,15 +107,16 @@ int local_connect(int port)
107 char buf[64]; 107 char buf[64];
108 int fd = -1; 108 int fd = -1;
109 109
110 fd = socket_loopback_client(port, SOCK_STREAM);
111#if ADB_HOST 110#if ADB_HOST
112 if(fd < 0) { 111 const char *host = getenv("ADBHOST");
113 const char *host = getenv("ADBHOST"); 112 if (host) {
114 if(host) { 113 fd = socket_network_client(host, port, SOCK_STREAM);
115 fd = socket_network_client(host, port, SOCK_STREAM);
116 }
117 } 114 }
118#endif 115#endif
116 if (fd < 0) {
117 fd = socket_loopback_client(port, SOCK_STREAM);
118 }
119
119 if (fd >= 0) { 120 if (fd >= 0) {
120 D("client: connected on remote on fd %d\n", fd); 121 D("client: connected on remote on fd %d\n", fd);
121 close_on_exec(fd); 122 close_on_exec(fd);
diff --git a/adb/transport_usb.c b/adb/transport_usb.c
index 4da7e8b65..01c4a7ede 100644
--- a/adb/transport_usb.c
+++ b/adb/transport_usb.c
@@ -55,7 +55,7 @@ static int remote_read(apacket *p, atransport *t)
55 } 55 }
56 56
57 fix_endians(p); 57 fix_endians(p);
58 58
59 if(check_header(p)) { 59 if(check_header(p)) {
60 D("remote usb: check_header failed\n"); 60 D("remote usb: check_header failed\n");
61 return -1; 61 return -1;
@@ -79,9 +79,9 @@ static int remote_read(apacket *p, atransport *t)
79static int remote_write(apacket *p, atransport *t) 79static int remote_write(apacket *p, atransport *t)
80{ 80{
81 unsigned size = p->msg.data_length; 81 unsigned size = p->msg.data_length;
82 82
83 fix_endians(p); 83 fix_endians(p);
84 84
85 if(usb_write(t->usb, &p->msg, sizeof(amessage))) { 85 if(usb_write(t->usb, &p->msg, sizeof(amessage))) {
86 D("remote usb: 1 - write terminated\n"); 86 D("remote usb: 1 - write terminated\n");
87 return -1; 87 return -1;
@@ -91,7 +91,7 @@ static int remote_write(apacket *p, atransport *t)
91 D("remote usb: 2 - write terminated\n"); 91 D("remote usb: 2 - write terminated\n");
92 return -1; 92 return -1;
93 } 93 }
94 94
95 return 0; 95 return 0;
96} 96}
97 97
@@ -117,7 +117,7 @@ void init_usb_transport(atransport *t, usb_handle *h)
117 t->connection_state = CS_OFFLINE; 117 t->connection_state = CS_OFFLINE;
118 t->type = kTransportUsb; 118 t->type = kTransportUsb;
119 t->usb = h; 119 t->usb = h;
120 120
121#if ADB_HOST 121#if ADB_HOST
122 HOST = 1; 122 HOST = 1;
123#else 123#else
@@ -135,7 +135,7 @@ int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_
135 /* not supported */ 135 /* not supported */
136 return 0; 136 return 0;
137 } 137 }
138 138
139 /* class:vendor (0xff) subclass:android (0x42) proto:adb (0x01) */ 139 /* class:vendor (0xff) subclass:android (0x42) proto:adb (0x01) */
140 if(usb_class == 0xff) { 140 if(usb_class == 0xff) {
141 if((usb_subclass == 0x42) && (usb_protocol == 0x01)) { 141 if((usb_subclass == 0x42) && (usb_protocol == 0x01)) {
diff --git a/adb/usb_linux_client.c b/adb/usb_linux_client.c
index e265a1c22..530bd04db 100644
--- a/adb/usb_linux_client.c
+++ b/adb/usb_linux_client.c
@@ -118,7 +118,7 @@ void usb_init()
118 h->fd = -1; 118 h->fd = -1;
119 adb_cond_init(&h->notify, 0); 119 adb_cond_init(&h->notify, 0);
120 adb_mutex_init(&h->lock, 0); 120 adb_mutex_init(&h->lock, 0);
121 121
122 // Open the file /dev/android_adb_enable to trigger 122 // Open the file /dev/android_adb_enable to trigger
123 // the enabling of the adb USB function in the kernel. 123 // the enabling of the adb USB function in the kernel.
124 // We never touch this file again - just leave it open 124 // We never touch this file again - just leave it open
diff --git a/adb/usb_osx.c b/adb/usb_osx.c
index 8ea84f926..49e1eef5b 100644
--- a/adb/usb_osx.c
+++ b/adb/usb_osx.c
@@ -72,13 +72,13 @@ InitUSB()
72 CFRunLoopSourceRef runLoopSource; 72 CFRunLoopSourceRef runLoopSource;
73 SInt32 vendor, product; 73 SInt32 vendor, product;
74 int i; 74 int i;
75 75
76 //* To set up asynchronous notifications, create a notification port and 76 //* To set up asynchronous notifications, create a notification port and
77 //* add its run loop event source to the program's run loop 77 //* add its run loop event source to the program's run loop
78 notificationPort = IONotificationPortCreate(kIOMasterPortDefault); 78 notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
79 runLoopSource = IONotificationPortGetRunLoopSource(notificationPort); 79 runLoopSource = IONotificationPortGetRunLoopSource(notificationPort);
80 CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode); 80 CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode);
81 81
82 memset(notificationIterators, 0, sizeof(notificationIterators)); 82 memset(notificationIterators, 0, sizeof(notificationIterators));
83 83
84 //* loop through all supported vendor/product pairs 84 //* loop through all supported vendor/product pairs
@@ -86,19 +86,19 @@ InitUSB()
86 //* Create our matching dictionary to find the Android device 86 //* Create our matching dictionary to find the Android device
87 //* IOServiceAddMatchingNotification consumes the reference, so we do not need to release this 87 //* IOServiceAddMatchingNotification consumes the reference, so we do not need to release this
88 matchingDict = IOServiceMatching(kIOUSBDeviceClassName); 88 matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
89 89
90 if (!matchingDict) { 90 if (!matchingDict) {
91 DBG("ERR: Couldn't create USB matching dictionary.\n"); 91 DBG("ERR: Couldn't create USB matching dictionary.\n");
92 return -1; 92 return -1;
93 } 93 }
94 94
95 //* Set up two matching dictionaries, one for each product ID we support. 95 //* Set up two matching dictionaries, one for each product ID we support.
96 //* This will cause the kernel to notify us only if the vendor and product IDs match. 96 //* This will cause the kernel to notify us only if the vendor and product IDs match.
97 vendor = kSupportedDevices[i].vid; 97 vendor = kSupportedDevices[i].vid;
98 product = kSupportedDevices[i].pid; 98 product = kSupportedDevices[i].pid;
99 CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vendor)); 99 CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vendor));
100 CFDictionarySetValue(matchingDict, CFSTR(kUSBProductID), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &product)); 100 CFDictionarySetValue(matchingDict, CFSTR(kUSBProductID), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &product));
101 101
102 //* Now set up two notifications: one to be called when a raw device 102 //* Now set up two notifications: one to be called when a raw device
103 //* is first matched by the I/O Kit and another to be called when the 103 //* is first matched by the I/O Kit and another to be called when the
104 //* device is terminated. 104 //* device is terminated.
@@ -110,7 +110,7 @@ InitUSB()
110 AndroidDeviceAdded, 110 AndroidDeviceAdded,
111 NULL, 111 NULL,
112 &notificationIterators[i]); 112 &notificationIterators[i]);
113 113
114 //* Iterate over set of matching devices to access already-present devices 114 //* Iterate over set of matching devices to access already-present devices
115 //* and to arm the notification 115 //* and to arm the notification
116 AndroidDeviceAdded(NULL, notificationIterators[i]); 116 AndroidDeviceAdded(NULL, notificationIterators[i]);
@@ -173,7 +173,7 @@ AndroidDeviceAdded(void *refCon, io_iterator_t iterator)
173 173
174 if (kr == kIOReturnSuccess && req.wLenDone > 0) { 174 if (kr == kIOReturnSuccess && req.wLenDone > 0) {
175 int i, count; 175 int i, count;
176 176
177 // skip first word, and copy the rest to the serial string, changing shorts to bytes. 177 // skip first word, and copy the rest to the serial string, changing shorts to bytes.
178 count = (req.wLenDone - 1) / 2; 178 count = (req.wLenDone - 1) / 2;
179 for (i = 0; i < count; i++) 179 for (i = 0; i < count; i++)
@@ -401,8 +401,8 @@ void* RunLoopThread(void* unused)
401 currentRunLoop = 0; 401 currentRunLoop = 0;
402 402
403 for (i = 0; i < kSupportedDeviceCount; i++) { 403 for (i = 0; i < kSupportedDeviceCount; i++) {
404 IOObjectRelease(notificationIterators[i]); 404 IOObjectRelease(notificationIterators[i]);
405 } 405 }
406 IONotificationPortDestroy(notificationPort); 406 IONotificationPortDestroy(notificationPort);
407 407
408 DBG("RunLoopThread done\n"); 408 DBG("RunLoopThread done\n");
diff --git a/adb/usb_windows.c b/adb/usb_windows.c
index 5b0f11fa6..7ddaa0c18 100644
--- a/adb/usb_windows.c
+++ b/adb/usb_windows.c
@@ -308,11 +308,11 @@ int usb_read(usb_handle *handle, void* data, int len) {
308 while (len > 0) { 308 while (len > 0) {
309 int xfer = (len > 4096) ? 4096 : len; 309 int xfer = (len > 4096) ? 4096 : len;
310 310
311 ret = AdbReadEndpointSync(handle->adb_read_pipe, 311 ret = AdbReadEndpointSync(handle->adb_read_pipe,
312 (void*)data, 312 (void*)data,
313 (unsigned long)xfer, 313 (unsigned long)xfer,
314 &read, 314 &read,
315 time_out); 315 time_out);
316 errno = GetLastError(); 316 errno = GetLastError();
317 D("usb_write got: %ld, expected: %d, errno: %d\n", read, xfer, errno); 317 D("usb_write got: %ld, expected: %d, errno: %d\n", read, xfer, errno);
318 if (ret) { 318 if (ret) {
@@ -475,11 +475,11 @@ void find_devices() {
475 // Lets see if we already have this device in the list 475 // Lets see if we already have this device in the list
476 if (!known_device(interf_name)) { 476 if (!known_device(interf_name)) {
477 // This seems to be a new device. Open it! 477 // This seems to be a new device. Open it!
478 handle = do_usb_open(next_interface->device_name); 478 handle = do_usb_open(next_interface->device_name);
479 if (NULL != handle) { 479 if (NULL != handle) {
480 // Lets see if this interface (device) belongs to us 480 // Lets see if this interface (device) belongs to us
481 if (recognized_device(handle)) { 481 if (recognized_device(handle)) {
482 D("adding a new device %s\n", interf_name); 482 D("adding a new device %s\n", interf_name);
483 char serial_number[512]; 483 char serial_number[512];
484 unsigned long serial_number_len = sizeof(serial_number); 484 unsigned long serial_number_len = sizeof(serial_number);
485 if (AdbGetSerialNumber(handle->adb_interface, 485 if (AdbGetSerialNumber(handle->adb_interface,
@@ -488,7 +488,7 @@ void find_devices() {
488 true)) { 488 true)) {
489 // Lets make sure that we don't duplicate this device 489 // Lets make sure that we don't duplicate this device
490 if (register_new_device(handle)) { 490 if (register_new_device(handle)) {
491 register_usb_transport(handle, serial_number); 491 register_usb_transport(handle, serial_number);
492 } else { 492 } else {
493 D("register_new_device failed for %s\n", interf_name); 493 D("register_new_device failed for %s\n", interf_name);
494 usb_cleanup_handle(handle); 494 usb_cleanup_handle(handle);
diff --git a/adb/utils.c b/adb/utils.c
new file mode 100644
index 000000000..91518bab6
--- /dev/null
+++ b/adb/utils.c
@@ -0,0 +1,106 @@
1/*
2 * Copyright (C) 2008 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#include "utils.h"
17#include <stdarg.h>
18#include <stdio.h>
19#include <string.h>
20
21char*
22buff_addc (char* buff, char* buffEnd, int c)
23{
24 int avail = buffEnd - buff;
25
26 if (avail <= 0) /* already in overflow mode */
27 return buff;
28
29 if (avail == 1) { /* overflowing, the last byte is reserved for zero */
30 buff[0] = 0;
31 return buff + 1;
32 }
33
34 buff[0] = (char) c; /* add char and terminating zero */
35 buff[1] = 0;
36 return buff + 1;
37}
38
39char*
40buff_adds (char* buff, char* buffEnd, const char* s)
41{
42 int slen = strlen(s);
43
44 return buff_addb(buff, buffEnd, s, slen);
45}
46
47char*
48buff_addb (char* buff, char* buffEnd, const void* data, int len)
49{
50 int avail = (buffEnd - buff);
51
52 if (avail <= 0 || len <= 0) /* already overflowing */
53 return buff;
54
55 if (len > avail)
56 len = avail;
57
58 memcpy(buff, data, len);
59
60 buff += len;
61
62 /* ensure there is a terminating zero */
63 if (buff >= buffEnd) { /* overflow */
64 buff[-1] = 0;
65 } else
66 buff[0] = 0;
67
68 return buff;
69}
70
71char*
72buff_add (char* buff, char* buffEnd, const char* format, ... )
73{
74 int avail;
75
76 avail = (buffEnd - buff);
77
78 if (avail > 0) {
79 va_list args;
80 int nn;
81
82 va_start(args, format);
83 nn = vsnprintf( buff, avail, format, args);
84 va_end(args);
85
86 if (nn < 0) {
87 /* some C libraries return -1 in case of overflow,
88 * but they will also do that if the format spec is
89 * invalid. We assume ADB is not buggy enough to
90 * trigger that last case. */
91 nn = avail;
92 }
93 else if (nn > avail) {
94 nn = avail;
95 }
96
97 buff += nn;
98
99 /* ensure that there is a terminating zero */
100 if (buff >= buffEnd)
101 buff[-1] = 0;
102 else
103 buff[0] = 0;
104 }
105 return buff;
106}
diff --git a/adb/utils.h b/adb/utils.h
new file mode 100644
index 000000000..f70ecd24d
--- /dev/null
+++ b/adb/utils.h
@@ -0,0 +1,68 @@
1/*
2 * Copyright (C) 2008 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#ifndef _ADB_UTILS_H
17#define _ADB_UTILS_H
18
19/* bounded buffer functions */
20
21/* all these functions are used to append data to a bounded buffer.
22 *
23 * after each operation, the buffer is guaranteed to be zero-terminated,
24 * even in the case of an overflow. they all return the new buffer position
25 * which allows one to use them in succession, only checking for overflows
26 * at the end. For example:
27 *
28 * BUFF_DECL(temp,p,end,1024);
29 * char* p;
30 *
31 * p = buff_addc(temp, end, '"');
32 * p = buff_adds(temp, end, string);
33 * p = buff_addc(temp, end, '"');
34 *
35 * if (p >= end) {
36 * overflow detected. note that 'temp' is
37 * zero-terminated for safety.
38 * }
39 * return strdup(temp);
40 */
41
42/* tries to add a character to the buffer, in case of overflow
43 * this will only write a terminating zero and return buffEnd.
44 */
45char* buff_addc (char* buff, char* buffEnd, int c);
46
47/* tries to add a string to the buffer */
48char* buff_adds (char* buff, char* buffEnd, const char* s);
49
50/* tries to add a bytes to the buffer. the input can contain zero bytes,
51 * but a terminating zero will always be appended at the end anyway
52 */
53char* buff_addb (char* buff, char* buffEnd, const void* data, int len);
54
55/* tries to add a formatted string to a bounded buffer */
56char* buff_add (char* buff, char* buffEnd, const char* format, ... );
57
58/* convenience macro used to define a bounded buffer, as well as
59 * a 'cursor' and 'end' variables all in one go.
60 *
61 * note: this doesn't place an initial terminating zero in the buffer,
62 * you need to use one of the buff_ functions for this. or simply
63 * do _cursor[0] = 0 manually.
64 */
65#define BUFF_DECL(_buff,_cursor,_end,_size) \
66 char _buff[_size], *_cursor=_buff, *_end = _cursor + (_size)
67
68#endif /* _ADB_UTILS_H */
diff --git a/cpio/Android.mk b/cpio/Android.mk
index f340fd69a..8d01852b0 100644
--- a/cpio/Android.mk
+++ b/cpio/Android.mk
@@ -10,4 +10,4 @@ LOCAL_MODULE := mkbootfs
10 10
11include $(BUILD_HOST_EXECUTABLE) 11include $(BUILD_HOST_EXECUTABLE)
12 12
13$(call dist-for-goals,user userdebug droid,$(LOCAL_BUILT_MODULE)) 13$(call dist-for-goals,droid,$(LOCAL_BUILT_MODULE))
diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk
index 03046bd5e..b22e1a81d 100644
--- a/debuggerd/Android.mk
+++ b/debuggerd/Android.mk
@@ -1,5 +1,7 @@
1# Copyright 2005 The Android Open Source Project 1# Copyright 2005 The Android Open Source Project
2 2
3ifeq ($(TARGET_ARCH),arm)
4
3LOCAL_PATH:= $(call my-dir) 5LOCAL_PATH:= $(call my-dir)
4include $(CLEAR_VARS) 6include $(CLEAR_VARS)
5 7
@@ -20,3 +22,5 @@ LOCAL_MODULE_TAGS := eng
20#LOCAL_FORCE_STATIC_EXECUTABLE := true 22#LOCAL_FORCE_STATIC_EXECUTABLE := true
21LOCAL_SHARED_LIBRARIES := libcutils libc 23LOCAL_SHARED_LIBRARIES := libcutils libc
22include $(BUILD_EXECUTABLE) 24include $(BUILD_EXECUTABLE)
25
26endif # TARGET_ARCH == arm
diff --git a/debuggerd/unwind-arm.c b/debuggerd/unwind-arm.c
index fdc0a6aa6..9642d2e4a 100644
--- a/debuggerd/unwind-arm.c
+++ b/debuggerd/unwind-arm.c
@@ -381,13 +381,15 @@ get_eit_entry (_Unwind_Control_Block *ucbp, _uw return_address, pid_t pid,
381} 381}
382 382
383/* Print out the current call level, pc, and module name in the crash log */ 383/* Print out the current call level, pc, and module name in the crash log */
384static _Unwind_Reason_Code log_function(_Unwind_Context *context, int tfd, 384static _Unwind_Reason_Code log_function(_Unwind_Context *context, pid_t pid,
385 int tfd,
385 int stack_level, 386 int stack_level,
386 mapinfo *map, 387 mapinfo *map,
387 unsigned int sp_list[], 388 unsigned int sp_list[],
388 bool at_fault) 389 bool at_fault)
389{ 390{
390 _uw pc; 391 _uw pc;
392 _uw rel_pc;
391 phase2_vrs *vrs = (phase2_vrs*) context; 393 phase2_vrs *vrs = (phase2_vrs*) context;
392 const mapinfo *mi; 394 const mapinfo *mi;
393 bool only_in_tombstone = !at_fault; 395 bool only_in_tombstone = !at_fault;
@@ -404,19 +406,53 @@ static _Unwind_Reason_Code log_function(_Unwind_Context *context, int tfd,
404 // For deeper framers, rollback pc by one instruction 406 // For deeper framers, rollback pc by one instruction
405 else { 407 else {
406 pc = vrs->core.r[R_PC]; 408 pc = vrs->core.r[R_PC];
407 // Thumb mode 409 /* Thumb mode - need to check whether the bl(x) has long offset or not.
410 * Examples:
411 *
412 * arm blx in the middle of thumb:
413 * 187ae: 2300 movs r3, #0
414 * 187b0: f7fe ee1c blx 173ec
415 * 187b4: 2c00 cmp r4, #0
416 *
417 * arm bl in the middle of thumb:
418 * 187d8: 1c20 adds r0, r4, #0
419 * 187da: f136 fd15 bl 14f208
420 * 187de: 2800 cmp r0, #0
421 *
422 * pure thumb:
423 * 18894: 189b adds r3, r3, r2
424 * 18896: 4798 blx r3
425 * 18898: b001 add sp, #4
426 */
408 if (pc & 1) { 427 if (pc & 1) {
409 pc = (pc & ~1) - 2; 428 _uw prev_word;
429 pc = (pc & ~1);
430 prev_word = get_remote_word(pid, (void *) pc-4);
431 // Long offset
432 if ((prev_word & 0xf0000000) == 0xf0000000 &&
433 (prev_word & 0x0000e000) == 0x0000e000) {
434 pc -= 4;
435 }
436 else {
437 pc -= 2;
438 }
410 } 439 }
411 else { 440 else {
412 pc -= 4; 441 pc -= 4;
413 } 442 }
414 } 443 }
415 444
416 mi = pc_to_mapinfo(map, pc); 445 /* We used to print the absolute PC in the back trace, and mask out the top
446 * 3 bits to guesstimate the offset in the .so file. This is not working for
447 * non-prelinked libraries since the starting offset may not be aligned on
448 * 1MB boundaries, and the library may be larger than 1MB. So for .so
449 * addresses we print the relative offset in back trace.
450 */
451 rel_pc = pc;
452 mi = pc_to_mapinfo(map, pc, &rel_pc);
417 453
418 _LOG(tfd, only_in_tombstone, 454 _LOG(tfd, only_in_tombstone,
419 " #%02d pc %08x %s\n", stack_level, pc, 455 " #%02d pc %08x %s\n", stack_level, rel_pc,
420 mi ? mi->name : ""); 456 mi ? mi->name : "");
421 457
422 return _URC_NO_REASON; 458 return _URC_NO_REASON;
@@ -459,7 +495,7 @@ int unwind_backtrace_with_ptrace(int tfd, pid_t pid, mapinfo *map,
459 */ 495 */
460 if (get_eitp(saved_vrs.core.r[R_PC], pid, map, NULL) == NULL) { 496 if (get_eitp(saved_vrs.core.r[R_PC], pid, map, NULL) == NULL) {
461 *frame0_pc_sane = 0; 497 *frame0_pc_sane = 0;
462 log_function ((_Unwind_Context *) &saved_vrs, tfd, stack_level, 498 log_function ((_Unwind_Context *) &saved_vrs, pid, tfd, stack_level,
463 map, sp_list, at_fault); 499 map, sp_list, at_fault);
464 saved_vrs.core.r[R_PC] = saved_vrs.core.r[R_LR]; 500 saved_vrs.core.r[R_PC] = saved_vrs.core.r[R_LR];
465 stack_level++; 501 stack_level++;
@@ -493,7 +529,7 @@ int unwind_backtrace_with_ptrace(int tfd, pid_t pid, mapinfo *map,
493 _Unwind_SetGR((_Unwind_Context *)&saved_vrs, 12, (_Unwind_Ptr) ucbp); 529 _Unwind_SetGR((_Unwind_Context *)&saved_vrs, 12, (_Unwind_Ptr) ucbp);
494 530
495 /* Call log function. */ 531 /* Call log function. */
496 if (log_function ((_Unwind_Context *) &saved_vrs, tfd, stack_level, 532 if (log_function ((_Unwind_Context *) &saved_vrs, pid, tfd, stack_level,
497 map, sp_list, at_fault) != _URC_NO_REASON) { 533 map, sp_list, at_fault) != _URC_NO_REASON) {
498 code = _URC_FAILURE; 534 code = _URC_FAILURE;
499 break; 535 break;
diff --git a/debuggerd/utility.c b/debuggerd/utility.c
index 0cb790fd6..8f3931c1f 100644
--- a/debuggerd/utility.c
+++ b/debuggerd/utility.c
@@ -18,6 +18,7 @@
18#include <sys/ptrace.h> 18#include <sys/ptrace.h>
19#include <sys/exec_elf.h> 19#include <sys/exec_elf.h>
20#include <assert.h> 20#include <assert.h>
21#include <string.h>
21#include <errno.h> 22#include <errno.h>
22 23
23#include "utility.h" 24#include "utility.h"
@@ -66,10 +67,14 @@ const char *map_to_name(mapinfo *mi, unsigned pc, const char* def)
66} 67}
67 68
68/* Find the containing map info for the pc */ 69/* Find the containing map info for the pc */
69const mapinfo *pc_to_mapinfo(mapinfo *mi, unsigned pc) 70const mapinfo *pc_to_mapinfo(mapinfo *mi, unsigned pc, unsigned *rel_pc)
70{ 71{
71 while(mi) { 72 while(mi) {
72 if((pc >= mi->start) && (pc < mi->end)){ 73 if((pc >= mi->start) && (pc < mi->end)){
74 // Only calculate the relative offset for shared libraries
75 if (strstr(mi->name, ".so")) {
76 *rel_pc = pc - mi->start;
77 }
73 return mi; 78 return mi;
74 } 79 }
75 mi = mi->next; 80 mi = mi->next;
diff --git a/debuggerd/utility.h b/debuggerd/utility.h
index 802e3ad2e..49f59518e 100644
--- a/debuggerd/utility.h
+++ b/debuggerd/utility.h
@@ -45,7 +45,7 @@ extern int get_remote_word(int pid, void *src);
45extern void get_remote_struct(int pid, void *src, void *dst, size_t size); 45extern void get_remote_struct(int pid, void *src, void *dst, size_t size);
46 46
47/* Find the containing map for the pc */ 47/* Find the containing map for the pc */
48const mapinfo *pc_to_mapinfo (mapinfo *mi, unsigned pc); 48const mapinfo *pc_to_mapinfo (mapinfo *mi, unsigned pc, unsigned *rel_pc);
49 49
50/* Map a pc address to the name of the containing ELF file */ 50/* Map a pc address to the name of the containing ELF file */
51const char *map_to_name(mapinfo *mi, unsigned pc, const char* def); 51const char *map_to_name(mapinfo *mi, unsigned pc, const char* def);
diff --git a/fastboot/Android.mk b/fastboot/Android.mk
index 5e9941de9..7a9d35f28 100644
--- a/fastboot/Android.mk
+++ b/fastboot/Android.mk
@@ -43,7 +43,7 @@ endif
43LOCAL_STATIC_LIBRARIES := $(EXTRA_STATIC_LIBS) libzipfile libunz 43LOCAL_STATIC_LIBRARIES := $(EXTRA_STATIC_LIBS) libzipfile libunz
44 44
45include $(BUILD_HOST_EXECUTABLE) 45include $(BUILD_HOST_EXECUTABLE)
46$(call dist-for-goals,user userdebug droid,$(LOCAL_BUILT_MODULE)) 46$(call dist-for-goals,droid,$(LOCAL_BUILT_MODULE))
47 47
48ifeq ($(HOST_OS),linux) 48ifeq ($(HOST_OS),linux)
49include $(CLEAR_VARS) 49include $(CLEAR_VARS)
diff --git a/fastboot/fastboot.c b/fastboot/fastboot.c
index 64a4045c5..4079a3894 100644
--- a/fastboot/fastboot.c
+++ b/fastboot/fastboot.c
@@ -47,6 +47,7 @@ static const char *serial = 0;
47static const char *product = 0; 47static const char *product = 0;
48static const char *cmdline = 0; 48static const char *cmdline = 0;
49static int wipe_data = 0; 49static int wipe_data = 0;
50static unsigned short vendor_id = 0;
50 51
51void die(const char *fmt, ...) 52void die(const char *fmt, ...)
52{ 53{
@@ -135,7 +136,8 @@ oops:
135 136
136int match_fastboot(usb_ifc_info *info) 137int match_fastboot(usb_ifc_info *info)
137{ 138{
138 if((info->dev_vendor != 0x18d1) && 139 if(!(vendor_id && (info->dev_vendor == vendor_id)) &&
140 (info->dev_vendor != 0x18d1) &&
139 (info->dev_vendor != 0x0bb4)) return -1; 141 (info->dev_vendor != 0x0bb4)) return -1;
140 if(info->ifc_class != 0xff) return -1; 142 if(info->ifc_class != 0xff) return -1;
141 if(info->ifc_subclass != 0x42) return -1; 143 if(info->ifc_subclass != 0x42) return -1;
@@ -208,6 +210,7 @@ void usage(void)
208 " -s <serial number> specify device serial number\n" 210 " -s <serial number> specify device serial number\n"
209 " -p <product> specify product name\n" 211 " -p <product> specify product name\n"
210 " -c <cmdline> override kernel commandline\n" 212 " -c <cmdline> override kernel commandline\n"
213 " -i <vendor id> specify a custom USB vendor id\n"
211 ); 214 );
212 exit(1); 215 exit(1);
213} 216}
@@ -553,6 +556,16 @@ int main(int argc, char **argv)
553 require(2); 556 require(2);
554 cmdline = argv[1]; 557 cmdline = argv[1];
555 skip(2); 558 skip(2);
559 } else if(!strcmp(*argv, "-i")) {
560 char *endptr = NULL;
561 unsigned long val;
562
563 require(2);
564 val = strtoul(argv[1], &endptr, 0);
565 if (!endptr || *endptr != '\0' || (val & ~0xffff))
566 die("invalid vendor id '%s'", argv[1]);
567 vendor_id = (unsigned short)val;
568 skip(2);
556 } else if(!strcmp(*argv, "getvar")) { 569 } else if(!strcmp(*argv, "getvar")) {
557 require(2); 570 require(2);
558 fb_queue_display(argv[1], argv[1]); 571 fb_queue_display(argv[1], argv[1]);
diff --git a/include/arch/linux-arm/AndroidConfig.h b/include/arch/linux-arm/AndroidConfig.h
index d7e182a93..b2dabf210 100644
--- a/include/arch/linux-arm/AndroidConfig.h
+++ b/include/arch/linux-arm/AndroidConfig.h
@@ -48,6 +48,12 @@
48#define HAVE_FUTEX 48#define HAVE_FUTEX
49 49
50/* 50/*
51 * Define if we already have the futex wrapper functions defined. Yes if
52 * compiling against bionic.
53 */
54#define HAVE_FUTEX_WRAPPERS 1
55
56/*
51 * Process creation model. Choose one: 57 * Process creation model. Choose one:
52 * 58 *
53 * HAVE_FORKEXEC - use fork() and exec() 59 * HAVE_FORKEXEC - use fork() and exec()
diff --git a/include/arch/target_linux-x86/AndroidConfig.h b/include/arch/target_linux-x86/AndroidConfig.h
new file mode 100644
index 000000000..4aa44f883
--- /dev/null
+++ b/include/arch/target_linux-x86/AndroidConfig.h
@@ -0,0 +1,296 @@
1/*
2 * Copyright 2005 The Android Open Source Project
3 *
4 * Android config -- "target_linux-x86". Used for x86 linux target devices.
5 */
6#ifndef _ANDROID_CONFIG_H
7#define _ANDROID_CONFIG_H
8
9/*
10 * ===========================================================================
11 * !!! IMPORTANT !!!
12 * ===========================================================================
13 *
14 * This file is included by ALL C/C++ source files. Don't put anything in
15 * here unless you are absolutely certain it can't go anywhere else.
16 *
17 * Any C++ stuff must be wrapped with "#ifdef __cplusplus". Do not use "//"
18 * comments.
19 */
20
21/*
22 * Threading model. Choose one:
23 *
24 * HAVE_PTHREADS - use the pthreads library.
25 * HAVE_WIN32_THREADS - use Win32 thread primitives.
26 * -- combine HAVE_CREATETHREAD, HAVE_CREATEMUTEX, and HAVE__BEGINTHREADEX
27 */
28#define HAVE_PTHREADS
29
30/*
31 * Do we have the futex syscall?
32 */
33
34#define HAVE_FUTEX
35
36/*
37 * Define if we already have the futex wrapper functions defined. Yes if
38 * compiling against bionic.
39 */
40#define HAVE_FUTEX_WRAPPERS 1
41
42/*
43 * Process creation model. Choose one:
44 *
45 * HAVE_FORKEXEC - use fork() and exec()
46 * HAVE_WIN32_PROC - use CreateProcess()
47 */
48#define HAVE_FORKEXEC
49
50/*
51 * Process out-of-memory adjustment. Set if running on Linux,
52 * where we can write to /proc/<pid>/oom_adj to modify the out-of-memory
53 * badness adjustment.
54 */
55#define HAVE_OOM_ADJ
56
57/*
58 * IPC model. Choose one:
59 *
60 * HAVE_SYSV_IPC - use the classic SysV IPC mechanisms (semget, shmget).
61 * HAVE_MACOSX_IPC - use Macintosh IPC mechanisms (sem_open, mmap).
62 * HAVE_WIN32_IPC - use Win32 IPC (CreateSemaphore, CreateFileMapping).
63 * HAVE_ANDROID_IPC - use Android versions (?, mmap).
64 */
65#define HAVE_ANDROID_IPC 1
66
67/*
68 * Memory-mapping model. Choose one:
69 *
70 * HAVE_POSIX_FILEMAP - use the Posix sys/mmap.h
71 * HAVE_WIN32_FILEMAP - use Win32 filemaps
72 */
73#define HAVE_POSIX_FILEMAP 1
74
75/*
76 * Define this if you have <termio.h>
77 */
78#define HAVE_TERMIO_H 1
79
80/*
81 * Define this if you build against have Microsoft C runtime (MSVCRT.DLL)
82 */
83/* #define HAVE_MS_C_RUNTIME */
84
85/*
86 * Define this if you have sys/uio.h
87 */
88#define HAVE_SYS_UIO_H 1
89
90/*
91 * Define this if your platforms implements symbolic links
92 * in its filesystems
93 */
94#define HAVE_SYMLINKS 1
95
96/*
97 * Define this if we have localtime_r().
98 */
99/* #define HAVE_LOCALTIME_R */
100
101/*
102 * Define this if we have gethostbyname_r().
103 */
104/* #define HAVE_GETHOSTBYNAME_R */
105
106/*
107 * Define this if we have ioctl().
108 */
109#define HAVE_IOCTL
110
111/*
112 * Define this if we want to use WinSock.
113 */
114/* #define HAVE_WINSOCK */
115
116/*
117 * Define this if have clock_gettime() and friends
118 *
119 */
120#define HAVE_POSIX_CLOCKS
121
122/*
123 * Define this if we have pthread_cond_timedwait_monotonic() and
124 * clock_gettime(CLOCK_MONOTONIC).
125 */
126#define HAVE_TIMEDWAIT_MONOTONIC
127
128/*
129 * Define this if we have linux style epoll()
130 */
131#define HAVE_EPOLL
132
133/*
134 * Endianness of the target machine. Choose one:
135 *
136 * HAVE_ENDIAN_H -- have endian.h header we can include.
137 * HAVE_LITTLE_ENDIAN -- we are little endian.
138 * HAVE_BIG_ENDIAN -- we are big endian.
139 */
140#define HAVE_ENDIAN_H
141#define HAVE_LITTLE_ENDIAN
142
143/*
144 * We need to choose between 32-bit and 64-bit off_t. All of our code should
145 * agree on the same size. For desktop systems, use 64-bit values,
146 * because some of our libraries (e.g. wxWidgets) expect to be built that way.
147 */
148/*
149 * #define _FILE_OFFSET_BITS 64
150 * #define _LARGEFILE_SOURCE 1
151 */
152
153/*
154 * Defined if we have the backtrace() call for retrieving a stack trace.
155 * Needed for CallStack to operate; if not defined, CallStack is
156 * non-functional.
157 */
158#define HAVE_BACKTRACE 0
159
160/*
161 * Defined if we have the dladdr() call for retrieving the symbol associated
162 * with a memory address. If not defined, stack crawls will not have symbolic
163 * information.
164 */
165#define HAVE_DLADDR 0
166
167/*
168 * Defined if we have the cxxabi.h header for demangling C++ symbols. If
169 * not defined, stack crawls will be displayed with raw mangled symbols
170 */
171#define HAVE_CXXABI 0
172
173/*
174 * Defined if we have the gettid() system call.
175 */
176#define HAVE_GETTID
177
178/*
179 * Defined if we have the sched_setscheduler() call
180 */
181#define HAVE_SCHED_SETSCHEDULER
182
183/*
184 * Add any extra platform-specific defines here.
185 */
186#ifndef __linux__
187#define __linux__
188#endif
189
190/*
191 * Define if we have <malloc.h> header
192 */
193#define HAVE_MALLOC_H
194
195/*
196 * Define if we're running on *our* linux on device or emulator.
197 */
198#define HAVE_ANDROID_OS 1
199
200/*
201 * Define if we have Linux-style non-filesystem Unix Domain Sockets
202 */
203#define HAVE_LINUX_LOCAL_SOCKET_NAMESPACE 1
204
205/*
206 * Define if we have Linux's inotify in <sys/inotify.h>.
207 */
208#define HAVE_INOTIFY 1
209
210/*
211 * Define if we have madvise() in <sys/mman.h>
212 */
213#define HAVE_MADVISE 1
214
215/*
216 * Define if we have Linux's dbus
217 */
218#define HAVE_DBUS 1
219
220/*
221 * Define if tm struct has tm_gmtoff field
222 */
223#define HAVE_TM_GMTOFF 1
224
225/*
226 * Define if dirent struct has d_type field
227 */
228#define HAVE_DIRENT_D_TYPE 1
229
230/*
231 * Define if libc includes Android system properties implementation.
232 */
233#define HAVE_LIBC_SYSTEM_PROPERTIES 1
234
235/*
236 * Define if system provides a system property server (should be
237 * mutually exclusive with HAVE_LIBC_SYSTEM_PROPERTIES).
238 */
239/* #define HAVE_SYSTEM_PROPERTY_SERVER */
240
241/*
242 * What CPU architecture does this platform use?
243 */
244#define ARCH_X86
245
246/*
247 * sprintf() format string for shared library naming.
248 */
249#define OS_SHARED_LIB_FORMAT_STR "lib%s.so"
250
251/*
252 * Do we have __memcmp16()?
253 */
254/* #define HAVE__MEMCMP16 1 */
255
256/*
257 * type for the third argument to mincore().
258 */
259#define MINCORE_POINTER_TYPE unsigned char *
260
261/*
262 * Do we have the sigaction flag SA_NOCLDWAIT?
263 */
264#define HAVE_SA_NOCLDWAIT
265
266/*
267 * The default path separator for the platform
268 */
269#define OS_PATH_SEPARATOR '/'
270
271/*
272 * Is the filesystem case sensitive?
273 */
274#define OS_CASE_SENSITIVE
275
276/*
277 * Define if <sys/socket.h> exists.
278 */
279#define HAVE_SYS_SOCKET_H 1
280
281/*
282 * Define if the strlcpy() function exists on the system.
283 */
284#define HAVE_STRLCPY 1
285
286/*
287 * Define if prctl() exists
288 */
289#define HAVE_PRCTL 1
290
291/*
292 * Whether or not _Unwind_Context is defined as a struct.
293 */
294#define HAVE_UNWIND_CONTEXT_STRUCT
295
296#endif /* _ANDROID_CONFIG_H */
diff --git a/include/cutils/tztime.h b/include/cutils/tztime.h
index 59c0670d6..9b3ece84c 100644
--- a/include/cutils/tztime.h
+++ b/include/cutils/tztime.h
@@ -24,6 +24,21 @@ extern "C" {
24time_t mktime_tz(struct tm * const tmp, char const * tz); 24time_t mktime_tz(struct tm * const tmp, char const * tz);
25void localtime_tz(const time_t * const timep, struct tm * tmp, const char* tz); 25void localtime_tz(const time_t * const timep, struct tm * tmp, const char* tz);
26 26
27struct strftime_locale {
28 const char *mon[12]; /* short names */
29 const char *month[12]; /* long names */
30 const char *wday[7]; /* short names */
31 const char *weekday[7]; /* long names */
32 const char *X_fmt;
33 const char *x_fmt;
34 const char *c_fmt;
35 const char *am;
36 const char *pm;
37 const char *date_fmt;
38};
39
40size_t strftime_tz(char *s, size_t max, const char *format, const struct tm *tm, const struct strftime_locale *locale);
41
27#ifdef __cplusplus 42#ifdef __cplusplus
28} 43}
29#endif 44#endif
diff --git a/include/pixelflinger/format.h b/include/pixelflinger/format.h
index ad0d29d84..308e56002 100644
--- a/include/pixelflinger/format.h
+++ b/include/pixelflinger/format.h
@@ -30,6 +30,7 @@ enum GGLPixelFormat {
30 GGL_PIXEL_FORMAT_RGBX_8888 = 2, // 3x8-bit RGB stored in 32-bit chunks 30 GGL_PIXEL_FORMAT_RGBX_8888 = 2, // 3x8-bit RGB stored in 32-bit chunks
31 GGL_PIXEL_FORMAT_RGB_888 = 3, // 3x8-bit RGB 31 GGL_PIXEL_FORMAT_RGB_888 = 3, // 3x8-bit RGB
32 GGL_PIXEL_FORMAT_RGB_565 = 4, // 16-bit RGB 32 GGL_PIXEL_FORMAT_RGB_565 = 4, // 16-bit RGB
33 GGL_PIXEL_FORMAT_BGRA_8888 = 5, // 4x8-bit BGRA
33 GGL_PIXEL_FORMAT_RGBA_5551 = 6, // 16-bit RGBA 34 GGL_PIXEL_FORMAT_RGBA_5551 = 6, // 16-bit RGBA
34 GGL_PIXEL_FORMAT_RGBA_4444 = 7, // 16-bit RGBA 35 GGL_PIXEL_FORMAT_RGBA_4444 = 7, // 16-bit RGBA
35 36
@@ -38,9 +39,11 @@ enum GGLPixelFormat {
38 GGL_PIXEL_FORMAT_LA_88 = 0xA, // 16-bit LA 39 GGL_PIXEL_FORMAT_LA_88 = 0xA, // 16-bit LA
39 GGL_PIXEL_FORMAT_RGB_332 = 0xB, // 8-bit RGB (non paletted) 40 GGL_PIXEL_FORMAT_RGB_332 = 0xB, // 8-bit RGB (non paletted)
40 41
41 // YCbCr formats 42 // YCbCr formats (SP=semi-planar, P=planar)
42 GGL_PIXEL_FORMAT_YCbCr_422_SP= 0x10, 43 GGL_PIXEL_FORMAT_YCbCr_422_SP= 0x10,
43 GGL_PIXEL_FORMAT_YCbCr_420_SP= 0x11, 44 GGL_PIXEL_FORMAT_YCbCr_420_SP= 0x11,
45 GGL_PIXEL_FORMAT_YCbCr_422_P = 0x14,
46 GGL_PIXEL_FORMAT_YCbCr_420_P = 0x15,
44 47
45 // reserved/special formats 48 // reserved/special formats
46 GGL_PIXEL_FORMAT_Z_16 = 0x18, 49 GGL_PIXEL_FORMAT_Z_16 = 0x18,
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index 13e134bba..c8551872a 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -150,8 +150,10 @@ static struct fs_path_config android_files[] = {
150 { 00550, AID_ROOT, AID_SHELL, "system/etc/init.testmenu" }, 150 { 00550, AID_ROOT, AID_SHELL, "system/etc/init.testmenu" },
151 { 00550, AID_ROOT, AID_SHELL, "system/etc/init.gprs-pppd" }, 151 { 00550, AID_ROOT, AID_SHELL, "system/etc/init.gprs-pppd" },
152 { 00550, AID_DHCP, AID_SHELL, "system/etc/dhcpcd/dhcpcd-run-hooks" }, 152 { 00550, AID_DHCP, AID_SHELL, "system/etc/dhcpcd/dhcpcd-run-hooks" },
153 { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/hcid.conf" },
154 { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/dbus.conf" }, 153 { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/dbus.conf" },
154 { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluez/hcid.conf" },
155 { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluez/input.conf" },
156 { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluez/audio.conf" },
155 { 00440, AID_RADIO, AID_AUDIO, "/system/etc/AudioPara4.csv" }, 157 { 00440, AID_RADIO, AID_AUDIO, "/system/etc/AudioPara4.csv" },
156 { 00644, AID_SYSTEM, AID_SYSTEM, "data/app/*" }, 158 { 00644, AID_SYSTEM, AID_SYSTEM, "data/app/*" },
157 { 00644, AID_SYSTEM, AID_SYSTEM, "data/app-private/*" }, 159 { 00644, AID_SYSTEM, AID_SYSTEM, "data/app-private/*" },
diff --git a/include/private/pixelflinger/ggl_context.h b/include/private/pixelflinger/ggl_context.h
index 241a0abdb..3a030c526 100644
--- a/include/private/pixelflinger/ggl_context.h
+++ b/include/private/pixelflinger/ggl_context.h
@@ -147,11 +147,11 @@ GGL_RESERVE_NEEDS( P_FOG, 9, 1 )
147GGL_RESERVE_NEEDS( P_RESERVED1, 10,22 ) 147GGL_RESERVE_NEEDS( P_RESERVED1, 10,22 )
148 148
149GGL_RESERVE_NEEDS( T_FORMAT, 0, 6 ) 149GGL_RESERVE_NEEDS( T_FORMAT, 0, 6 )
150GGL_RESERVE_NEEDS( T_RESERVED0, 6, 2 ) 150GGL_RESERVE_NEEDS( T_RESERVED0, 6, 1 )
151GGL_RESERVE_NEEDS( T_POT, 7, 1 )
151GGL_RESERVE_NEEDS( T_S_WRAP, 8, 2 ) 152GGL_RESERVE_NEEDS( T_S_WRAP, 8, 2 )
152GGL_RESERVE_NEEDS( T_T_WRAP, 10, 2 ) 153GGL_RESERVE_NEEDS( T_T_WRAP, 10, 2 )
153GGL_RESERVE_NEEDS( T_ENV, 12, 2 ) 154GGL_RESERVE_NEEDS( T_ENV, 12, 3 )
154GGL_RESERVE_NEEDS( T_POT, 14, 1 )
155GGL_RESERVE_NEEDS( T_LINEAR, 15, 1 ) 155GGL_RESERVE_NEEDS( T_LINEAR, 15, 1 )
156 156
157const int GGL_NEEDS_WRAP_CLAMP_TO_EDGE = 0; 157const int GGL_NEEDS_WRAP_CLAMP_TO_EDGE = 0;
@@ -182,12 +182,14 @@ inline uint32_t ggl_env_to_needs(uint32_t e) {
182 case GGL_MODULATE: return 1; 182 case GGL_MODULATE: return 1;
183 case GGL_DECAL: return 2; 183 case GGL_DECAL: return 2;
184 case GGL_BLEND: return 3; 184 case GGL_BLEND: return 3;
185 case GGL_ADD: return 4;
185 } 186 }
186 return 0; 187 return 0;
187} 188}
188 189
189inline uint32_t ggl_needs_to_env(uint32_t n) { 190inline uint32_t ggl_needs_to_env(uint32_t n) {
190 const uint32_t envs[] = { GGL_REPLACE, GGL_MODULATE, GGL_DECAL, GGL_BLEND }; 191 const uint32_t envs[] = { GGL_REPLACE, GGL_MODULATE,
192 GGL_DECAL, GGL_BLEND, GGL_ADD };
191 return envs[n]; 193 return envs[n];
192 194
193} 195}
diff --git a/init/README.BOOTCHART b/init/README.BOOTCHART
index 489936973..70cf2c39b 100644
--- a/init/README.BOOTCHART
+++ b/init/README.BOOTCHART
@@ -1,32 +1,50 @@
1this version of init contains code to perform "bootcharting", i.e. generating log 1This version of init contains code to perform "bootcharting", i.e. generating log
2files that can be later processed by the tools provided by www.bootchart.org. 2files that can be later processed by the tools provided by www.bootchart.org.
3 3
4to activate it, you need to define build 'init' with the INIT_BOOTCHART environment 4To activate it, you need to define build 'init' with the INIT_BOOTCHART environment
5variable defined to 'true', then create a file on the /data partition with a command 5variable defined to 'true', for example:
6like the following:
7 6
8 adb shell 'echo 1 > /data/bootchart' 7 touch system/init/init.c
8 m INIT_BOOTCHART=true
9 9
10if the '/data/bootchart' file doesn't exist, or doesn't contain a '1' in its first 10On the emulator, use the new -bootchart <timeout> option to boot with bootcharting
11byte, init will proceed normally. 11activated for <timeout> seconds.
12 12
13by default, the bootchart log stops after 2 minutes, but you can stop it earlier 13Otherwise, flash your device, and start it. Then create a file on the /data partition
14with the following command while the device is booting: 14with a command like the following:
15
16 adb shell 'echo $TIMEOUT > /data/bootchart-start'
17
18Where the value of $TIMEOUT corresponds to the wanted bootcharted period in seconds;
19for example, to bootchart for 2 minutes, do:
20
21 adb shell 'echo 120 > /data/bootchart-start'
22
23Reboot your device, bootcharting will begin and stop after the period you gave.
24You can also stop the bootcharting at any moment by doing the following:
15 25
16 adb shell 'echo 1 > /data/bootchart-stop' 26 adb shell 'echo 1 > /data/bootchart-stop'
17 27
18note that /data/bootchart-stop is deleted automatically by init at the end of the 28Note that /data/bootchart-stop is deleted automatically by init at the end of the
19bootcharting. this is not the case of /data/bootchart, so don't forget to delete it 29bootcharting. This is not the case of /data/bootchart-start, so don't forget to delete it
20when you're done collecting data: 30when you're done collecting data:
21 31
22 adb shell rm /data/bootchart 32 adb shell rm /data/bootchart-start
23 33
24the log files are placed in /tmp/bootchart/. you must run the script tools/grab-bootchart.sh 34The log files are placed in /data/bootchart/. you must run the script tools/grab-bootchart.sh
25which will use ADB to retrieve them and create a bootchart.tgz file that can be used with 35which will use ADB to retrieve them and create a bootchart.tgz file that can be used with
26the bootchart parser/renderer, or even uploaded directly to the form located at: 36the bootchart parser/renderer, or even uploaded directly to the form located at:
27 37
28 http://www.bootchart.org/download.html 38 http://www.bootchart.org/download.html
29 39
40NOTE: the bootchart.org webform doesn't seem to work at the moment, you can generate an
41 image on your machine by doing the following:
42
43 1/ download the sources from www.bootchart.org
44 2/ unpack them
45 3/ in the source directory, type 'ant' to build the bootchart program
46 4/ type 'java -jar bootchart.jar /path/to/bootchart.tgz
47
30technical note: 48technical note:
31 49
32this implementation of bootcharting does use the 'bootchartd' script provided by 50this implementation of bootcharting does use the 'bootchartd' script provided by
diff --git a/init/bootchart.c b/init/bootchart.c
index 2afe98b6b..f72fcaaca 100644
--- a/init/bootchart.c
+++ b/init/bootchart.c
@@ -1,3 +1,19 @@
1/*
2 * Copyright (C) 2008 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
1/* this code is used to generate a boot sequence profile that can be used 17/* this code is used to generate a boot sequence profile that can be used
2 * with the 'bootchart' graphics generation tool. see www.bootchart.org 18 * with the 'bootchart' graphics generation tool. see www.bootchart.org
3 * note that unlike the original bootchartd, this is not a Bash script but 19 * note that unlike the original bootchartd, this is not a Bash script but
@@ -16,17 +32,18 @@
16#include <errno.h> 32#include <errno.h>
17#include <stdlib.h> 33#include <stdlib.h>
18#include <sys/stat.h> 34#include <sys/stat.h>
35#include "bootchart.h"
19 36
20#define VERSION "0.8" 37#define VERSION "0.8"
21#define SAMPLE_PERIOD 0.2 38#define SAMPLE_PERIOD 0.2
22#define LOG_ROOT "/tmp/bootchart" 39#define LOG_ROOT "/data/bootchart"
23#define LOG_STAT LOG_ROOT"/proc_stat.log" 40#define LOG_STAT LOG_ROOT"/proc_stat.log"
24#define LOG_PROCS LOG_ROOT"/proc_ps.log" 41#define LOG_PROCS LOG_ROOT"/proc_ps.log"
25#define LOG_DISK LOG_ROOT"/proc_diskstats.log" 42#define LOG_DISK LOG_ROOT"/proc_diskstats.log"
26#define LOG_HEADER LOG_ROOT"/header" 43#define LOG_HEADER LOG_ROOT"/header"
27#define LOG_ACCT LOG_ROOT"/kernel_pacct" 44#define LOG_ACCT LOG_ROOT"/kernel_pacct"
28 45
29#define LOG_STARTFILE "/data/bootchart" 46#define LOG_STARTFILE "/data/bootchart-start"
30#define LOG_STOPFILE "/data/bootchart-stop" 47#define LOG_STOPFILE "/data/bootchart-stop"
31 48
32static int 49static int
@@ -54,12 +71,11 @@ proc_read(const char* filename, char* buff, size_t buffsize)
54 len = unix_read(fd, buff, buffsize-1); 71 len = unix_read(fd, buff, buffsize-1);
55 close(fd); 72 close(fd);
56 } 73 }
57 buff[len] = 0; 74 buff[len > 0 ? len : 0] = 0;
58 return len; 75 return len;
59} 76}
60 77
61#define FILE_BUFF_SIZE 65536 78#define FILE_BUFF_SIZE 65536
62#define FILE_BUFF_RESERVE (FILE_BUFF_SIZE - 4096)
63 79
64typedef struct { 80typedef struct {
65 int count; 81 int count;
@@ -81,7 +97,7 @@ file_buff_write( FileBuff buff, const void* src, int len )
81 int avail = sizeof(buff->data) - buff->count; 97 int avail = sizeof(buff->data) - buff->count;
82 if (avail > len) 98 if (avail > len)
83 avail = len; 99 avail = len;
84 100
85 memcpy( buff->data + buff->count, src, avail ); 101 memcpy( buff->data + buff->count, src, avail );
86 len -= avail; 102 len -= avail;
87 src = (char*)src + avail; 103 src = (char*)src + avail;
@@ -115,7 +131,7 @@ log_header(void)
115 time_t now_t = time(NULL); 131 time_t now_t = time(NULL);
116 struct tm now = *localtime(&now_t); 132 struct tm now = *localtime(&now_t);
117 strftime(date, sizeof(date), "%x %X", &now); 133 strftime(date, sizeof(date), "%x %X", &now);
118 134
119 out = fopen( LOG_HEADER, "w" ); 135 out = fopen( LOG_HEADER, "w" );
120 if (out == NULL) 136 if (out == NULL)
121 return; 137 return;
@@ -123,7 +139,7 @@ log_header(void)
123 proc_read("/proc/cmdline", cmdline, sizeof(cmdline)); 139 proc_read("/proc/cmdline", cmdline, sizeof(cmdline));
124 proc_read("/proc/version", uname, sizeof(uname)); 140 proc_read("/proc/version", uname, sizeof(uname));
125 proc_read("/proc/cpuinfo", cpuinfo, sizeof(cpuinfo)); 141 proc_read("/proc/cpuinfo", cpuinfo, sizeof(cpuinfo));
126 142
127 cpu = strchr( cpuinfo, ':' ); 143 cpu = strchr( cpuinfo, ':' );
128 if (cpu) { 144 if (cpu) {
129 char* p = strchr(cpu, '\n'); 145 char* p = strchr(cpu, '\n');
@@ -131,7 +147,7 @@ log_header(void)
131 if (p) 147 if (p)
132 *p = 0; 148 *p = 0;
133 } 149 }
134 150
135 fprintf(out, "version = %s\n", VERSION); 151 fprintf(out, "version = %s\n", VERSION);
136 fprintf(out, "title = Boot chart for Android ( %s )\n", date); 152 fprintf(out, "title = Boot chart for Android ( %s )\n", date);
137 fprintf(out, "system.uname = %s\n", uname); 153 fprintf(out, "system.uname = %s\n", uname);
@@ -174,7 +190,6 @@ do_log_uptime(FileBuff log)
174 fd = open("/proc/uptime",O_RDONLY); 190 fd = open("/proc/uptime",O_RDONLY);
175 if (fd >= 0) { 191 if (fd >= 0) {
176 int ret; 192 int ret;
177 close_on_exec(fd);
178 ret = unix_read(fd, buff, 64); 193 ret = unix_read(fd, buff, 64);
179 close(fd); 194 close(fd);
180 buff[64] = 0; 195 buff[64] = 0;
@@ -212,7 +227,7 @@ do_log_file(FileBuff log, const char* procfile)
212 ret = unix_read(fd, buff, sizeof(buff)); 227 ret = unix_read(fd, buff, sizeof(buff));
213 if (ret <= 0) 228 if (ret <= 0)
214 break; 229 break;
215 230
216 file_buff_write(log, buff, ret); 231 file_buff_write(log, buff, ret);
217 if (ret < (int)sizeof(buff)) 232 if (ret < (int)sizeof(buff))
218 break; 233 break;
@@ -230,7 +245,7 @@ do_log_procs(FileBuff log)
230 struct dirent* entry; 245 struct dirent* entry;
231 246
232 do_log_uptime(log); 247 do_log_uptime(log);
233 248
234 while ((entry = readdir(dir)) != NULL) { 249 while ((entry = readdir(dir)) != NULL) {
235 /* only match numeric values */ 250 /* only match numeric values */
236 char* end; 251 char* end;
@@ -241,7 +256,7 @@ do_log_procs(FileBuff log)
241 char cmdline[1024]; 256 char cmdline[1024];
242 int len; 257 int len;
243 int fd; 258 int fd;
244 259
245 /* read command line and extract program name */ 260 /* read command line and extract program name */
246 snprintf(filename,sizeof(filename),"/proc/%d/cmdline",pid); 261 snprintf(filename,sizeof(filename),"/proc/%d/cmdline",pid);
247 proc_read(filename, cmdline, sizeof(cmdline)); 262 proc_read(filename, cmdline, sizeof(cmdline));
@@ -285,11 +300,36 @@ int bootchart_init( void )
285{ 300{
286 int ret; 301 int ret;
287 char buff[4]; 302 char buff[4];
288 303 int timeout = 0, count = 0;
304
289 buff[0] = 0; 305 buff[0] = 0;
290 proc_read( LOG_STARTFILE, buff, sizeof(buff) ); 306 proc_read( LOG_STARTFILE, buff, sizeof(buff) );
291 if (buff[0] != '1') 307 if (buff[0] != 0) {
292 return -1; 308 timeout = atoi(buff);
309 }
310 else {
311 /* when running with emulator, androidboot.bootchart=<timeout>
312 * might be passed by as kernel parameters to specify the bootchart
313 * timeout. this is useful when using -wipe-data since the /data
314 * partition is fresh
315 */
316 char cmdline[1024];
317 char* s;
318#define KERNEL_OPTION "androidboot.bootchart="
319 proc_read( "/proc/cmdline", cmdline, sizeof(cmdline) );
320 s = strstr(cmdline, KERNEL_OPTION);
321 if (s) {
322 s += sizeof(KERNEL_OPTION)-1;
323 timeout = atoi(s);
324 }
325 }
326 if (timeout == 0)
327 return 0;
328
329 if (timeout > BOOTCHART_MAX_TIME_SEC)
330 timeout = BOOTCHART_MAX_TIME_SEC;
331
332 count = (timeout*1000 + BOOTCHART_POLLING_MS-1)/BOOTCHART_POLLING_MS;
293 333
294 do {ret=mkdir(LOG_ROOT,0755);}while (ret < 0 && errno == EINTR); 334 do {ret=mkdir(LOG_ROOT,0755);}while (ret < 0 && errno == EINTR);
295 335
@@ -307,7 +347,7 @@ int bootchart_init( void )
307 } 347 }
308 348
309 log_header(); 349 log_header();
310 return 0; 350 return count;
311} 351}
312 352
313/* called each time you want to perform a bootchart sampling op */ 353/* called each time you want to perform a bootchart sampling op */
@@ -324,6 +364,7 @@ int bootchart_step( void )
324 return -1; 364 return -1;
325 } 365 }
326 } 366 }
367
327 return 0; 368 return 0;
328} 369}
329 370
diff --git a/init/bootchart.h b/init/bootchart.h
new file mode 100644
index 000000000..39d2d4f20
--- /dev/null
+++ b/init/bootchart.h
@@ -0,0 +1,36 @@
1/*
2 * Copyright (C) 2008 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#ifndef _BOOTCHART_H
18#define _BOOTCHART_H
19
20#ifndef BOOTCHART
21# define BOOTCHART 0
22#endif
23
24#if BOOTCHART
25
26extern int bootchart_init(void);
27extern int bootchart_step(void);
28extern void bootchart_finish(void);
29
30# define BOOTCHART_POLLING_MS 200 /* polling period in ms */
31# define BOOTCHART_DEFAULT_TIME_SEC (2*60) /* default polling time in seconds */
32# define BOOTCHART_MAX_TIME_SEC (10*60) /* max polling time in seconds */
33
34#endif /* BOOTCHART */
35
36#endif /* _BOOTCHART_H */
diff --git a/init/builtins.c b/init/builtins.c
index ba344100c..95fb22304 100644
--- a/init/builtins.c
+++ b/init/builtins.c
@@ -64,7 +64,7 @@ static int write_file(const char *path, const char *value)
64 } 64 }
65} 65}
66 66
67static int insmod(const char *filename) 67static int insmod(const char *filename, char *options)
68{ 68{
69 void *module; 69 void *module;
70 unsigned size; 70 unsigned size;
@@ -74,7 +74,7 @@ static int insmod(const char *filename)
74 if (!module) 74 if (!module)
75 return -1; 75 return -1;
76 76
77 ret = init_module(module, size, ""); 77 ret = init_module(module, size, options);
78 78
79 free(module); 79 free(module);
80 80
@@ -172,9 +172,35 @@ int do_ifup(int nargs, char **args)
172 return __ifupdown(args[1], 1); 172 return __ifupdown(args[1], 1);
173} 173}
174 174
175
176static int do_insmod_inner(int nargs, char **args, int opt_len)
177{
178 char options[opt_len + 1];
179 int i;
180
181 options[0] = '\0';
182 if (nargs > 2) {
183 strcpy(options, args[2]);
184 for (i = 3; i < nargs; ++i) {
185 strcat(options, " ");
186 strcat(options, args[i]);
187 }
188 }
189
190 return insmod(args[1], options);
191}
192
175int do_insmod(int nargs, char **args) 193int do_insmod(int nargs, char **args)
176{ 194{
177 return insmod(args[1]); 195 int i;
196 int size = 0;
197
198 if (nargs > 2) {
199 for (i = 2; i < nargs; ++i)
200 size += strlen(args[i]) + 1;
201 }
202
203 return do_insmod_inner(nargs, args, size);
178} 204}
179 205
180int do_import(int nargs, char **args) 206int do_import(int nargs, char **args)
@@ -326,6 +352,20 @@ int do_symlink(int nargs, char **args)
326 return symlink(args[1], args[2]); 352 return symlink(args[1], args[2]);
327} 353}
328 354
355int do_sysclktz(int nargs, char **args)
356{
357 struct timezone tz;
358
359 if (nargs != 2)
360 return -1;
361
362 memset(&tz, 0, sizeof(tz));
363 tz.tz_minuteswest = atoi(args[1]);
364 if (settimeofday(NULL, &tz))
365 return -1;
366 return 0;
367}
368
329int do_write(int nargs, char **args) 369int do_write(int nargs, char **args)
330{ 370{
331 return write_file(args[1], args[2]); 371 return write_file(args[1], args[2]);
diff --git a/init/devices.c b/init/devices.c
index 7aea24623..f86eab991 100644
--- a/init/devices.c
+++ b/init/devices.c
@@ -98,9 +98,12 @@ static struct perms_ devperms[] = {
98 /* these should not be world writable */ 98 /* these should not be world writable */
99 { "/dev/android_adb", 0660, AID_ADB, AID_ADB, 0 }, 99 { "/dev/android_adb", 0660, AID_ADB, AID_ADB, 0 },
100 { "/dev/android_adb_enable", 0660, AID_ADB, AID_ADB, 0 }, 100 { "/dev/android_adb_enable", 0660, AID_ADB, AID_ADB, 0 },
101 { "/dev/ttyMSM0", 0660, AID_BLUETOOTH, AID_BLUETOOTH, 0 }, 101 /* TODO: remove legacy ttyMSM0 */
102 { "/dev/ttyMSM0", 0600, AID_BLUETOOTH, AID_BLUETOOTH, 0 },
103 { "/dev/ttyHS0", 0600, AID_BLUETOOTH, AID_BLUETOOTH, 0 },
104 { "/dev/uinput", 0600, AID_BLUETOOTH, AID_BLUETOOTH, 0 },
102 { "/dev/alarm", 0664, AID_SYSTEM, AID_RADIO, 0 }, 105 { "/dev/alarm", 0664, AID_SYSTEM, AID_RADIO, 0 },
103 { "/dev/tty0", 0666, AID_ROOT, AID_SYSTEM, 0 }, 106 { "/dev/tty0", 0660, AID_ROOT, AID_SYSTEM, 0 },
104 { "/dev/graphics/", 0660, AID_ROOT, AID_GRAPHICS, 1 }, 107 { "/dev/graphics/", 0660, AID_ROOT, AID_GRAPHICS, 1 },
105 { "/dev/hw3d", 0660, AID_SYSTEM, AID_GRAPHICS, 0 }, 108 { "/dev/hw3d", 0660, AID_SYSTEM, AID_GRAPHICS, 0 },
106 { "/dev/input/", 0660, AID_ROOT, AID_INPUT, 1 }, 109 { "/dev/input/", 0660, AID_ROOT, AID_INPUT, 1 },
@@ -360,29 +363,29 @@ static void handle_device_event(struct uevent *uevent)
360 return; 363 return;
361 364
362 /* are we block or char? where should we live? */ 365 /* are we block or char? where should we live? */
363 if(!strncmp(uevent->path, "/block", 6)) { 366 if(!strncmp(uevent->subsystem, "block", 5)) {
364 block = 1; 367 block = 1;
365 base = "/dev/block/"; 368 base = "/dev/block/";
366 mkdir(base, 0755); 369 mkdir(base, 0755);
367 } else { 370 } else {
368 block = 0; 371 block = 0;
369 /* this should probably be configurable somehow */ 372 /* this should probably be configurable somehow */
370 if(!strncmp(uevent->path, "/class/graphics/", 16)) { 373 if(!strncmp(uevent->subsystem, "graphics", 8)) {
371 base = "/dev/graphics/"; 374 base = "/dev/graphics/";
372 mkdir(base, 0755); 375 mkdir(base, 0755);
373 } else if (!strncmp(uevent->path, "/class/oncrpc/", 14)) { 376 } else if (!strncmp(uevent->subsystem, "oncrpc", 6)) {
374 base = "/dev/oncrpc/"; 377 base = "/dev/oncrpc/";
375 mkdir(base, 0755); 378 mkdir(base, 0755);
376 } else if (!strncmp(uevent->path, "/class/adsp/", 12)) { 379 } else if (!strncmp(uevent->subsystem, "adsp", 4)) {
377 base = "/dev/adsp/"; 380 base = "/dev/adsp/";
378 mkdir(base, 0755); 381 mkdir(base, 0755);
379 } else if(!strncmp(uevent->path, "/class/input/", 13)) { 382 } else if(!strncmp(uevent->subsystem, "input", 5)) {
380 base = "/dev/input/"; 383 base = "/dev/input/";
381 mkdir(base, 0755); 384 mkdir(base, 0755);
382 } else if(!strncmp(uevent->path, "/class/mtd/", 11)) { 385 } else if(!strncmp(uevent->subsystem, "mtd", 3)) {
383 base = "/dev/mtd/"; 386 base = "/dev/mtd/";
384 mkdir(base, 0755); 387 mkdir(base, 0755);
385 } else if(!strncmp(uevent->path, "/class/misc/", 12) && 388 } else if(!strncmp(uevent->subsystem, "misc", 4) &&
386 !strncmp(name, "log_", 4)) { 389 !strncmp(name, "log_", 4)) {
387 base = "/dev/log/"; 390 base = "/dev/log/";
388 mkdir(base, 0755); 391 mkdir(base, 0755);
diff --git a/init/grab-bootchart.sh b/init/grab-bootchart.sh
index 57c955688..7fe890436 100755
--- a/init/grab-bootchart.sh
+++ b/init/grab-bootchart.sh
@@ -9,13 +9,13 @@ TMPDIR=/tmp/android-bootchart
9rm -rf $TMPDIR 9rm -rf $TMPDIR
10mkdir -p $TMPDIR 10mkdir -p $TMPDIR
11 11
12LOGROOT=/tmp/bootchart 12LOGROOT=/data/bootchart
13TARBALL=bootchart.tgz 13TARBALL=bootchart.tgz
14 14
15FILES="header proc_stat.log proc_ps.log proc_diskstats.log kernel_pacct" 15FILES="header proc_stat.log proc_ps.log proc_diskstats.log kernel_pacct"
16 16
17for f in $FILES; do 17for f in $FILES; do
18 adb pull $LOGROOT/$f $TMPDIR/$f &> /dev/null 18 adb pull $LOGROOT/$f $TMPDIR/$f 2>&1 > /dev/null
19done 19done
20(cd $TMPDIR && tar -czf $TARBALL $FILES) 20(cd $TMPDIR && tar -czf $TARBALL $FILES)
21cp -f $TMPDIR/$TARBALL ./$TARBALL 21cp -f $TMPDIR/$TARBALL ./$TARBALL
diff --git a/init/init.c b/init/init.c
index f6e9b398b..361684095 100644
--- a/init/init.c
+++ b/init/init.c
@@ -43,21 +43,12 @@
43#include "devices.h" 43#include "devices.h"
44#include "init.h" 44#include "init.h"
45#include "property_service.h" 45#include "property_service.h"
46 46#include "bootchart.h"
47#ifndef BOOTCHART
48# define BOOTCHART 0
49#endif
50 47
51static int property_triggers_enabled = 0; 48static int property_triggers_enabled = 0;
52 49
53#if BOOTCHART 50#if BOOTCHART
54static int bootchart_count; 51static int bootchart_count;
55extern int bootchart_init(void);
56extern int bootchart_step(void);
57extern void bootchart_finish(void);
58# define BOOTCHART_POLLING_MS 200 /* polling period in ms */
59# define BOOTCHART_MAX_TIME_MS (2*60*1000) /* max polling time from boot */
60# define BOOTCHART_MAX_COUNT (BOOTCHART_MAX_TIME_MS/BOOTCHART_POLLING_MS)
61#endif 52#endif
62 53
63static char console[32]; 54static char console[32];
@@ -834,11 +825,13 @@ int main(int argc, char **argv)
834 ufds[2].events = POLLIN; 825 ufds[2].events = POLLIN;
835 826
836#if BOOTCHART 827#if BOOTCHART
837 if (bootchart_init() < 0) 828 bootchart_count = bootchart_init();
829 if (bootchart_count < 0) {
838 ERROR("bootcharting init failure\n"); 830 ERROR("bootcharting init failure\n");
839 else { 831 } else if (bootchart_count > 0) {
840 NOTICE("bootcharting started\n"); 832 NOTICE("bootcharting started (period=%d ms)\n", bootchart_count*BOOTCHART_POLLING_MS);
841 bootchart_count = BOOTCHART_MAX_COUNT; 833 } else {
834 NOTICE("bootcharting ignored\n");
842 } 835 }
843#endif 836#endif
844 837
diff --git a/init/keywords.h b/init/keywords.h
index f09bad242..058996e3b 100644
--- a/init/keywords.h
+++ b/init/keywords.h
@@ -19,6 +19,7 @@ int do_start(int nargs, char **args);
19int do_stop(int nargs, char **args); 19int do_stop(int nargs, char **args);
20int do_trigger(int nargs, char **args); 20int do_trigger(int nargs, char **args);
21int do_symlink(int nargs, char **args); 21int do_symlink(int nargs, char **args);
22int do_sysclktz(int nargs, char **args);
22int do_write(int nargs, char **args); 23int do_write(int nargs, char **args);
23int do_chown(int nargs, char **args); 24int do_chown(int nargs, char **args);
24int do_chmod(int nargs, char **args); 25int do_chmod(int nargs, char **args);
@@ -60,6 +61,7 @@ enum {
60 KEYWORD(stop, COMMAND, 1, do_stop) 61 KEYWORD(stop, COMMAND, 1, do_stop)
61 KEYWORD(trigger, COMMAND, 1, do_trigger) 62 KEYWORD(trigger, COMMAND, 1, do_trigger)
62 KEYWORD(symlink, COMMAND, 1, do_symlink) 63 KEYWORD(symlink, COMMAND, 1, do_symlink)
64 KEYWORD(sysclktz, COMMAND, 1, do_sysclktz)
63 KEYWORD(user, OPTION, 0, 0) 65 KEYWORD(user, OPTION, 0, 0)
64 KEYWORD(write, COMMAND, 2, do_write) 66 KEYWORD(write, COMMAND, 2, do_write)
65 KEYWORD(chown, COMMAND, 2, do_chown) 67 KEYWORD(chown, COMMAND, 2, do_chown)
diff --git a/init/parser.c b/init/parser.c
index 95bf01791..a51691be2 100644
--- a/init/parser.c
+++ b/init/parser.c
@@ -183,6 +183,7 @@ int lookup_keyword(const char *s)
183 if (!strcmp(s, "tart")) return K_start; 183 if (!strcmp(s, "tart")) return K_start;
184 if (!strcmp(s, "top")) return K_stop; 184 if (!strcmp(s, "top")) return K_stop;
185 if (!strcmp(s, "ymlink")) return K_symlink; 185 if (!strcmp(s, "ymlink")) return K_symlink;
186 if (!strcmp(s, "ysclktz")) return K_sysclktz;
186 break; 187 break;
187 case 't': 188 case 't':
188 if (!strcmp(s, "rigger")) return K_trigger; 189 if (!strcmp(s, "rigger")) return K_trigger;
diff --git a/init/property_service.c b/init/property_service.c
index 0bc403f63..7a6416b5e 100644
--- a/init/property_service.c
+++ b/init/property_service.c
@@ -343,7 +343,7 @@ void handle_property_set_fd(int fd)
343 socklen_t addr_size = sizeof(addr); 343 socklen_t addr_size = sizeof(addr);
344 socklen_t cr_size = sizeof(cr); 344 socklen_t cr_size = sizeof(cr);
345 345
346 if ((s = accept(fd, &addr, &addr_size)) < 0) { 346 if ((s = accept(fd, (struct sockaddr *) &addr, &addr_size)) < 0) {
347 return; 347 return;
348 } 348 }
349 349
diff --git a/init/readme.txt b/init/readme.txt
index 360a1b709..665090bad 100644
--- a/init/readme.txt
+++ b/init/readme.txt
@@ -194,6 +194,9 @@ stop <service>
194symlink <target> <path> 194symlink <target> <path>
195 Create a symbolic link at <path> with the value <target> 195 Create a symbolic link at <path> with the value <target>
196 196
197sysclktz <mins_west_of_gmt>
198 Set the system clock base (0 if system clock ticks in GMT)
199
197trigger <event> 200trigger <event>
198 Trigger an event. Used to queue an action from another 201 Trigger an event. Used to queue an action from another
199 action. 202 action.
diff --git a/libcutils/Android.mk b/libcutils/Android.mk
index 3d0c12b1d..a43f7e3e4 100644
--- a/libcutils/Android.mk
+++ b/libcutils/Android.mk
@@ -60,6 +60,7 @@ else
60 selector.c \ 60 selector.c \
61 fdevent.c \ 61 fdevent.c \
62 tztime.c \ 62 tztime.c \
63 tzstrftime.c \
63 adb_networking.c \ 64 adb_networking.c \
64 zygote.c 65 zygote.c
65endif 66endif
@@ -91,8 +92,14 @@ else #!sim
91# ======================================================== 92# ========================================================
92include $(CLEAR_VARS) 93include $(CLEAR_VARS)
93LOCAL_MODULE := libcutils 94LOCAL_MODULE := libcutils
94LOCAL_SRC_FILES := $(commonSources) memset32.S atomic-android-arm.S mq.c \ 95LOCAL_SRC_FILES := $(commonSources) ashmem-dev.c mq.c
95 ashmem-dev.c 96
97ifeq ($(TARGET_ARCH),arm)
98LOCAL_SRC_FILES += memset32.S atomic-android-arm.S
99else # !arm
100LOCAL_SRC_FILES += memory.c
101endif # !arm
102
96LOCAL_C_INCLUDES := $(KERNEL_HEADERS) 103LOCAL_C_INCLUDES := $(KERNEL_HEADERS)
97LOCAL_STATIC_LIBRARIES := liblog 104LOCAL_STATIC_LIBRARIES := liblog
98include $(BUILD_STATIC_LIBRARY) 105include $(BUILD_STATIC_LIBRARY)
diff --git a/libcutils/atomic-android-arm.S b/libcutils/atomic-android-arm.S
index 2a4c34f06..c56ec5d0e 100644
--- a/libcutils/atomic-android-arm.S
+++ b/libcutils/atomic-android-arm.S
@@ -14,6 +14,8 @@
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 16
17#include <machine/cpu-features.h>
18
17/* 19/*
18 * NOTE: these atomic operations are SMP safe on all architectures, 20 * NOTE: these atomic operations are SMP safe on all architectures,
19 * except swap(), see below. 21 * except swap(), see below.
@@ -59,8 +61,14 @@ android_atomic_write:
591: @ android_atomic_write 611: @ android_atomic_write
60 ldr r0, [r2] 62 ldr r0, [r2]
61 mov r3, #kernel_atomic_base 63 mov r3, #kernel_atomic_base
64#ifdef __ARM_HAVE_PC_INTERWORK
62 add lr, pc, #4 65 add lr, pc, #4
63 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base) 66 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
67#else
68 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base)
69 mov lr, pc
70 bx r3
71#endif
64 bcc 1b 72 bcc 1b
65 ldmia sp!, {r4, lr} 73 ldmia sp!, {r4, lr}
66 bx lr 74 bx lr
@@ -78,9 +86,16 @@ android_atomic_inc:
781: @ android_atomic_inc 861: @ android_atomic_inc
79 ldr r0, [r2] 87 ldr r0, [r2]
80 mov r3, #kernel_atomic_base 88 mov r3, #kernel_atomic_base
89#ifdef __ARM_HAVE_PC_INTERWORK
81 add lr, pc, #4 90 add lr, pc, #4
82 add r1, r0, #1 91 add r1, r0, #1
83 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base) 92 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
93#else
94 add r1, r0, #1
95 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base)
96 mov lr, pc
97 bx r3
98#endif
84 bcc 1b 99 bcc 1b
85 sub r0, r1, #1 100 sub r0, r1, #1
86 ldmia sp!, {r4, lr} 101 ldmia sp!, {r4, lr}
@@ -99,9 +114,16 @@ android_atomic_dec:
991: @ android_atomic_dec 1141: @ android_atomic_dec
100 ldr r0, [r2] 115 ldr r0, [r2]
101 mov r3, #kernel_atomic_base 116 mov r3, #kernel_atomic_base
117#ifdef __ARM_HAVE_PC_INTERWORK
102 add lr, pc, #4 118 add lr, pc, #4
103 sub r1, r0, #1 119 sub r1, r0, #1
104 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base) 120 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
121#else
122 sub r1, r0, #1
123 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base)
124 mov lr, pc
125 bx r3
126#endif
105 bcc 1b 127 bcc 1b
106 add r0, r1, #1 128 add r0, r1, #1
107 ldmia sp!, {r4, lr} 129 ldmia sp!, {r4, lr}
@@ -121,9 +143,16 @@ android_atomic_add:
1211: @ android_atomic_add 1431: @ android_atomic_add
122 ldr r0, [r2] 144 ldr r0, [r2]
123 mov r3, #kernel_atomic_base 145 mov r3, #kernel_atomic_base
146#ifdef __ARM_HAVE_PC_INTERWORK
124 add lr, pc, #4 147 add lr, pc, #4
125 add r1, r0, r4 148 add r1, r0, r4
126 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base) 149 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
150#else
151 add r1, r0, r4
152 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base)
153 mov lr, pc
154 bx r3
155#endif
127 bcc 1b 156 bcc 1b
128 sub r0, r1, r4 157 sub r0, r1, r4
129 ldmia sp!, {r4, lr} 158 ldmia sp!, {r4, lr}
@@ -144,10 +173,18 @@ android_atomic_and:
1441: @ android_atomic_and 1731: @ android_atomic_and
145 ldr r0, [r2] /* r0 = address[0] */ 174 ldr r0, [r2] /* r0 = address[0] */
146 mov r3, #kernel_atomic_base 175 mov r3, #kernel_atomic_base
176#ifdef __ARM_HAVE_PC_INTERWORK
147 add lr, pc, #8 177 add lr, pc, #8
148 mov r5, r0 /* r5 = save address[0] */ 178 mov r5, r0 /* r5 = save address[0] */
149 and r1, r0, r4 /* r1 = new value */ 179 and r1, r0, r4 /* r1 = new value */
150 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base) /* call cmpxchg() */ 180 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base) /* call cmpxchg() */
181#else
182 mov r5, r0 /* r5 = save address[0] */
183 and r1, r0, r4 /* r1 = new value */
184 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base) /* call cmpxchg() */
185 mov lr, pc
186 bx r3
187#endif
151 bcc 1b 188 bcc 1b
152 mov r0, r5 189 mov r0, r5
153 ldmia sp!, {r4, r5, lr} 190 ldmia sp!, {r4, r5, lr}
@@ -167,10 +204,18 @@ android_atomic_or:
1671: @ android_atomic_or 2041: @ android_atomic_or
168 ldr r0, [r2] /* r0 = address[0] */ 205 ldr r0, [r2] /* r0 = address[0] */
169 mov r3, #kernel_atomic_base 206 mov r3, #kernel_atomic_base
207#ifdef __ARM_HAVE_PC_INTERWORK
170 add lr, pc, #8 208 add lr, pc, #8
171 mov r5, r0 /* r5 = save address[0] */ 209 mov r5, r0 /* r5 = save address[0] */
172 orr r1, r0, r4 /* r1 = new value */ 210 orr r1, r0, r4 /* r1 = new value */
173 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base) /* call cmpxchg() */ 211 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base) /* call cmpxchg() */
212#else
213 mov r5, r0 /* r5 = save address[0] */
214 orr r1, r0, r4 /* r1 = new value */
215 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base) /* call cmpxchg() */
216 mov lr, pc
217 bx r3
218#endif
174 bcc 1b 219 bcc 1b
175 mov r0, r5 220 mov r0, r5
176 ldmia sp!, {r4, r5, lr} 221 ldmia sp!, {r4, r5, lr}
@@ -202,9 +247,16 @@ android_atomic_cmpxchg:
202 mov r4, r0 /* r4 = save oldvalue */ 247 mov r4, r0 /* r4 = save oldvalue */
2031: @ android_atomic_cmpxchg 2481: @ android_atomic_cmpxchg
204 mov r3, #kernel_atomic_base 249 mov r3, #kernel_atomic_base
250#ifdef __ARM_HAVE_PC_INTERWORK
205 add lr, pc, #4 251 add lr, pc, #4
206 mov r0, r4 /* r0 = oldvalue */ 252 mov r0, r4 /* r0 = oldvalue */
207 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base) 253 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
254#else
255 mov r0, r4 /* r0 = oldvalue */
256 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base)
257 mov lr, pc
258 bx r3
259#endif
208 bcs 2f /* swap was made. we're good, return. */ 260 bcs 2f /* swap was made. we're good, return. */
209 ldr r3, [r2] /* swap not made, see if it's because *ptr!=oldvalue */ 261 ldr r3, [r2] /* swap not made, see if it's because *ptr!=oldvalue */
210 cmp r3, r4 262 cmp r3, r4
diff --git a/libcutils/tzstrftime.c b/libcutils/tzstrftime.c
new file mode 100644
index 000000000..29c50154a
--- /dev/null
+++ b/libcutils/tzstrftime.c
@@ -0,0 +1,834 @@
1#ifndef lint
2#ifndef NOID
3static char elsieid[] = "@(#)strftime.c 8.1";
4/*
5** Based on the UCB version with the ID appearing below.
6** This is ANSIish only when "multibyte character == plain character".
7*/
8#endif /* !defined NOID */
9#endif /* !defined lint */
10
11#include <time.h>
12#include <tzfile.h>
13#include <limits.h>
14#include <cutils/tztime.h>
15
16/*
17** Copyright (c) 1989 The Regents of the University of California.
18** All rights reserved.
19**
20** Redistribution and use in source and binary forms are permitted
21** provided that the above copyright notice and this paragraph are
22** duplicated in all such forms and that any documentation,
23** advertising materials, and other materials related to such
24** distribution and use acknowledge that the software was developed
25** by the University of California, Berkeley. The name of the
26** University may not be used to endorse or promote products derived
27** from this software without specific prior written permission.
28** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
29** IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
30** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
31*/
32
33#ifndef LIBC_SCCS
34#ifndef lint
35static const char sccsid[] = "@(#)strftime.c 5.4 (Berkeley) 3/14/89";
36#endif /* !defined lint */
37#endif /* !defined LIBC_SCCS */
38
39#include <ctype.h>
40
41#define P(x) x
42
43static char * _add P((const char *, char *, const char *, int));
44static char * _conv P((int, const char *, char *, const char *));
45static char * _fmt P((const char *, const struct tm *, char *, const char *,
46 int *, const struct strftime_locale *Locale));
47static char * _yconv P((int, int, int, int, char *, const char *, int));
48static char * getformat P((int, char *, char *, char *, char *));
49
50extern char * tzname[];
51
52
53
54
55
56/* from private.h */
57
58#ifndef TYPE_BIT
59#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
60#endif /* !defined TYPE_BIT */
61
62#ifndef TYPE_SIGNED
63#define TYPE_SIGNED(type) (((type) -1) < 0)
64#endif /* !defined TYPE_SIGNED */
65
66#ifndef INT_STRLEN_MAXIMUM
67/*
68 * ** 302 / 1000 is log10(2.0) rounded up.
69 * ** Subtract one for the sign bit if the type is signed;
70 * ** add one for integer division truncation;
71 * ** add one more for a minus sign if the type is signed.
72 * */
73#define INT_STRLEN_MAXIMUM(type) \
74 ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + \
75 1 + TYPE_SIGNED(type))
76#endif /* !defined INT_STRLEN_MAXIMUM */
77
78/* end of part from private.h */
79
80
81
82
83#ifndef YEAR_2000_NAME
84#define YEAR_2000_NAME "CHECK_STRFTIME_FORMATS_FOR_TWO_DIGIT_YEARS"
85#endif /* !defined YEAR_2000_NAME */
86
87#define IN_NONE 0
88#define IN_SOME 1
89#define IN_THIS 2
90#define IN_ALL 3
91
92#define FORCE_LOWER_CASE 0x100
93
94size_t
95strftime_tz(s, maxsize, format, t, Locale)
96char * const s;
97const size_t maxsize;
98const char * const format;
99const struct tm * const t;
100const struct strftime_locale *Locale;
101{
102 char * p;
103 int warn;
104
105 warn = IN_NONE;
106 p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn, Locale);
107#if 0
108 if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) {
109 (void) fprintf(stderr, "\n");
110 if (format == NULL)
111 (void) fprintf(stderr, "NULL strftime format ");
112 else (void) fprintf(stderr, "strftime format \"%s\" ",
113 format);
114 (void) fprintf(stderr, "yields only two digits of years in ");
115 if (warn == IN_SOME)
116 (void) fprintf(stderr, "some locales");
117 else if (warn == IN_THIS)
118 (void) fprintf(stderr, "the current locale");
119 else (void) fprintf(stderr, "all locales");
120 (void) fprintf(stderr, "\n");
121 }
122#endif /* !defined NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU */
123 if (p == s + maxsize)
124 return 0;
125 *p = '\0';
126 return p - s;
127}
128
129static char *getformat(int modifier, char *normal, char *underscore,
130 char *dash, char *zero) {
131 switch (modifier) {
132 case '_':
133 return underscore;
134
135 case '-':
136 return dash;
137
138 case '0':
139 return zero;
140 }
141
142 return normal;
143}
144
145static char *
146_fmt(format, t, pt, ptlim, warnp, Locale)
147const char * format;
148const struct tm * const t;
149char * pt;
150const char * const ptlim;
151int * warnp;
152const struct strftime_locale *Locale;
153{
154 for ( ; *format; ++format) {
155 if (*format == '%') {
156 int modifier = 0;
157label:
158 switch (*++format) {
159 case '\0':
160 --format;
161 break;
162 case 'A':
163 pt = _add((t->tm_wday < 0 ||
164 t->tm_wday >= DAYSPERWEEK) ?
165 "?" : Locale->weekday[t->tm_wday],
166 pt, ptlim, modifier);
167 continue;
168 case 'a':
169 pt = _add((t->tm_wday < 0 ||
170 t->tm_wday >= DAYSPERWEEK) ?
171 "?" : Locale->wday[t->tm_wday],
172 pt, ptlim, modifier);
173 continue;
174 case 'B':
175 pt = _add((t->tm_mon < 0 ||
176 t->tm_mon >= MONSPERYEAR) ?
177 "?" : Locale->month[t->tm_mon],
178 pt, ptlim, modifier);
179 continue;
180 case 'b':
181 case 'h':
182 pt = _add((t->tm_mon < 0 ||
183 t->tm_mon >= MONSPERYEAR) ?
184 "?" : Locale->mon[t->tm_mon],
185 pt, ptlim, modifier);
186 continue;
187 case 'C':
188 /*
189 ** %C used to do a...
190 ** _fmt("%a %b %e %X %Y", t);
191 ** ...whereas now POSIX 1003.2 calls for
192 ** something completely different.
193 ** (ado, 1993-05-24)
194 */
195 pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 0,
196 pt, ptlim, modifier);
197 continue;
198 case 'c':
199 {
200 int warn2 = IN_SOME;
201
202 pt = _fmt(Locale->c_fmt, t, pt, ptlim, warnp, Locale);
203 if (warn2 == IN_ALL)
204 warn2 = IN_THIS;
205 if (warn2 > *warnp)
206 *warnp = warn2;
207 }
208 continue;
209 case 'D':
210 pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp, Locale);
211 continue;
212 case 'd':
213 pt = _conv(t->tm_mday,
214 getformat(modifier, "%02d",
215 "%2d", "%d", "%02d"),
216 pt, ptlim);
217 continue;
218 case 'E':
219 case 'O':
220 /*
221 ** C99 locale modifiers.
222 ** The sequences
223 ** %Ec %EC %Ex %EX %Ey %EY
224 ** %Od %oe %OH %OI %Om %OM
225 ** %OS %Ou %OU %OV %Ow %OW %Oy
226 ** are supposed to provide alternate
227 ** representations.
228 */
229 goto label;
230 case '_':
231 case '-':
232 case '0':
233 case '^':
234 case '#':
235 modifier = *format;
236 goto label;
237 case 'e':
238 pt = _conv(t->tm_mday,
239 getformat(modifier, "%2d",
240 "%2d", "%d", "%02d"),
241 pt, ptlim);
242 continue;
243 case 'F':
244 pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp, Locale);
245 continue;
246 case 'H':
247 pt = _conv(t->tm_hour,
248 getformat(modifier, "%02d",
249 "%2d", "%d", "%02d"),
250 pt, ptlim);
251 continue;
252 case 'I':
253 pt = _conv((t->tm_hour % 12) ?
254 (t->tm_hour % 12) : 12,
255 getformat(modifier, "%02d",
256 "%2d", "%d", "%02d"),
257 pt, ptlim);
258 continue;
259 case 'j':
260 pt = _conv(t->tm_yday + 1,
261 getformat(modifier, "%03d", "%3d", "%d", "%03d"),
262 pt, ptlim);
263 continue;
264 case 'k':
265 /*
266 ** This used to be...
267 ** _conv(t->tm_hour % 12 ?
268 ** t->tm_hour % 12 : 12, 2, ' ');
269 ** ...and has been changed to the below to
270 ** match SunOS 4.1.1 and Arnold Robbins'
271 ** strftime version 3.0. That is, "%k" and
272 ** "%l" have been swapped.
273 ** (ado, 1993-05-24)
274 */
275 pt = _conv(t->tm_hour,
276 getformat(modifier, "%2d",
277 "%2d", "%d", "%02d"),
278 pt, ptlim);
279 continue;
280#ifdef KITCHEN_SINK
281 case 'K':
282 /*
283 ** After all this time, still unclaimed!
284 */
285 pt = _add("kitchen sink", pt, ptlim, modifier);
286 continue;
287#endif /* defined KITCHEN_SINK */
288 case 'l':
289 /*
290 ** This used to be...
291 ** _conv(t->tm_hour, 2, ' ');
292 ** ...and has been changed to the below to
293 ** match SunOS 4.1.1 and Arnold Robbin's
294 ** strftime version 3.0. That is, "%k" and
295 ** "%l" have been swapped.
296 ** (ado, 1993-05-24)
297 */
298 pt = _conv((t->tm_hour % 12) ?
299 (t->tm_hour % 12) : 12,
300 getformat(modifier, "%2d",
301 "%2d", "%d", "%02d"),
302 pt, ptlim);
303 continue;
304 case 'M':
305 pt = _conv(t->tm_min,
306 getformat(modifier, "%02d",
307 "%2d", "%d", "%02d"),
308 pt, ptlim);
309 continue;
310 case 'm':
311 pt = _conv(t->tm_mon + 1,
312 getformat(modifier, "%02d",
313 "%2d", "%d", "%02d"),
314 pt, ptlim);
315 continue;
316 case 'n':
317 pt = _add("\n", pt, ptlim, modifier);
318 continue;
319 case 'p':
320 pt = _add((t->tm_hour >= (HOURSPERDAY / 2)) ?
321 Locale->pm :
322 Locale->am,
323 pt, ptlim, modifier);
324 continue;
325 case 'P':
326 pt = _add((t->tm_hour >= (HOURSPERDAY / 2)) ?
327 Locale->pm :
328 Locale->am,
329 pt, ptlim, FORCE_LOWER_CASE);
330 continue;
331 case 'R':
332 pt = _fmt("%H:%M", t, pt, ptlim, warnp, Locale);
333 continue;
334 case 'r':
335 pt = _fmt("%I:%M:%S %p", t, pt, ptlim, warnp, Locale);
336 continue;
337 case 'S':
338 pt = _conv(t->tm_sec,
339 getformat(modifier, "%02d",
340 "%2d", "%d", "%02d"),
341 pt, ptlim);
342 continue;
343 case 's':
344 {
345 struct tm tm;
346 char buf[INT_STRLEN_MAXIMUM(
347 time_t) + 1];
348 time_t mkt;
349
350 tm = *t;
351 mkt = mktime(&tm);
352 if (TYPE_SIGNED(time_t))
353 (void) sprintf(buf, "%ld",
354 (long) mkt);
355 else (void) sprintf(buf, "%lu",
356 (unsigned long) mkt);
357 pt = _add(buf, pt, ptlim, modifier);
358 }
359 continue;
360 case 'T':
361 pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp, Locale);
362 continue;
363 case 't':
364 pt = _add("\t", pt, ptlim, modifier);
365 continue;
366 case 'U':
367 pt = _conv((t->tm_yday + DAYSPERWEEK -
368 t->tm_wday) / DAYSPERWEEK,
369 getformat(modifier, "%02d",
370 "%2d", "%d", "%02d"),
371 pt, ptlim);
372 continue;
373 case 'u':
374 /*
375 ** From Arnold Robbins' strftime version 3.0:
376 ** "ISO 8601: Weekday as a decimal number
377 ** [1 (Monday) - 7]"
378 ** (ado, 1993-05-24)
379 */
380 pt = _conv((t->tm_wday == 0) ?
381 DAYSPERWEEK : t->tm_wday, "%d", pt, ptlim);
382 continue;
383 case 'V': /* ISO 8601 week number */
384 case 'G': /* ISO 8601 year (four digits) */
385 case 'g': /* ISO 8601 year (two digits) */
386/*
387** From Arnold Robbins' strftime version 3.0: "the week number of the
388** year (the first Monday as the first day of week 1) as a decimal number
389** (01-53)."
390** (ado, 1993-05-24)
391**
392** From "http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html" by Markus Kuhn:
393** "Week 01 of a year is per definition the first week which has the
394** Thursday in this year, which is equivalent to the week which contains
395** the fourth day of January. In other words, the first week of a new year
396** is the week which has the majority of its days in the new year. Week 01
397** might also contain days from the previous year and the week before week
398** 01 of a year is the last week (52 or 53) of the previous year even if
399** it contains days from the new year. A week starts with Monday (day 1)
400** and ends with Sunday (day 7). For example, the first week of the year
401** 1997 lasts from 1996-12-30 to 1997-01-05..."
402** (ado, 1996-01-02)
403*/
404 {
405 int year;
406 int base;
407 int yday;
408 int wday;
409 int w;
410
411 year = t->tm_year;
412 base = TM_YEAR_BASE;
413 yday = t->tm_yday;
414 wday = t->tm_wday;
415 for ( ; ; ) {
416 int len;
417 int bot;
418 int top;
419
420 len = isleap_sum(year, base) ?
421 DAYSPERLYEAR :
422 DAYSPERNYEAR;
423 /*
424 ** What yday (-3 ... 3) does
425 ** the ISO year begin on?
426 */
427 bot = ((yday + 11 - wday) %
428 DAYSPERWEEK) - 3;
429 /*
430 ** What yday does the NEXT
431 ** ISO year begin on?
432 */
433 top = bot -
434 (len % DAYSPERWEEK);
435 if (top < -3)
436 top += DAYSPERWEEK;
437 top += len;
438 if (yday >= top) {
439 ++base;
440 w = 1;
441 break;
442 }
443 if (yday >= bot) {
444 w = 1 + ((yday - bot) /
445 DAYSPERWEEK);
446 break;
447 }
448 --base;
449 yday += isleap_sum(year, base) ?
450 DAYSPERLYEAR :
451 DAYSPERNYEAR;
452 }
453#ifdef XPG4_1994_04_09
454 if ((w == 52 &&
455 t->tm_mon == TM_JANUARY) ||
456 (w == 1 &&
457 t->tm_mon == TM_DECEMBER))
458 w = 53;
459#endif /* defined XPG4_1994_04_09 */
460 if (*format == 'V')
461 pt = _conv(w,
462 getformat(modifier,
463 "%02d",
464 "%2d",
465 "%d",
466 "%02d"),
467 pt, ptlim);
468 else if (*format == 'g') {
469 *warnp = IN_ALL;
470 pt = _yconv(year, base, 0, 1,
471 pt, ptlim, modifier);
472 } else pt = _yconv(year, base, 1, 1,
473 pt, ptlim, modifier);
474 }
475 continue;
476 case 'v':
477 /*
478 ** From Arnold Robbins' strftime version 3.0:
479 ** "date as dd-bbb-YYYY"
480 ** (ado, 1993-05-24)
481 */
482 pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp, Locale);
483 continue;
484 case 'W':
485 pt = _conv((t->tm_yday + DAYSPERWEEK -
486 (t->tm_wday ?
487 (t->tm_wday - 1) :
488 (DAYSPERWEEK - 1))) / DAYSPERWEEK,
489 getformat(modifier, "%02d",
490 "%2d", "%d", "%02d"),
491 pt, ptlim);
492 continue;
493 case 'w':
494 pt = _conv(t->tm_wday, "%d", pt, ptlim);
495 continue;
496 case 'X':
497 pt = _fmt(Locale->X_fmt, t, pt, ptlim, warnp, Locale);
498 continue;
499 case 'x':
500 {
501 int warn2 = IN_SOME;
502
503 pt = _fmt(Locale->x_fmt, t, pt, ptlim, &warn2, Locale);
504 if (warn2 == IN_ALL)
505 warn2 = IN_THIS;
506 if (warn2 > *warnp)
507 *warnp = warn2;
508 }
509 continue;
510 case 'y':
511 *warnp = IN_ALL;
512 pt = _yconv(t->tm_year, TM_YEAR_BASE, 0, 1,
513 pt, ptlim, modifier);
514 continue;
515 case 'Y':
516 pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 1,
517 pt, ptlim, modifier);
518 continue;
519 case 'Z':
520#ifdef TM_ZONE
521 if (t->TM_ZONE != NULL)
522 pt = _add(t->TM_ZONE, pt, ptlim,
523 modifier);
524 else
525#endif /* defined TM_ZONE */
526 if (t->tm_isdst >= 0)
527 pt = _add(tzname[t->tm_isdst != 0],
528 pt, ptlim, modifier);
529 /*
530 ** C99 says that %Z must be replaced by the
531 ** empty string if the time zone is not
532 ** determinable.
533 */
534 continue;
535 case 'z':
536 {
537 int diff;
538 char const * sign;
539
540 if (t->tm_isdst < 0)
541 continue;
542#ifdef TM_GMTOFF
543 diff = t->TM_GMTOFF;
544#else /* !defined TM_GMTOFF */
545 /*
546 ** C99 says that the UTC offset must
547 ** be computed by looking only at
548 ** tm_isdst. This requirement is
549 ** incorrect, since it means the code
550 ** must rely on magic (in this case
551 ** altzone and timezone), and the
552 ** magic might not have the correct
553 ** offset. Doing things correctly is
554 ** tricky and requires disobeying C99;
555 ** see GNU C strftime for details.
556 ** For now, punt and conform to the
557 ** standard, even though it's incorrect.
558 **
559 ** C99 says that %z must be replaced by the
560 ** empty string if the time zone is not
561 ** determinable, so output nothing if the
562 ** appropriate variables are not available.
563 */
564 if (t->tm_isdst == 0)
565#ifdef USG_COMPAT
566 diff = -timezone;
567#else /* !defined USG_COMPAT */
568 continue;
569#endif /* !defined USG_COMPAT */
570 else
571#ifdef ALTZONE
572 diff = -altzone;
573#else /* !defined ALTZONE */
574 continue;
575#endif /* !defined ALTZONE */
576#endif /* !defined TM_GMTOFF */
577 if (diff < 0) {
578 sign = "-";
579 diff = -diff;
580 } else sign = "+";
581 pt = _add(sign, pt, ptlim, modifier);
582 diff /= SECSPERMIN;
583 diff = (diff / MINSPERHOUR) * 100 +
584 (diff % MINSPERHOUR);
585 pt = _conv(diff,
586 getformat(modifier, "%04d",
587 "%4d", "%d", "%04d"),
588 pt, ptlim);
589 }
590 continue;
591 case '+':
592 pt = _fmt(Locale->date_fmt, t, pt, ptlim,
593 warnp, Locale);
594 continue;
595 case '%':
596 /*
597 ** X311J/88-090 (4.12.3.5): if conversion char is
598 ** undefined, behavior is undefined. Print out the
599 ** character itself as printf(3) also does.
600 */
601 default:
602 break;
603 }
604 }
605 if (pt == ptlim)
606 break;
607 *pt++ = *format;
608 }
609 return pt;
610}
611
612static char *
613_conv(n, format, pt, ptlim)
614const int n;
615const char * const format;
616char * const pt;
617const char * const ptlim;
618{
619 char buf[INT_STRLEN_MAXIMUM(int) + 1];
620
621 (void) sprintf(buf, format, n);
622 return _add(buf, pt, ptlim, 0);
623}
624
625static char *
626_add(str, pt, ptlim, modifier)
627const char * str;
628char * pt;
629const char * const ptlim;
630int modifier;
631{
632 int c;
633
634 switch (modifier) {
635 case FORCE_LOWER_CASE:
636 while (pt < ptlim && (*pt = tolower(*str++)) != '\0') {
637 ++pt;
638 }
639 break;
640
641 case '^':
642 while (pt < ptlim && (*pt = toupper(*str++)) != '\0') {
643 ++pt;
644 }
645 break;
646
647 case '#':
648 while (pt < ptlim && (c = *str++) != '\0') {
649 if (isupper(c)) {
650 c = tolower(c);
651 } else if (islower(c)) {
652 c = toupper(c);
653 }
654 *pt = c;
655 ++pt;
656 }
657
658 break;
659
660 default:
661 while (pt < ptlim && (*pt = *str++) != '\0') {
662 ++pt;
663 }
664 }
665
666 return pt;
667}
668
669/*
670** POSIX and the C Standard are unclear or inconsistent about
671** what %C and %y do if the year is negative or exceeds 9999.
672** Use the convention that %C concatenated with %y yields the
673** same output as %Y, and that %Y contains at least 4 bytes,
674** with more only if necessary.
675*/
676
677static char *
678_yconv(a, b, convert_top, convert_yy, pt, ptlim, modifier)
679const int a;
680const int b;
681const int convert_top;
682const int convert_yy;
683char * pt;
684const char * const ptlim;
685int modifier;
686{
687 register int lead;
688 register int trail;
689
690#define DIVISOR 100
691 trail = a % DIVISOR + b % DIVISOR;
692 lead = a / DIVISOR + b / DIVISOR + trail / DIVISOR;
693 trail %= DIVISOR;
694 if (trail < 0 && lead > 0) {
695 trail += DIVISOR;
696 --lead;
697 } else if (lead < 0 && trail > 0) {
698 trail -= DIVISOR;
699 ++lead;
700 }
701 if (convert_top) {
702 if (lead == 0 && trail < 0)
703 pt = _add("-0", pt, ptlim, modifier);
704 else pt = _conv(lead, getformat(modifier, "%02d",
705 "%2d", "%d", "%02d"),
706 pt, ptlim);
707 }
708 if (convert_yy)
709 pt = _conv(((trail < 0) ? -trail : trail),
710 getformat(modifier, "%02d", "%2d", "%d", "%02d"),
711 pt, ptlim);
712 return pt;
713}
714
715#ifdef LOCALE_HOME
716static struct lc_time_T *
717_loc P((void))
718{
719 static const char locale_home[] = LOCALE_HOME;
720 static const char lc_time[] = "LC_TIME";
721 static char * locale_buf;
722
723 int fd;
724 int oldsun; /* "...ain't got nothin' to do..." */
725 char * lbuf;
726 char * name;
727 char * p;
728 const char ** ap;
729 const char * plim;
730 char filename[FILENAME_MAX];
731 struct stat st;
732 size_t namesize;
733 size_t bufsize;
734
735 /*
736 ** Use localebuf.mon[0] to signal whether locale is already set up.
737 */
738 if (localebuf.mon[0])
739 return &localebuf;
740 name = setlocale(LC_TIME, (char *) NULL);
741 if (name == NULL || *name == '\0')
742 goto no_locale;
743 /*
744 ** If the locale name is the same as our cache, use the cache.
745 */
746 lbuf = locale_buf;
747 if (lbuf != NULL && strcmp(name, lbuf) == 0) {
748 p = lbuf;
749 for (ap = (const char **) &localebuf;
750 ap < (const char **) (&localebuf + 1);
751 ++ap)
752 *ap = p += strlen(p) + 1;
753 return &localebuf;
754 }
755 /*
756 ** Slurp the locale file into the cache.
757 */
758 namesize = strlen(name) + 1;
759 if (sizeof filename <
760 ((sizeof locale_home) + namesize + (sizeof lc_time)))
761 goto no_locale;
762 oldsun = 0;
763 (void) sprintf(filename, "%s/%s/%s", locale_home, name, lc_time);
764 fd = open(filename, O_RDONLY);
765 if (fd < 0) {
766 /*
767 ** Old Sun systems have a different naming and data convention.
768 */
769 oldsun = 1;
770 (void) sprintf(filename, "%s/%s/%s", locale_home,
771 lc_time, name);
772 fd = open(filename, O_RDONLY);
773 if (fd < 0)
774 goto no_locale;
775 }
776 if (fstat(fd, &st) != 0)
777 goto bad_locale;
778 if (st.st_size <= 0)
779 goto bad_locale;
780 bufsize = namesize + st.st_size;
781 locale_buf = NULL;
782 lbuf = (lbuf == NULL) ? malloc(bufsize) : realloc(lbuf, bufsize);
783 if (lbuf == NULL)
784 goto bad_locale;
785 (void) strcpy(lbuf, name);
786 p = lbuf + namesize;
787 plim = p + st.st_size;
788 if (read(fd, p, (size_t) st.st_size) != st.st_size)
789 goto bad_lbuf;
790 if (close(fd) != 0)
791 goto bad_lbuf;
792 /*
793 ** Parse the locale file into localebuf.
794 */
795 if (plim[-1] != '\n')
796 goto bad_lbuf;
797 for (ap = (const char **) &localebuf;
798 ap < (const char **) (&localebuf + 1);
799 ++ap) {
800 if (p == plim)
801 goto bad_lbuf;
802 *ap = p;
803 while (*p != '\n')
804 ++p;
805 *p++ = '\0';
806 }
807 if (oldsun) {
808 /*
809 ** SunOS 4 used an obsolescent format; see localdtconv(3).
810 ** c_fmt had the ``short format for dates and times together''
811 ** (SunOS 4 date, "%a %b %e %T %Z %Y" in the C locale);
812 ** date_fmt had the ``long format for dates''
813 ** (SunOS 4 strftime %C, "%A, %B %e, %Y" in the C locale).
814 ** Discard the latter in favor of the former.
815 */
816 localebuf.date_fmt = localebuf.c_fmt;
817 }
818 /*
819 ** Record the successful parse in the cache.
820 */
821 locale_buf = lbuf;
822
823 return &localebuf;
824
825bad_lbuf:
826 free(lbuf);
827bad_locale:
828 (void) close(fd);
829no_locale:
830 localebuf = C_time_locale;
831 locale_buf = NULL;
832 return &localebuf;
833}
834#endif /* defined LOCALE_HOME */
diff --git a/libnetutils/dhcp_utils.c b/libnetutils/dhcp_utils.c
index 97fe76dd3..ba9893351 100644
--- a/libnetutils/dhcp_utils.c
+++ b/libnetutils/dhcp_utils.c
@@ -181,6 +181,22 @@ int dhcp_stop(const char *interface)
181 return 0; 181 return 0;
182} 182}
183 183
184/**
185 * Release the current DHCP client lease.
186 */
187int dhcp_release_lease(const char *interface)
188{
189 const char *ctrl_prop = "ctl.stop";
190 const char *desired_status = "stopped";
191
192 /* Stop the daemon and wait until it's reported to be stopped */
193 property_set(ctrl_prop, DAEMON_NAME);
194 if (wait_for_property(DAEMON_PROP_NAME, desired_status, 5) < 0) {
195 return -1;
196 }
197 return 0;
198}
199
184char *dhcp_get_errmsg() { 200char *dhcp_get_errmsg() {
185 return errmsg; 201 return errmsg;
186} 202}
diff --git a/libpixelflinger/Android.mk b/libpixelflinger/Android.mk
index a8e5ee4eb..6edc56fec 100644
--- a/libpixelflinger/Android.mk
+++ b/libpixelflinger/Android.mk
@@ -85,3 +85,6 @@ ifeq ($(TARGET_ARCH),arm)
85LOCAL_WHOLE_STATIC_LIBRARIES := libpixelflinger_armv6 85LOCAL_WHOLE_STATIC_LIBRARIES := libpixelflinger_armv6
86endif 86endif
87include $(BUILD_STATIC_LIBRARY) 87include $(BUILD_STATIC_LIBRARY)
88
89
90include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/libpixelflinger/codeflinger/GGLAssembler.cpp b/libpixelflinger/codeflinger/GGLAssembler.cpp
index 90c275e4b..1cd189c9f 100644
--- a/libpixelflinger/codeflinger/GGLAssembler.cpp
+++ b/libpixelflinger/codeflinger/GGLAssembler.cpp
@@ -151,6 +151,7 @@ int GGLAssembler::scanline_core(const needs_t& needs, context_t const* c)
151 // Destination is zero (beware of logic ops) 151 // Destination is zero (beware of logic ops)
152 } 152 }
153 153
154 int fbComponents = 0;
154 const int masking = GGL_READ_NEEDS(MASK_ARGB, needs.n); 155 const int masking = GGL_READ_NEEDS(MASK_ARGB, needs.n);
155 for (int i=0 ; i<4 ; i++) { 156 for (int i=0 ; i<4 ; i++) {
156 const int mask = 1<<i; 157 const int mask = 1<<i;
@@ -176,9 +177,14 @@ int GGLAssembler::scanline_core(const needs_t& needs, context_t const* c)
176 177
177 mBlending |= (info.blend ? mask : 0); 178 mBlending |= (info.blend ? mask : 0);
178 mMasking |= (mCbFormat.c[i].h && info.masked) ? mask : 0; 179 mMasking |= (mCbFormat.c[i].h && info.masked) ? mask : 0;
180 fbComponents |= mCbFormat.c[i].h ? mask : 0;
179 } 181 }
180 182
181 183 mAllMasked = (mMasking == fbComponents);
184 if (mAllMasked) {
185 mDithering = 0;
186 }
187
182 fragment_parts_t parts; 188 fragment_parts_t parts;
183 189
184 // ------------------------------------------------------------------------ 190 // ------------------------------------------------------------------------
@@ -226,8 +232,10 @@ int GGLAssembler::scanline_core(const needs_t& needs, context_t const* c)
226 build_textures(parts, regs); 232 build_textures(parts, regs);
227 } 233 }
228 234
229 if ((blending & (FACTOR_DST|BLEND_DST)) || mMasking || 235 if ((blending & (FACTOR_DST|BLEND_DST)) ||
230 (mLogicOp & LOGIC_OP_DST)) { 236 (mMasking && !mAllMasked) ||
237 (mLogicOp & LOGIC_OP_DST))
238 {
231 // blending / logic_op / masking need the framebuffer 239 // blending / logic_op / masking need the framebuffer
232 mDstPixel.setTo(regs.obtain(), &mCbFormat); 240 mDstPixel.setTo(regs.obtain(), &mCbFormat);
233 241
@@ -284,14 +292,16 @@ int GGLAssembler::scanline_core(const needs_t& needs, context_t const* c)
284 pixel = mDstPixel; 292 pixel = mDstPixel;
285 } 293 }
286 294
287 // logic operation 295 if (!mAllMasked) {
288 build_logic_op(pixel, regs); 296 // logic operation
289 297 build_logic_op(pixel, regs);
290 // masking 298
291 build_masking(pixel, regs); 299 // masking
292 300 build_masking(pixel, regs);
293 comment("store"); 301
294 store(parts.cbPtr, pixel, WRITE_BACK); 302 comment("store");
303 store(parts.cbPtr, pixel, WRITE_BACK);
304 }
295 } 305 }
296 306
297 if (registerFile().status()) 307 if (registerFile().status())
@@ -322,7 +332,9 @@ int GGLAssembler::scanline_core(const needs_t& needs, context_t const* c)
322 build_smooth_shade(parts); 332 build_smooth_shade(parts);
323 build_iterate_z(parts); 333 build_iterate_z(parts);
324 build_iterate_f(parts); 334 build_iterate_f(parts);
325 ADD(AL, 0, parts.cbPtr.reg, parts.cbPtr.reg, imm(parts.cbPtr.size>>3)); 335 if (!mAllMasked) {
336 ADD(AL, 0, parts.cbPtr.reg, parts.cbPtr.reg, imm(parts.cbPtr.size>>3));
337 }
326 SUB(AL, S, parts.count.reg, parts.count.reg, imm(1<<16)); 338 SUB(AL, S, parts.count.reg, parts.count.reg, imm(1<<16));
327 B(PL, "fragment_loop"); 339 B(PL, "fragment_loop");
328 epilog(registerFile().touched()); 340 epilog(registerFile().touched());
@@ -370,16 +382,18 @@ void GGLAssembler::build_scanline_prolog(
370 MOV(AL, 0, parts.count.reg, reg_imm(parts.count.reg, LSL, 16)); 382 MOV(AL, 0, parts.count.reg, reg_imm(parts.count.reg, LSL, 16));
371 } 383 }
372 384
373 // compute dst ptr 385 if (!mAllMasked) {
374 comment("compute color-buffer pointer"); 386 // compute dst ptr
375 const int cb_bits = mCbFormat.size*8; 387 comment("compute color-buffer pointer");
376 int Rs = scratches.obtain(); 388 const int cb_bits = mCbFormat.size*8;
377 parts.cbPtr.setTo(obtainReg(), cb_bits); 389 int Rs = scratches.obtain();
378 CONTEXT_LOAD(Rs, state.buffers.color.stride); 390 parts.cbPtr.setTo(obtainReg(), cb_bits);
379 CONTEXT_LOAD(parts.cbPtr.reg, state.buffers.color.data); 391 CONTEXT_LOAD(Rs, state.buffers.color.stride);
380 SMLABB(AL, Rs, Ry, Rs, Rx); // Rs = Rx + Ry*Rs 392 CONTEXT_LOAD(parts.cbPtr.reg, state.buffers.color.data);
381 base_offset(parts.cbPtr, parts.cbPtr, Rs); 393 SMLABB(AL, Rs, Ry, Rs, Rx); // Rs = Rx + Ry*Rs
382 scratches.recycle(Rs); 394 base_offset(parts.cbPtr, parts.cbPtr, Rs);
395 scratches.recycle(Rs);
396 }
383 397
384 // init fog 398 // init fog
385 const int need_fog = GGL_READ_NEEDS(P_FOG, needs.p); 399 const int need_fog = GGL_READ_NEEDS(P_FOG, needs.p);
@@ -904,8 +918,9 @@ void GGLAssembler::build_and_immediate(int d, int s, uint32_t mask, int bits)
904 918
905void GGLAssembler::build_masking(pixel_t& pixel, Scratch& regs) 919void GGLAssembler::build_masking(pixel_t& pixel, Scratch& regs)
906{ 920{
907 if (!mMasking) 921 if (!mMasking || mAllMasked) {
908 return; 922 return;
923 }
909 924
910 comment("color mask"); 925 comment("color mask");
911 926
@@ -928,7 +943,7 @@ void GGLAssembler::build_masking(pixel_t& pixel, Scratch& regs)
928 943
929 // There is no need to clear the masked components of the source 944 // There is no need to clear the masked components of the source
930 // (unless we applied a logic op), because they're already zeroed 945 // (unless we applied a logic op), because they're already zeroed
931 // by contruction (masked components are not computed) 946 // by construction (masked components are not computed)
932 947
933 if (mLogicOp) { 948 if (mLogicOp) {
934 const needs_t& needs = mBuilderContext.needs; 949 const needs_t& needs = mBuilderContext.needs;
diff --git a/libpixelflinger/codeflinger/GGLAssembler.h b/libpixelflinger/codeflinger/GGLAssembler.h
index ccaf43d3a..d1d29f0b0 100644
--- a/libpixelflinger/codeflinger/GGLAssembler.h
+++ b/libpixelflinger/codeflinger/GGLAssembler.h
@@ -363,6 +363,10 @@ private:
363 const component_t& incoming, 363 const component_t& incoming,
364 const pixel_t& texel, int component, int tmu); 364 const pixel_t& texel, int component, int tmu);
365 365
366 void add( component_t& dest,
367 const component_t& incoming,
368 const pixel_t& texel, int component);
369
366 // load/store stuff 370 // load/store stuff
367 void store(const pointer_t& addr, const pixel_t& src, uint32_t flags=0); 371 void store(const pointer_t& addr, const pixel_t& src, uint32_t flags=0);
368 void load(const pointer_t& addr, const pixel_t& dest, uint32_t flags=0); 372 void load(const pointer_t& addr, const pixel_t& dest, uint32_t flags=0);
@@ -517,6 +521,7 @@ private:
517 component_info_t mInfo[4]; 521 component_info_t mInfo[4];
518 int mBlending; 522 int mBlending;
519 int mMasking; 523 int mMasking;
524 int mAllMasked;
520 int mLogicOp; 525 int mLogicOp;
521 int mAlphaTest; 526 int mAlphaTest;
522 int mAA; 527 int mAA;
diff --git a/libpixelflinger/codeflinger/blending.cpp b/libpixelflinger/codeflinger/blending.cpp
index 6d3b28201..f10217b74 100644
--- a/libpixelflinger/codeflinger/blending.cpp
+++ b/libpixelflinger/codeflinger/blending.cpp
@@ -50,6 +50,12 @@ void GGLAssembler::build_fog(
50 integer_t factor(scratches.obtain(), 16, CORRUPTIBLE); 50 integer_t factor(scratches.obtain(), 16, CORRUPTIBLE);
51 CONTEXT_LOAD(factor.reg, generated_vars.f); 51 CONTEXT_LOAD(factor.reg, generated_vars.f);
52 52
53 // clamp fog factor (TODO: see if there is a way to guarantee
54 // we won't overflow, when setting the iterators)
55 BIC(AL, 0, factor.reg, factor.reg, reg_imm(factor.reg, ASR, 31));
56 CMP(AL, factor.reg, imm( 0x10000 ));
57 MOV(HS, 0, factor.reg, imm( 0x10000 ));
58
53 build_blendFOneMinusF(temp, factor, fragment, fogColor); 59 build_blendFOneMinusF(temp, factor, fragment, fogColor);
54 } 60 }
55} 61}
diff --git a/libpixelflinger/codeflinger/load_store.cpp b/libpixelflinger/codeflinger/load_store.cpp
index 514ce073e..93c582579 100644
--- a/libpixelflinger/codeflinger/load_store.cpp
+++ b/libpixelflinger/codeflinger/load_store.cpp
@@ -168,7 +168,7 @@ void GGLAssembler::expand(integer_t& d, const component_t& s, int dbits)
168void GGLAssembler::expand(component_t& d, const component_t& s, int dbits) 168void GGLAssembler::expand(component_t& d, const component_t& s, int dbits)
169{ 169{
170 integer_t r(d.reg, 32, d.flags); 170 integer_t r(d.reg, 32, d.flags);
171 expand(r, d, dbits); 171 expand(r, s, dbits);
172 d = component_t(r); 172 d = component_t(r);
173} 173}
174 174
diff --git a/libpixelflinger/codeflinger/texturing.cpp b/libpixelflinger/codeflinger/texturing.cpp
index 269b6c003..90e658407 100644
--- a/libpixelflinger/codeflinger/texturing.cpp
+++ b/libpixelflinger/codeflinger/texturing.cpp
@@ -1000,6 +1000,9 @@ void GGLAssembler::build_texture_environment(
1000 case GGL_BLEND: 1000 case GGL_BLEND:
1001 blend(fragment, incoming, texel, component, i); 1001 blend(fragment, incoming, texel, component, i);
1002 break; 1002 break;
1003 case GGL_ADD:
1004 add(fragment, incoming, texel, component);
1005 break;
1003 } 1006 }
1004 } 1007 }
1005 } 1008 }
@@ -1202,6 +1205,46 @@ void GGLAssembler::blend(
1202 build_blendOneMinusFF(dest, factor, incomingNorm, color); 1205 build_blendOneMinusFF(dest, factor, incomingNorm, color);
1203} 1206}
1204 1207
1208void GGLAssembler::add(
1209 component_t& dest,
1210 const component_t& incoming,
1211 const pixel_t& incomingTexel, int component)
1212{
1213 // RGBA:
1214 // Cv = Cf + Ct;
1215 Scratch locals(registerFile());
1216
1217 component_t incomingTemp(incoming);
1218
1219 // use "dest" as a temporary for extracting the texel, unless "dest"
1220 // overlaps "incoming".
1221 integer_t texel(dest.reg, 32, CORRUPTIBLE);
1222 if (dest.reg == incomingTemp.reg)
1223 texel.reg = locals.obtain();
1224 extract(texel, incomingTexel, component);
1225
1226 if (texel.s < incomingTemp.size()) {
1227 expand(texel, texel, incomingTemp.size());
1228 } else if (texel.s > incomingTemp.size()) {
1229 if (incomingTemp.flags & CORRUPTIBLE) {
1230 expand(incomingTemp, incomingTemp, texel.s);
1231 } else {
1232 incomingTemp.reg = locals.obtain();
1233 expand(incomingTemp, incoming, texel.s);
1234 }
1235 }
1236
1237 if (incomingTemp.l) {
1238 ADD(AL, 0, dest.reg, texel.reg,
1239 reg_imm(incomingTemp.reg, LSR, incomingTemp.l));
1240 } else {
1241 ADD(AL, 0, dest.reg, texel.reg, incomingTemp.reg);
1242 }
1243 dest.l = 0;
1244 dest.h = texel.size();
1245 component_sat(dest);
1246}
1247
1205// ---------------------------------------------------------------------------- 1248// ----------------------------------------------------------------------------
1206 1249
1207}; // namespace android 1250}; // namespace android
diff --git a/libpixelflinger/format.cpp b/libpixelflinger/format.cpp
index c77eadaba..cbbd91a0e 100644
--- a/libpixelflinger/format.cpp
+++ b/libpixelflinger/format.cpp
@@ -21,13 +21,13 @@
21namespace android { 21namespace android {
22 22
23static GGLFormat const gPixelFormatInfos[] = 23static GGLFormat const gPixelFormatInfos[] =
24{ 24{ // Alpha Red Green Blue
25 { 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE 25 { 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
26 { 4, 32, {{32,24, 8, 0, 16, 8, 24,16 }}, GGL_RGBA }, // PIXEL_FORMAT_RGBA_8888 26 { 4, 32, {{32,24, 8, 0, 16, 8, 24,16 }}, GGL_RGBA }, // PIXEL_FORMAT_RGBA_8888
27 { 4, 24, {{ 0, 0, 8, 0, 16, 8, 24,16 }}, GGL_RGB }, // PIXEL_FORMAT_RGBX_8888 27 { 4, 24, {{ 0, 0, 8, 0, 16, 8, 24,16 }}, GGL_RGB }, // PIXEL_FORMAT_RGBX_8888
28 { 3, 24, {{ 0, 0, 8, 0, 16, 8, 24,16 }}, GGL_RGB }, // PIXEL_FORMAT_RGB_888 28 { 3, 24, {{ 0, 0, 8, 0, 16, 8, 24,16 }}, GGL_RGB }, // PIXEL_FORMAT_RGB_888
29 { 2, 16, {{ 0, 0, 16,11, 11, 5, 5, 0 }}, GGL_RGB }, // PIXEL_FORMAT_RGB_565 29 { 2, 16, {{ 0, 0, 16,11, 11, 5, 5, 0 }}, GGL_RGB }, // PIXEL_FORMAT_RGB_565
30 { 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE 30 { 4, 32, {{32,24, 24,16, 16, 8, 8, 0 }}, GGL_RGBA }, // PIXEL_FORMAT_BGRA_8888
31 { 2, 16, {{ 1, 0, 16,11, 11, 6, 6, 1 }}, GGL_RGBA }, // PIXEL_FORMAT_RGBA_5551 31 { 2, 16, {{ 1, 0, 16,11, 11, 6, 6, 1 }}, GGL_RGBA }, // PIXEL_FORMAT_RGBA_5551
32 { 2, 16, {{ 4, 0, 16,12, 12, 8, 8, 4 }}, GGL_RGBA }, // PIXEL_FORMAT_RGBA_4444 32 { 2, 16, {{ 4, 0, 16,12, 12, 8, 8, 4 }}, GGL_RGBA }, // PIXEL_FORMAT_RGBA_4444
33 { 1, 8, {{ 8, 0, 0, 0, 0, 0, 0, 0 }}, GGL_ALPHA}, // PIXEL_FORMAT_A8 33 { 1, 8, {{ 8, 0, 0, 0, 0, 0, 0, 0 }}, GGL_ALPHA}, // PIXEL_FORMAT_A8
diff --git a/libpixelflinger/scanline.cpp b/libpixelflinger/scanline.cpp
index d24c98805..75b668d37 100644
--- a/libpixelflinger/scanline.cpp
+++ b/libpixelflinger/scanline.cpp
@@ -55,9 +55,11 @@
55# define ANDROID_ARM_CODEGEN 0 55# define ANDROID_ARM_CODEGEN 0
56#endif 56#endif
57 57
58
59#define DEBUG__CODEGEN_ONLY 0 58#define DEBUG__CODEGEN_ONLY 0
60 59
60
61#define ASSEMBLY_SCRATCH_SIZE 2048
62
61// ---------------------------------------------------------------------------- 63// ----------------------------------------------------------------------------
62namespace android { 64namespace android {
63// ---------------------------------------------------------------------------- 65// ----------------------------------------------------------------------------
@@ -247,7 +249,8 @@ static void pick_scanline(context_t* c)
247 sp<Assembly> assembly = gCodeCache.lookup(key); 249 sp<Assembly> assembly = gCodeCache.lookup(key);
248 if (assembly == 0) { 250 if (assembly == 0) {
249 // create a new assembly region 251 // create a new assembly region
250 sp<ScanlineAssembly> a = new ScanlineAssembly(c->state.needs, 1024); 252 sp<ScanlineAssembly> a = new ScanlineAssembly(c->state.needs,
253 ASSEMBLY_SCRATCH_SIZE);
251 // initialize our assembler 254 // initialize our assembler
252 GGLAssembler assembler( new ARMAssembler(a) ); 255 GGLAssembler assembler( new ARMAssembler(a) );
253 //GGLAssembler assembler( 256 //GGLAssembler assembler(
@@ -676,6 +679,12 @@ void scanline(context_t* c)
676 Cf = ((((1<<st) - factor) * Cf) + Ct*Cc)>>st; 679 Cf = ((((1<<st) - factor) * Cf) + Ct*Cc)>>st;
677 } 680 }
678 break; 681 break;
682 case GGL_ADD:
683 if (st) {
684 rescale(Cf, sf, Ct, st);
685 Cf += Ct;
686 }
687 break;
679 } 688 }
680 } 689 }
681 } 690 }
@@ -1473,7 +1482,7 @@ extern "C" void ggl_test_codegen(uint32_t n, uint32_t p, uint32_t t0, uint32_t t
1473 needs.p = p; 1482 needs.p = p;
1474 needs.t[0] = t0; 1483 needs.t[0] = t0;
1475 needs.t[1] = t1; 1484 needs.t[1] = t1;
1476 sp<ScanlineAssembly> a(new ScanlineAssembly(needs, 1024)); 1485 sp<ScanlineAssembly> a(new ScanlineAssembly(needs, ASSEMBLY_SCRATCH_SIZE));
1477 GGLAssembler assembler( new ARMAssembler(a) ); 1486 GGLAssembler assembler( new ARMAssembler(a) );
1478 int err = assembler.scanline(needs, (context_t*)c); 1487 int err = assembler.scanline(needs, (context_t*)c);
1479 if (err != 0) { 1488 if (err != 0) {
diff --git a/libpixelflinger/tests/Android.mk b/libpixelflinger/tests/Android.mk
new file mode 100644
index 000000000..65711611c
--- /dev/null
+++ b/libpixelflinger/tests/Android.mk
@@ -0,0 +1 @@
include $(all-subdir-makefiles)
diff --git a/libpixelflinger/tests/codegen/Android.mk b/libpixelflinger/tests/codegen/Android.mk
new file mode 100644
index 000000000..1bc421487
--- /dev/null
+++ b/libpixelflinger/tests/codegen/Android.mk
@@ -0,0 +1,15 @@
1LOCAL_PATH:= $(call my-dir)
2include $(CLEAR_VARS)
3
4LOCAL_SRC_FILES:= \
5 codegen.cpp
6
7LOCAL_SHARED_LIBRARIES := \
8 libcutils \
9 libpixelflinger
10
11LOCAL_MODULE:= test-opengl-codegen
12
13LOCAL_MODULE_TAGS := tests
14
15include $(BUILD_EXECUTABLE)
diff --git a/libpixelflinger/tests/codegen/codegen.cpp b/libpixelflinger/tests/codegen/codegen.cpp
new file mode 100644
index 000000000..18658881b
--- /dev/null
+++ b/libpixelflinger/tests/codegen/codegen.cpp
@@ -0,0 +1,21 @@
1#include <stdio.h>
2#include <stdint.h>
3
4extern "C" void ggl_test_codegen(
5 uint32_t n, uint32_t p, uint32_t t0, uint32_t t1);
6
7
8int main(int argc, char** argv)
9{
10 if (argc != 2) {
11 printf("usage: %s 00000117:03454504_00001501_00000000\n", argv[0]);
12 return 0;
13 }
14 uint32_t n;
15 uint32_t p;
16 uint32_t t0;
17 uint32_t t1;
18 sscanf(argv[1], "%08x:%08x_%08x_%08x", &p, &n, &t0, &t1);
19 ggl_test_codegen(n, p, t0, t1);
20 return 0;
21}
diff --git a/logcat/event-log-tags b/logcat/event-log-tags
index 3ee5f8e64..3d977a5e5 100644
--- a/logcat/event-log-tags
+++ b/logcat/event-log-tags
@@ -244,8 +244,8 @@
24450000 menu_item_selected (Menu type where 0 is options and 1 is context|1|5),(Menu item title|3) 24450000 menu_item_selected (Menu type where 0 is options and 1 is context|1|5),(Menu item title|3)
24550001 menu_opened (Menu type where 0 is options and 1 is context|1|5) 24550001 menu_opened (Menu type where 0 is options and 1 is context|1|5)
246# Connectivity state changed: 246# Connectivity state changed:
247# [31-11] Reserved for future use 247# [31-13] Reserved for future use
248# [10-9] Mobile network connection type (as defined by the TelephonyManager) 248# [12- 9] Network subtype (for mobile network, as defined by TelephonyManager)
249# [ 8- 3] Detailed state ordinal (as defined by NetworkInfo.DetailedState) 249# [ 8- 3] Detailed state ordinal (as defined by NetworkInfo.DetailedState)
250# [ 2- 0] Network type (as defined by ConnectivityManager) 250# [ 2- 0] Network type (as defined by ConnectivityManager)
25150020 connectivity_state_changed (custom|1|5) 25150020 connectivity_state_changed (custom|1|5)
@@ -271,8 +271,9 @@
27150024 wifi_interface_configuration_state_changed (IP_configuration|1|5) 27150024 wifi_interface_configuration_state_changed (IP_configuration|1|5)
272 272
273# Wi-Fi supplicant connection state changed: 273# Wi-Fi supplicant connection state changed:
274# [31- 1] Reserved for future use 274# [31- 2] Reserved for future use
275# [ 0- 0] Connected to supplicant (1) or disconnected from supplicant (0) 275# [ 1- 0] Connected to supplicant (1) or disconnected from supplicant (0),
276# or supplicant died (2)
27650025 wifi_supplicant_connection_state_changed (connected|1|5) 27750025 wifi_supplicant_connection_state_changed (connected|1|5)
277 278
278# PDP Context has a bad DNS address 279# PDP Context has a bad DNS address
@@ -291,6 +292,17 @@
291# Reregister to data network - timed out with no incoming packets. 292# Reregister to data network - timed out with no incoming packets.
29250104 pdp_reregister_network (out_packet_count|1|1) 29350104 pdp_reregister_network (out_packet_count|1|1)
293 294
295# PDP Setup failures
29650105 pdp_setup_fail (cause|1|5), (cid|1|5), (network_type|1|5)
297
298# Call drops
29950106 call_drop (cause|1|5), (cid|1|5), (network_type|1|5)
300
301# Data network registration failed after successful voice registration
30250107 data_network_registration_fail (op_numeric|1|5), (cid|1|5)
303
304# Suspicious status of data connection while radio poweroff
30550108 data_network_status_on_radio_off (dc_state|3), (enable|1|5)
294 306
295# Do not change these names without updating tag in: 307# Do not change these names without updating tag in:
296#//device/dalvik/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.c 308#//device/dalvik/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.c
diff --git a/logwrapper/logwrapper.c b/logwrapper/logwrapper.c
index c7a253460..f00bfbf3d 100644
--- a/logwrapper/logwrapper.c
+++ b/logwrapper/logwrapper.c
@@ -21,7 +21,9 @@
21#include <stdlib.h> 21#include <stdlib.h>
22#include <unistd.h> 22#include <unistd.h>
23#include <errno.h> 23#include <errno.h>
24#include <fcntl.h>
24 25
26#include "private/android_filesystem_config.h"
25#include "cutils/log.h" 27#include "cutils/log.h"
26 28
27void fatal(const char *msg) { 29void fatal(const char *msg) {
@@ -32,48 +34,74 @@ void fatal(const char *msg) {
32 34
33void usage() { 35void usage() {
34 fatal( 36 fatal(
35 "Usage: logwrapper BINARY [ARGS ...]\n" 37 "Usage: logwrapper [-x] BINARY [ARGS ...]\n"
36 "\n" 38 "\n"
37 "Forks and executes BINARY ARGS, redirecting stdout and stderr to\n" 39 "Forks and executes BINARY ARGS, redirecting stdout and stderr to\n"
38 "the Android logging system. Tag is set to BINARY, priority is\n" 40 "the Android logging system. Tag is set to BINARY, priority is\n"
39 "always LOG_INFO.\n"); 41 "always LOG_INFO.\n"
42 "\n"
43 "-x: Causes logwrapper to SIGSEGV when BINARY terminates\n"
44 " fault address is set to the status of wait()\n");
40} 45}
41 46
42void parent(const char *tag, int parent_read) { 47void parent(const char *tag, int seg_fault_on_exit, int parent_read) {
43 int status; 48 int status;
44 char buffer[1024]; 49 char buffer[4096];
45 50
46 int a = 0; // start index of unprocessed data 51 int a = 0; // start index of unprocessed data
47 int b = 0; // end index of unprocessed data 52 int b = 0; // end index of unprocessed data
48 int sz; 53 int sz;
49 while ((sz = read(parent_read, &buffer[b], 1023 - b)) > 0) { 54 while ((sz = read(parent_read, &buffer[b], sizeof(buffer) - 1 - b)) > 0) {
55
56 sz += b;
50 // Log one line at a time 57 // Log one line at a time
51 for (b = a; b < sz; b++) { 58 for (b = 0; b < sz; b++) {
52 if (buffer[b] == '\n') { 59 if (buffer[b] == '\r') {
60 buffer[b] = '\0';
61 } else if (buffer[b] == '\n') {
53 buffer[b] = '\0'; 62 buffer[b] = '\0';
54 LOG(LOG_INFO, tag, &buffer[a]); 63 LOG(LOG_INFO, tag, &buffer[a]);
55 a = b + 1; 64 a = b + 1;
56 } 65 }
57 } 66 }
58 67
59 if (a == 0 && b == 1023) { 68 if (a == 0 && b == sizeof(buffer) - 1) {
60 // buffer is full, flush 69 // buffer is full, flush
61 buffer[b] = '\0'; 70 buffer[b] = '\0';
62 LOG(LOG_INFO, tag, &buffer[a]); 71 LOG(LOG_INFO, tag, &buffer[a]);
63 b = 0; 72 b = 0;
64 } else { 73 } else if (a != b) {
65 // Keep left-overs 74 // Keep left-overs
66 b = sz - a; 75 b -= a;
67 memmove(buffer, &buffer[a], b); 76 memmove(buffer, &buffer[a], b);
68 a = 0; 77 a = 0;
78 } else {
79 a = 0;
80 b = 0;
69 } 81 }
82
70 } 83 }
71 // Flush remaining data 84 // Flush remaining data
72 if (a != b) { 85 if (a != b) {
73 buffer[b] = '\0'; 86 buffer[b] = '\0';
74 LOG(LOG_INFO, tag, &buffer[a]); 87 LOG(LOG_INFO, tag, &buffer[a]);
75 } 88 }
76 wait(&status); // Wait for child 89 status = 0xAAAA;
90 if (wait(&status) != -1) { // Wait for child
91 if (WIFEXITED(status))
92 LOG(LOG_INFO, "logwrapper", "%s terminated by exit(%d)", tag,
93 WEXITSTATUS(status));
94 else if (WIFSIGNALED(status))
95 LOG(LOG_INFO, "logwrapper", "%s terminated by signal %d", tag,
96 WTERMSIG(status));
97 else if (WIFSTOPPED(status))
98 LOG(LOG_INFO, "logwrapper", "%s stopped by signal %d", tag,
99 WSTOPSIG(status));
100 } else
101 LOG(LOG_INFO, "logwrapper", "%s wait() failed: %s (%d)", tag,
102 strerror(errno), errno);
103 if (seg_fault_on_exit)
104 *(int *)status = 0; // causes SIGSEGV with fault_address = status
77} 105}
78 106
79void child(int argc, char* argv[]) { 107void child(int argc, char* argv[]) {
@@ -91,35 +119,62 @@ void child(int argc, char* argv[]) {
91 119
92int main(int argc, char* argv[]) { 120int main(int argc, char* argv[]) {
93 pid_t pid; 121 pid_t pid;
122 int seg_fault_on_exit = 0;
123
124 int parent_ptty;
125 int child_ptty;
126 char *child_devname = NULL;
94 127
95 int pipe_fds[2]; 128 if (argc < 2) {
96 int *parent_read = &pipe_fds[0]; 129 usage();
97 int *child_write = &pipe_fds[1]; 130 }
131
132 if (strncmp(argv[1], "-d", 2) == 0) {
133 seg_fault_on_exit = 1;
134 argc--;
135 argv++;
136 }
98 137
99 if (argc < 2) { 138 if (argc < 2) {
100 usage(); 139 usage();
101 } 140 }
102 141
103 if (pipe(pipe_fds) < 0) { 142 /* Use ptty instead of socketpair so that STDOUT is not buffered */
104 fatal("Cannot create pipe\n"); 143 parent_ptty = open("/dev/ptmx", O_RDWR);
144 if (parent_ptty < 0) {
145 fatal("Cannot create parent ptty\n");
146 }
147
148 if (grantpt(parent_ptty) || unlockpt(parent_ptty) ||
149 ((child_devname = (char*)ptsname(parent_ptty)) == 0)) {
150 fatal("Problem with /dev/ptmx\n");
105 } 151 }
106 152
107 pid = fork(); 153 pid = fork();
108 if (pid < 0) { 154 if (pid < 0) {
109 fatal("Failed to fork\n"); 155 fatal("Failed to fork\n");
110 } else if (pid == 0) { 156 } else if (pid == 0) {
157 child_ptty = open(child_devname, O_RDWR);
158 if (child_ptty < 0) {
159 fatal("Problem with child ptty\n");
160 }
161
111 // redirect stdout and stderr 162 // redirect stdout and stderr
112 close(*parent_read); 163 close(parent_ptty);
113 dup2(*child_write, 1); 164 dup2(child_ptty, 1);
114 dup2(*child_write, 2); 165 dup2(child_ptty, 2);
115 close(*child_write); 166 close(child_ptty);
116 167
117 child(argc - 1, &argv[1]); 168 child(argc - 1, &argv[1]);
118 169
119 } else { 170 } else {
120 close(*child_write); 171 // switch user and group to "log"
172 // this may fail if we are not root,
173 // but in that case switching user/group is unnecessary
174 setgid(AID_LOG);
175 setuid(AID_LOG);
121 176
122 parent(argv[1], *parent_read); 177 parent(argv[1], seg_fault_on_exit, parent_ptty);
123 } 178 }
124 179
125 return 0; 180 return 0;
diff --git a/mkbootimg/Android.mk b/mkbootimg/Android.mk
index e44bd99a0..a579de0b6 100644
--- a/mkbootimg/Android.mk
+++ b/mkbootimg/Android.mk
@@ -8,4 +8,4 @@ LOCAL_MODULE := mkbootimg
8 8
9include $(BUILD_HOST_EXECUTABLE) 9include $(BUILD_HOST_EXECUTABLE)
10 10
11$(call dist-for-goals,user userdebug droid,$(LOCAL_BUILT_MODULE)) 11$(call dist-for-goals,droid,$(LOCAL_BUILT_MODULE))
diff --git a/mountd/ASEC.c b/mountd/ASEC.c
new file mode 100644
index 000000000..3d8e50e0a
--- /dev/null
+++ b/mountd/ASEC.c
@@ -0,0 +1,770 @@
1/*
2 * Copyright (C) 2008 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/*
18** Android Secure External Cache
19*/
20
21#include "mountd.h"
22
23#include <stdio.h>
24#include <unistd.h>
25#include <string.h>
26#include <fcntl.h>
27#include <dirent.h>
28#include <ctype.h>
29#include <pwd.h>
30#include <stdlib.h>
31#include <poll.h>
32#include <errno.h>
33
34#include <sys/ioctl.h>
35#include <sys/mount.h>
36#include <sys/stat.h>
37
38#include <linux/loop.h>
39
40#include <cutils/properties.h>
41#include <cutils/misc.h>
42
43#include "ASEC.h"
44#include "dm-ioctl.h"
45
46extern int init_module(void *, unsigned long, const char *);
47extern int delete_module(const char *, unsigned int);
48
49struct asec_context
50{
51 char *name; // Device mapper volume name
52 char *srcPath; // Path to the source (original) mount
53 char *backingFile; // Name of the image file
54 unsigned int sectors; // Number of sectors
55 char *dstPath; // Destination mount point
56 char *crypt; // Crypt options
57
58 boolean needs_format;
59 boolean started;
60 int cacheFd;
61 int lo_num;
62 int dm_num;
63 unsigned char key[16];
64};
65
66static const char *MODULES[] = { "dm_mod", "crypto", "crypto_algapi", "crypto_blkcipher",
67 "cryptomgr", "dm_crypt", "jbd",
68 "twofish_common", "twofish", "cbc",
69 "mbcache", "ext3",
70 NULL };
71static const char KEY_PATH[] = "/data/system/asec.key";
72static const char MODULE_PATH[] = "/system/lib/modules";
73static const char MKE2FS_PATH[] = "/system/bin/mke2fs";
74static const char E2FSCK_PATH[] = "/system/bin/e2fsck";
75
76boolean AsecIsStarted(void *Handle)
77{
78 struct asec_context *ctx = (struct asec_context *) Handle;
79
80 return ctx->started;
81}
82
83const char *AsecMountPoint(void *Handle)
84{
85 struct asec_context *ctx = (struct asec_context *) Handle;
86
87 return ctx->dstPath;
88}
89
90static boolean AsecIsEnabled()
91{
92 char value[PROPERTY_VALUE_MAX];
93 int enabled;
94
95 property_get(ASEC_ENABLED, value, "0");
96
97 if (atoi(value) == 1)
98 return true;
99 return false;
100}
101
102void *AsecInit(const char *Name, const char *SrcPath, const char *BackingFile,
103 const char *Size, const char *DstPath, const char *Crypt)
104{
105 struct asec_context *ctx;
106
107 LOG_ASEC("AsecInit(%s, %s, %s, %s, %s, %s):\n",
108 Name, SrcPath, BackingFile, Size, DstPath, Crypt);
109
110 if (!AsecIsEnabled()) {
111 LOG_ERROR("AsecInit(): Disabled\n");
112 return NULL;
113 }
114
115 if (!Name || !SrcPath || !BackingFile || !Size || !DstPath || !Crypt) {
116 LOG_ERROR("AsecInit(): Invalid arguments\n");
117 return NULL;
118 }
119
120 if (!(ctx = malloc(sizeof(struct asec_context)))) {
121 LOG_ERROR("AsecInit(): Out of memory\n");
122 return NULL;
123 }
124
125 memset(ctx, 0, sizeof(struct asec_context));
126 ctx->name = strdup(Name);
127 ctx->srcPath = strdup(SrcPath);
128 ctx->backingFile = strdup(BackingFile);
129 ctx->sectors = atoi(Size);
130 ctx->dstPath = strdup(DstPath);
131 ctx->crypt = strdup(Crypt);
132 return ctx;
133}
134
135void AsecDeinit(void *Handle)
136{
137 struct asec_context *ctx = (struct asec_context *) Handle;
138
139 free(ctx->name);
140 free(ctx->srcPath);
141 free(ctx->backingFile);
142 free(ctx->dstPath);
143 free(ctx->crypt);
144
145 free(ctx);
146}
147
148static int AsecLoadModules()
149{
150 int i;
151
152 for (i = 0; MODULES[i] != NULL; i++) {
153 const char *moduleName = MODULES[i];
154 char moduleFile[255];
155 int rc = 0;
156 void *module;
157 unsigned int size;
158
159 sprintf(moduleFile, "%s/%s.ko", MODULE_PATH, moduleName);
160 module = load_file(moduleFile, &size);
161 if (!module) {
162 LOG_ERROR("Failed to load module %s\n", moduleFile);
163 return -1;
164 }
165
166 rc = init_module(module, size, "");
167 free(module);
168 if (rc && errno != EEXIST) {
169 LOG_ERROR("Failed to init module %s (%d)\n", moduleFile, errno);
170 return -errno;
171 }
172 }
173 return 0;
174}
175
176static int AsecUnloadModules()
177{
178 int i, j, rc;
179
180 for (i = 0; MODULES[i] != NULL; i++);
181
182 for (j = (i - 1); j >= 0; j--) {
183 const char *moduleName = MODULES[j];
184 int maxretry = 10;
185 while(maxretry-- > 0) {
186 rc = delete_module(moduleName, O_NONBLOCK | O_EXCL);
187 if (rc < 0 && errno == EAGAIN)
188 usleep(500000);
189 else
190 break;
191 }
192 if (rc != 0) {
193 LOG_ERROR("Failed to unload module %s\n", moduleName);
194 return -errno;
195 }
196 }
197 return 0;
198}
199
200static int AsecGenerateKey(struct asec_context *ctx)
201{
202 LOG_ASEC("AsecGenerateKey():\n");
203
204 memset((void *) ctx->key, 0x69, sizeof(ctx->key));
205 return 0;
206}
207
208static int AsecLoadGenerateKey(struct asec_context *ctx)
209{
210 int fd;
211 int rc = 0;
212
213 if ((fd = open(KEY_PATH, O_RDWR | O_CREAT, 0600)) < 0) {
214 LOG_ERROR("Error opening / creating keyfile (%d)\n", errno);
215 return -errno;
216 }
217
218 if (read(fd, ctx->key, sizeof(ctx->key)) != sizeof(ctx->key)) {
219 LOG_ASEC("Generating key\n");
220 if ((rc = AsecGenerateKey(ctx)) < 0) {
221 LOG_ERROR("Error generating key (%d)\n", rc);
222 goto out;
223 }
224 if (write(fd, ctx->key, sizeof(ctx->key)) != sizeof(ctx->key)) {
225 LOG_ERROR("Error writing keyfile (%d)\n", errno);
226 rc = -1;
227 goto out;
228 }
229 }
230
231 out:
232 close (fd);
233 return rc;
234}
235
236static int AsecFormatFilesystem(struct asec_context *ctx)
237{
238 char cmdline[255];
239 int rc;
240
241 sprintf(cmdline,
242 "%s -b 4096 -m 1 -j -L \"%s\" /dev/block/dm-%d",
243 MKE2FS_PATH, ctx->name, ctx->dm_num);
244
245 LOG_ASEC("Formatting filesystem (%s)\n", cmdline);
246 // XXX: PROTECT FROM VIKING KILLER
247 if ((rc = system(cmdline)) < 0) {
248 LOG_ERROR("Error executing format command (%d)\n", errno);
249 return -errno;
250 }
251
252 rc = WEXITSTATUS(rc);
253
254 if (!rc) {
255 LOG_ASEC("Format completed\n");
256 } else {
257 LOG_ASEC("Format failed (%d)\n", rc);
258 }
259
260 return rc;
261}
262
263static int AsecCheckFilesystem(struct asec_context *ctx)
264{
265 char cmdline[255];
266 int rc;
267
268 sprintf(cmdline, "%s -p /dev/block/dm-%d", E2FSCK_PATH, ctx->dm_num);
269
270 LOG_ASEC("Checking filesystem (%s)\n", cmdline);
271 // XXX: PROTECT FROM VIKING KILLER
272 if ((rc = system(cmdline)) < 0) {
273 LOG_ERROR("Error executing check command (%d)\n", errno);
274 return -errno;
275 }
276
277 rc = WEXITSTATUS(rc);
278
279 if (rc == 0) {
280 LOG_ASEC("ASEC volume '%s' had no errors\n", ctx->name);
281 } else if (rc == 1) {
282 LOG_ASEC("ASEC volume '%s' had corrected errors\n", ctx->name);
283 rc = 0;
284 } else if (rc == 2) {
285 LOG_ERROR("ASEC volume '%s' had corrected errors (system should be rebooted)\n", ctx->name);
286 } else if (rc == 4) {
287 LOG_ERROR("ASEC volume '%s' had uncorrectable errors\n", ctx->name);
288 } else if (rc == 8) {
289 LOG_ERROR("Operational error while checking volume '%s'\n", ctx->name);
290 } else {
291 LOG_ERROR("Unknown e2fsck exit code (%d)\n", rc);
292 }
293 return rc;
294}
295
296static int AsecOpenCreateCache(struct asec_context *ctx)
297{
298 char filepath[255];
299
300 sprintf(filepath, "%s/%s", ctx->srcPath, ctx->backingFile);
301
302 if ((ctx->cacheFd = open(filepath, O_RDWR)) < 0) {
303 if (errno == ENOENT) {
304 int rc = 0;
305
306 LOG_ASEC("Creating cache file (%u sectors)\n", ctx->sectors);
307 if ((ctx->cacheFd = creat(filepath, 0600)) < 0) {
308 LOG_ERROR("Error creating cache (%d)\n", errno);
309 return -errno;
310 }
311 if (ftruncate(ctx->cacheFd, ctx->sectors * 512) < 0) {
312 LOG_ERROR("Error truncating cache (%d)\n", errno);
313 close(ctx->cacheFd);
314 unlink(filepath);
315 return -errno;
316 }
317 LOG_ASEC("Cache created (%u sectors) \n", ctx->sectors);
318 close(ctx->cacheFd); // creat() is WRONLY
319
320 if ((ctx->cacheFd = open(filepath, O_RDWR)) < 0) {
321 LOG_ERROR("Error opening cache file (%d)\n", errno);
322 close(ctx->cacheFd);
323 unlink(filepath);
324 return -errno;
325 }
326
327 ctx->needs_format = 1;
328 } else
329 return -errno;
330 } else {
331 struct stat stat_buf;
332
333 if (fstat(ctx->cacheFd, &stat_buf) < 0) {
334 LOG_ERROR("Failed to fstat cache (%d)\n", errno);
335 close(ctx->cacheFd);
336 return -errno;
337 }
338 if (stat_buf.st_size != ctx->sectors * 512) {
339 LOG_ERROR("Cache size %lld != configured size %u\n",
340 stat_buf.st_size, ctx->sectors * 512);
341 }
342
343 // XXX: Verify volume label matches ctx->name
344 }
345
346 return 0;
347}
348
349static void AsecCloseCache(struct asec_context *ctx)
350{
351 close(ctx->cacheFd);
352}
353
354static void *_align(void *ptr, unsigned int a)
355{
356 register unsigned long agn = --a;
357
358 return (void *) (((unsigned long) ptr + agn) & ~agn);
359}
360
361static struct dm_ioctl *_dm_ioctl_setup(struct asec_context *ctx, int flags)
362{
363 void *buffer;
364 void *p;
365 const size_t min_size = 16 * 1024;
366 size_t len = sizeof(struct dm_ioctl);
367 struct dm_ioctl *io;
368 struct dm_target_spec *tgt;
369 int i;
370 char params[1024];
371 char key[80];
372
373 key[0] = '\0';
374
375 for (i = 0; i < (int) sizeof(ctx->key); i++) {
376 char tmp[8];
377
378 sprintf(tmp, "%02x", ctx->key[i]);
379 strcat(key, tmp);
380 }
381
382 // XXX: Handle ctx->crypt
383 sprintf(params, "twofish %s 0 /dev/block/loop%d 0", key, ctx->lo_num);
384
385 if (len < min_size)
386 len = min_size;
387
388 if (!(buffer = malloc(len))) {
389 LOG_ERROR("Unable to allocate memory\n");
390 return NULL;
391 }
392
393 memset(buffer, 0, len);
394 io = buffer;
395 tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)];
396
397 io->version[0] = 4;
398 io->version[1] = 0;
399 io->version[2] = 0;
400
401 io->data_size = len;
402 io->data_start = sizeof(struct dm_ioctl);
403
404 io->flags = flags;
405 io->dev = 0;
406
407 io->target_count = 1;
408 io->event_nr = 1;
409 strncpy(io->name, ctx->name, sizeof(io->name));
410
411 tgt->status = 0;
412 tgt->sector_start = 0;
413 tgt->length = ctx->sectors;
414 strncpy(tgt->target_type, "crypt", sizeof(tgt->target_type));
415
416 p = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec);
417 strcpy((char *) p, params);
418 p+= strlen(params) + 1;
419
420 p = _align(p, 8);
421 tgt->next = p - buffer;
422
423 return io;
424}
425
426static int FindNextAvailableDm()
427{
428 int i;
429
430 for (i = 0; i < 8; i++) {
431 char path[255];
432 sprintf(path, "/dev/block/dm-%d", i);
433 if ((access(path, F_OK) < 0) && (errno == ENOENT))
434 return i;
435 }
436
437 LOG_ERROR("Out of device mapper numbers\n");
438 return -1;
439}
440
441static int AsecCreateDeviceMapping(struct asec_context *ctx)
442{
443 struct dm_ioctl *io;
444 int dmFd;
445 int rc = 0;
446
447 ctx->dm_num = FindNextAvailableDm();
448
449 if ((dmFd = open("/dev/device-mapper", O_RDWR)) < 0) {
450 LOG_ERROR("Error opening device mapper (%d)\n", errno);
451 return -errno;
452 }
453
454 if (!(io = _dm_ioctl_setup(ctx, 0))) {
455 LOG_ERROR("Unable to setup ioctl (out of memory)\n");
456 close(dmFd);
457 return -ENOMEM;
458 }
459
460 if ((rc = ioctl(dmFd, DM_DEV_CREATE, io)) < 0) {
461 LOG_ERROR("device-mapper create ioctl failed (%d)\n", errno);
462 rc = -errno;
463 goto out_free;
464 }
465
466 free(io);
467
468 if (!(io = _dm_ioctl_setup(ctx, DM_STATUS_TABLE_FLAG))) {
469 LOG_ERROR("Unable to setup ioctl (out of memory)\n");
470 rc = -ENOMEM;
471 goto out_nofree;
472 }
473
474 if ((rc = ioctl(dmFd, DM_TABLE_LOAD, io)) < 0) {
475 LOG_ERROR("device-mapper load ioctl failed (%d)\n", errno);
476 rc = -errno;
477 goto out_free;
478 }
479
480 free(io);
481
482 if (!(io = _dm_ioctl_setup(ctx, 0))) {
483 LOG_ERROR("Unable to setup ioctl (out of memory)\n");
484 rc = -ENOMEM;
485 goto out_nofree;
486 }
487
488 if ((rc = ioctl(dmFd, DM_DEV_SUSPEND, io)) < 0) {
489 LOG_ERROR("device-mapper resume ioctl failed (%d)\n", errno);
490 rc = -errno;
491 goto out_free;
492 }
493
494out_free:
495 free (io);
496out_nofree:
497 close (dmFd);
498 return rc;
499}
500
501static int AsecDestroyDeviceMapping(struct asec_context *ctx)
502{
503 struct dm_ioctl *io;
504 int dmFd;
505 int rc = 0;
506
507 if ((dmFd = open("/dev/device-mapper", O_RDWR)) < 0) {
508 LOG_ERROR("Error opening device mapper (%d)\n", errno);
509 return -errno;
510 }
511
512 if (!(io = _dm_ioctl_setup(ctx, DM_PERSISTENT_DEV_FLAG))) {
513 LOG_ERROR("Unable to setup ioctl (out of memory)\n");
514 rc = -ENOMEM;
515 goto out_nofree;
516 }
517
518 if ((rc = ioctl(dmFd, DM_DEV_REMOVE, io)) < 0) {
519 LOG_ERROR("device-mapper remove ioctl failed (%d)\n", errno);
520 rc = -errno;
521 goto out_free;
522 }
523
524out_free:
525 free (io);
526out_nofree:
527 close (dmFd);
528 return rc;
529}
530
531static int AsecMountCache(struct asec_context *ctx)
532{
533 int flags = MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_NOATIME | MS_NODIRATIME;
534 char devname[255];
535
536 if (access(ctx->dstPath, R_OK)) {
537 LOG_ERROR("Destination mount point '%s' unavailable (%d)\n", ctx->dstPath, errno);
538 return -errno;
539 }
540
541 sprintf(devname, "/dev/block/dm-%d", ctx->dm_num);
542
543 if (mount(devname, ctx->dstPath, "ext3", flags, NULL)) {
544 LOG_ERROR("ASEC mount failed (%d)\n", errno);
545 return -errno;
546 }
547
548 return 0;
549}
550
551static int AsecUnmountCache(struct asec_context *ctx)
552{
553 if (umount(ctx->dstPath)) {
554 if (errno == EBUSY) {
555 LOG_ASEC("ASEC volume '%s' still busy\n", ctx->name);
556 } else {
557 LOG_ERROR("ASEC umount failed (%d)\n", errno);
558 }
559 return -errno;
560 }
561 LOG_ASEC("ASEC volume '%s' unmounted\n", ctx->name);
562 return 0;
563}
564
565static int FindNextAvailableLoop()
566{
567 int i;
568
569 for (i = 0; i < MAX_LOOP; i++) {
570 struct loop_info info;
571 char devname[255];
572 int fd;
573
574 sprintf(devname, "/dev/block/loop%d", i);
575
576 if ((fd = open(devname, O_RDONLY)) < 0) {
577 LOG_ERROR("Unable to open %s (%d)\n", devname, errno);
578 return -errno;
579 }
580
581 if (ioctl(fd, LOOP_GET_STATUS, &info) < 0) {
582 close(fd);
583
584 if (errno == ENXIO)
585 return i;
586
587 LOG_ERROR("Unable to get loop status for %s (%d)\n", devname, errno);
588 return -errno;
589 }
590 close(fd);
591 }
592 return -ENXIO;
593}
594
595static int AsecCreateLoop(struct asec_context *ctx)
596{
597 char devname[255];
598 int device_fd;
599 int rc = 0;
600
601 ctx->lo_num = FindNextAvailableLoop();
602 if (ctx->lo_num < 0) {
603 LOG_ERROR("No loop devices available\n");
604 return -ENXIO;
605 }
606
607 sprintf(devname, "/dev/block/loop%d", ctx->lo_num);
608 device_fd = open(devname, O_RDWR);
609 if (device_fd < 0) {
610 LOG_ERROR("failed to open loop device (%d)\n", errno);
611 return -errno;
612 }
613
614 if (ioctl(device_fd, LOOP_SET_FD, ctx->cacheFd) < 0) {
615 LOG_ERROR("loop_set_fd ioctl failed (%d)\n", errno);
616 rc = -errno;
617 }
618 close(device_fd);
619 return rc;
620}
621
622static int AsecDestroyLoop(struct asec_context *ctx)
623{
624 char devname[255];
625 int device_fd;
626 int rc = 0;
627
628 sprintf(devname, "/dev/block/loop%d", ctx->lo_num);
629 device_fd = open(devname, O_RDONLY);
630 if (device_fd < 0) {
631 LOG_ERROR("Failed to open loop (%d)\n", errno);
632 return -errno;
633 }
634
635 if (ioctl(device_fd, LOOP_CLR_FD, 0) < 0) {
636 LOG_ERROR("Failed to destroy loop (%d)\n", errno);
637 rc = -errno;
638 }
639
640 close(device_fd);
641 return rc;
642}
643
644int AsecStart(void *Handle)
645{
646 struct asec_context *ctx = (struct asec_context *) Handle;
647 char value[PROPERTY_VALUE_MAX];
648 int rc = 0;
649
650 if (!ctx)
651 return -EINVAL;
652
653 if (ctx->started)
654 return -EBUSY;
655
656 LOG_ASEC("AsecStart(%s):\n", ctx->name);
657
658 NotifyAsecState(ASEC_BUSY, ctx->dstPath);
659
660 if ((rc = AsecLoadModules()) < 0) {
661 LOG_ERROR("AsecStart: Failed to load kernel modules\n");
662 NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
663 return rc;
664 }
665
666 if ((rc = AsecLoadGenerateKey(ctx))) {
667 LOG_ERROR("AsecStart: Failed to load / generate key\n");
668 NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
669 return rc;
670 }
671
672 if ((rc = AsecOpenCreateCache(ctx)) < 0) {
673 LOG_ERROR("AsecStart: Failed to open / create cache\n");
674 NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
675 return rc;
676 }
677
678 if ((rc = AsecCreateLoop(ctx)) < 0) {
679 LOG_ERROR("AsecStart: Failed to create loop\n");
680 NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
681 goto fail_closecache;
682 }
683
684 if ((rc = AsecCreateDeviceMapping(ctx)) < 0) {
685 LOG_ERROR("AsecStart: Failed to create devmapping (%d)\n", rc);
686 NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
687 goto fail_destroyloop;
688 }
689
690 if (ctx->needs_format) {
691 if ((rc = AsecFormatFilesystem(ctx))) {
692 LOG_ERROR("AsecStart: Failed to format cache (%d)\n", rc);
693 NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
694 goto fail_destroydm;
695 }
696 ctx->needs_format = 0;
697 } else {
698 if ((rc = AsecCheckFilesystem(ctx))) {
699 LOG_ERROR("AsecStart: Failed to check filesystem (%d)\n", rc);
700 NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
701 goto fail_destroydm;
702 }
703 }
704
705 if ((rc = AsecMountCache(ctx)) < 0) {
706 LOG_ERROR("AsecStart: Failed to mount cache (%d)\n", rc);
707 NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
708 goto fail_destroydm;
709 }
710
711 NotifyAsecState(ASEC_AVAILABLE, ctx->dstPath);
712 ctx->started = true;
713
714 return rc;
715
716 fail_destroydm:
717 AsecDestroyDeviceMapping(ctx);
718 fail_destroyloop:
719 AsecDestroyLoop(ctx);
720 fail_closecache:
721 AsecCloseCache(ctx);
722 return rc;
723}
724
725int AsecStop(void *Handle)
726{
727 struct asec_context *ctx = (struct asec_context *) Handle;
728 int rc = 0;
729
730 if (!ctx->started)
731 return -EINVAL;
732
733 LOG_ASEC("AsecStop(%s):\n", ctx->name);
734
735 NotifyAsecState(ASEC_BUSY, ctx->dstPath);
736
737 if ((rc = AsecUnmountCache(ctx)) < 0) {
738 LOG_ERROR("AsecStop: Failed to unmount cache (%d)\n", rc);
739 NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
740 return rc;
741 }
742
743 if ((rc = AsecDestroyDeviceMapping(ctx)) < 0) {
744 LOG_ERROR("AsecStop: Failed to destroy devmapping (%d)\n", rc);
745 NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
746 return rc;
747 }
748
749 if ((rc = AsecDestroyLoop(ctx)) < 0) {
750 LOG_ERROR("AsecStop: Failed to destroy loop device (%d)\n", rc);
751 NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
752 return rc;
753 }
754
755 AsecCloseCache(ctx);
756
757 if ((rc = AsecUnloadModules()) < 0) {
758 if (rc == -EAGAIN) {
759 LOG_ASEC("AsecStop: Kernel modules still in use\n");
760 } else {
761 LOG_ERROR("AsecStop: Failed to unload kernel modules (%d)\n", rc);
762 NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
763 return rc;
764 }
765 }
766
767 ctx->started = false;
768 NotifyAsecState(ASEC_DISABLED, ctx->dstPath);
769 return rc;
770}
diff --git a/mountd/ASEC.h b/mountd/ASEC.h
new file mode 100644
index 000000000..c87b28877
--- /dev/null
+++ b/mountd/ASEC.h
@@ -0,0 +1,66 @@
1#ifndef _ASEC_H
2#define _ASEC_H
3
4#define ASEC_STORES_MAX 4
5#define MAX_LOOP 8
6
7typedef enum AsecState {
8 // Feature disabled
9 ASEC_DISABLED,
10
11 // Feature enabled and operational
12 ASEC_AVAILABLE,
13
14 // Busy
15 ASEC_BUSY,
16
17 // Internal Error
18 ASEC_FAILED_INTERR,
19
20 // No media available
21 ASEC_FAILED_NOMEDIA,
22
23 // Media is corrupt
24 ASEC_FAILED_BADMEDIA,
25
26 // Key mismatch
27 ASEC_FAILED_BADKEY,
28} AsecState;
29
30/*
31 * ASEC commands
32 */
33#define ASEC_CMD_SEND_STATUS "asec_send_status"
34#define ASEC_CMD_ENABLE "asec_enable"
35#define ASEC_CMD_DISABLE "asec_disable"
36
37/*
38 * ASEC events
39 */
40
41// These events correspond to the states in the AsecState enum.
42// A path to the ASEC mount point follows the colon
43#define ASEC_EVENT_DISABLED "asec_disabled:"
44#define ASEC_EVENT_AVAILABLE "asec_available:"
45#define ASEC_EVENT_BUSY "asec_busy:"
46#define ASEC_EVENT_FAILED_INTERR "asec_failed_interror:"
47#define ASEC_EVENT_FAILED_NOMEDIA "asec_failed_nomedia"
48#define ASEC_EVENT_FAILED_BADMEDIA "asec_failed_badmedia:"
49#define ASEC_EVENT_FAILED_BADKEY "asec_failed_badkey:"
50
51/*
52 * System Properties
53 */
54
55#define ASEC_ENABLED "asec.enabled"
56
57#define ASEC_STATUS "ro.asec.status"
58#define ASEC_STATUS_DISABLED "disabled"
59#define ASEC_STATUS_AVAILABLE "available"
60#define ASEC_STATUS_BUSY "busy"
61#define ASEC_STATUS_FAILED_INTERR "internal_error"
62#define ASEC_STATUS_FAILED_NOMEDIA "no_media"
63#define ASEC_STATUS_FAILED_BADMEDIA "bad_media"
64#define ASEC_STATUS_FAILED_BADKEY "bad_key"
65
66#endif
diff --git a/mountd/Android.mk b/mountd/Android.mk
index 87bcef3ec..bc128ac0e 100644
--- a/mountd/Android.mk
+++ b/mountd/Android.mk
@@ -6,7 +6,8 @@ LOCAL_SRC_FILES:= \
6 AutoMount.c \ 6 AutoMount.c \
7 ProcessKiller.c \ 7 ProcessKiller.c \
8 Server.c \ 8 Server.c \
9 mountd.c 9 mountd.c \
10 ASEC.c
10 11
11LOCAL_MODULE:= mountd 12LOCAL_MODULE:= mountd
12 13
diff --git a/mountd/AutoMount.c b/mountd/AutoMount.c
index bfe8ad105..0aac871d5 100644
--- a/mountd/AutoMount.c
+++ b/mountd/AutoMount.c
@@ -76,17 +76,20 @@ typedef struct MountPoint {
76 76
77 // mount point for device 77 // mount point for device
78 const char* mountPoint; 78 const char* mountPoint;
79
80 // path to the UMS driver file for specifying the block device path
81 const char* driverStorePath;
79 82
80 // true if device can be shared via 83 // true if device can be shared via
81 // USB mass storage 84 // USB mass storage
82 boolean enableUms; 85 boolean enableUms;
83 86
87 // Array of ASEC handles
88 void *asecHandles[ASEC_STORES_MAX];
89
84 // true if the device is being shared via USB mass storage 90 // true if the device is being shared via USB mass storage
85 boolean umsActive; 91 boolean umsActive;
86 92
87 // logical unit number (for UMS)
88 int lun;
89
90 // current state of the mount point 93 // current state of the mount point
91 MountState state; 94 MountState state;
92 95
@@ -100,11 +103,13 @@ typedef struct MountPoint {
100 103
101// list of our mount points (does not change after initialization) 104// list of our mount points (does not change after initialization)
102static MountPoint* sMountPointList = NULL; 105static MountPoint* sMountPointList = NULL;
103static int sNextLun = 0;
104boolean gMassStorageEnabled = false; 106boolean gMassStorageEnabled = false;
105boolean gMassStorageConnected = false; 107boolean gMassStorageConnected = false;
106 108
107static pthread_t sAutoMountThread = 0; 109static pthread_t sAutoMountThread = 0;
110static pid_t gExcludedPids[2] = {-1, -1};
111
112static const char FSCK_MSDOS_PATH[] = "/system/bin/fsck_msdos";
108 113
109// number of mount points that have timeouts pending 114// number of mount points that have timeouts pending
110static int sRetriesPending = 0; 115static int sRetriesPending = 0;
@@ -116,15 +121,18 @@ static pthread_mutex_t sMutex = PTHREAD_MUTEX_INITIALIZER;
116// via USB mass storage. 121// via USB mass storage.
117static void SetBackingStore(MountPoint* mp, boolean enable) 122static void SetBackingStore(MountPoint* mp, boolean enable)
118{ 123{
119 char path[PATH_MAX];
120 int fd; 124 int fd;
121 125
126 if (!mp->driverStorePath) {
127 LOG_ERROR("no driver_store_path specified in config file for %s", mp->device);
128 return;
129 }
130
122 LOG_MOUNT("SetBackingStore enable: %s\n", (enable ? "true" : "false")); 131 LOG_MOUNT("SetBackingStore enable: %s\n", (enable ? "true" : "false"));
123 snprintf(path, sizeof(path), "/sys/devices/platform/usb_mass_storage/lun%d/file", mp->lun); 132 fd = open(mp->driverStorePath, O_WRONLY);
124 fd = open(path, O_WRONLY);
125 if (fd < 0) 133 if (fd < 0)
126 { 134 {
127 LOG_ERROR("could not open %s\n", path); 135 LOG_ERROR("could not open driver_store_path %s\n", mp->driverStorePath);
128 } 136 }
129 else 137 else
130 { 138 {
@@ -192,6 +200,56 @@ static boolean IsLoopMounted(const char* path)
192 return result; 200 return result;
193} 201}
194 202
203static int CheckFilesystem(const char *device)
204{
205 char cmdline[255];
206 int rc;
207
208 // XXX: SAN: Check for FAT signature
209
210 int result = access(FSCK_MSDOS_PATH, X_OK);
211 if (result != 0) {
212 LOG_MOUNT("CheckFilesystem(%s): fsck_msdos not found (skipping checks)\n", device);
213 return 0;
214 }
215
216 sprintf(cmdline, "%s -p %s", FSCK_MSDOS_PATH, device);
217 LOG_MOUNT("Checking filesystem (%s)\n", cmdline);
218
219 // XXX: Notify framework we're disk checking
220
221 // XXX: PROTECT FROM VIKING KILLER
222 if ((rc = system(cmdline)) < 0) {
223 LOG_ERROR("Error executing disk check command (%d)\n", errno);
224 return -errno;
225 }
226
227 rc = WEXITSTATUS(rc);
228
229 if (rc == 0) {
230 LOG_MOUNT("Filesystem check completed OK\n");
231 return 0;
232 } else if (rc == 1) {
233 LOG_MOUNT("Filesystem check failed (invalid usage)\n");
234 return -EINVAL;
235 } else if (rc == 2) {
236 LOG_MOUNT("Filesystem check failed (unresolved issues)\n");
237 return -EIO;
238 } else if (rc == 4) {
239 LOG_MOUNT("Filesystem check failed (root changed)\n");
240 return -EIO;
241 } else if (rc == 8) {
242 LOG_MOUNT("Filesystem check failed (general failure)\n");
243 return -EIO;
244 } else if (rc == 12) {
245 LOG_MOUNT("Filesystem check failed (exit signaled)\n");
246 return -EIO;
247 } else {
248 LOG_MOUNT("Filesystem check failed (unknown exit code %d)\n", rc);
249 return -EIO;
250 }
251}
252
195static int DoMountDevice(const char* device, const char* mountPoint) 253static int DoMountDevice(const char* device, const char* mountPoint)
196{ 254{
197 LOG_MOUNT("mounting %s at %s\n", device, mountPoint); 255 LOG_MOUNT("mounting %s at %s\n", device, mountPoint);
@@ -237,6 +295,17 @@ static int DoMountDevice(const char* device, const char* mountPoint)
237 if (result != 0) 295 if (result != 0)
238 return result; 296 return result;
239 297
298 if ((result = CheckFilesystem(device))) {
299 LOG_ERROR("Not mounting filesystem due to check failure (%d)\n", result);
300 // XXX: Notify framework - need a new SDCARD state for the following:
301 // - SD cards which are not present
302 // - SD cards with no partition table
303 // - SD cards with no filesystem
304 // - SD cards with bad filesystem
305 return result;
306 }
307
308
240 // Extra safety measures: 309 // Extra safety measures:
241 flags |= MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_DIRSYNC; 310 flags |= MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_DIRSYNC;
242 // Also, set fmask = 711 so that files cannot be marked executable, 311 // Also, set fmask = 711 so that files cannot be marked executable,
@@ -254,6 +323,24 @@ static int DoMountDevice(const char* device, const char* mountPoint)
254 323
255 if (result == 0) { 324 if (result == 0) {
256 NotifyMediaState(mountPoint, MEDIA_MOUNTED, (flags & MS_RDONLY) != 0); 325 NotifyMediaState(mountPoint, MEDIA_MOUNTED, (flags & MS_RDONLY) != 0);
326
327 MountPoint* mp = sMountPointList;
328 while (mp) {
329 if (!strcmp(mountPoint, mp->mountPoint)) {
330 int i;
331
332 for (i = 0; i < ASEC_STORES_MAX; i++) {
333 if (mp->asecHandles[i] != NULL) {
334 int a_result;
335 if ((a_result = AsecStart(mp->asecHandles[i])) < 0) {
336 LOG_ERROR("ASEC start failure (%d)\n", a_result);
337 }
338 }
339 }
340 break;
341 }
342 mp = mp -> next;
343 }
257 } else if (errno == EBUSY) { 344 } else if (errno == EBUSY) {
258 // ignore EBUSY, since it usually means the device is already mounted 345 // ignore EBUSY, since it usually means the device is already mounted
259 result = 0; 346 result = 0;
@@ -267,32 +354,39 @@ static int DoMountDevice(const char* device, const char* mountPoint)
267 return result; 354 return result;
268} 355}
269 356
270static int DoUnmountDevice(const char* mountPoint) 357static int DoUnmountDevice(MountPoint *mp)
271{ 358{
272 boolean loop = IsLoopMounted(mountPoint); 359 boolean loop = IsLoopMounted(mp->mountPoint);
273 int result = umount(mountPoint); 360 int i;
361
362 for (i = 0; i < ASEC_STORES_MAX; i++) {
363 if (mp->asecHandles[i] && AsecIsStarted(mp->asecHandles[i]))
364 AsecStop(mp->asecHandles[i]);
365 }
366
367 int result = umount(mp->mountPoint);
274 LOG_MOUNT("umount returned %d errno: %d\n", result, errno); 368 LOG_MOUNT("umount returned %d errno: %d\n", result, errno);
275 369
276 if (result == 0) 370 if (result == 0)
277 { 371 {
278 if (loop)
279 {
280 // free the loop device
281 int loop_fd = open(LOOP_DEVICE, O_RDONLY);
282 if (loop_fd < -1) {
283 LOG_ERROR("open loop device failed\n");
284 }
285 if (ioctl(loop_fd, LOOP_CLR_FD, 0) < 0) {
286 LOG_ERROR("ioctl LOOP_CLR_FD failed\n");
287 }
288
289 close(loop_fd);
290 }
291
292#if CREATE_MOUNT_POINTS 372#if CREATE_MOUNT_POINTS
293 rmdir(mountPoint); 373 rmdir(mountPoint);
294#endif 374#endif
295 NotifyMediaState(mountPoint, MEDIA_UNMOUNTED, false); 375 NotifyMediaState(mp->mountPoint, MEDIA_UNMOUNTED, false);
376 }
377
378 if (loop)
379 {
380 // free the loop device
381 int loop_fd = open(LOOP_DEVICE, O_RDONLY);
382 if (loop_fd < -1) {
383 LOG_ERROR("open loop device failed\n");
384 }
385 if (ioctl(loop_fd, LOOP_CLR_FD, 0) < 0) {
386 LOG_ERROR("ioctl LOOP_CLR_FD failed\n");
387 }
388
389 close(loop_fd);
296 } 390 }
297 391
298 // ignore EINVAL and ENOENT, since it usually means the device is already unmounted 392 // ignore EINVAL and ENOENT, since it usually means the device is already unmounted
@@ -408,7 +502,7 @@ static void RequestUnmount(MountPoint* mp, MountState retryState)
408 sync(); 502 sync();
409 DropSystemCaches(); 503 DropSystemCaches();
410 504
411 if (DoUnmountDevice(mp->mountPoint) == 0) 505 if (DoUnmountDevice(mp) == 0)
412 { 506 {
413 SetState(mp, kUnmounted); 507 SetState(mp, kUnmounted);
414 if (retryState == kUnmountingForUms) 508 if (retryState == kUnmountingForUms)
@@ -502,6 +596,8 @@ static void HandleMediaInserted(const char* device)
502{ 596{
503 MountPoint* mp = sMountPointList; 597 MountPoint* mp = sMountPointList;
504 598
599 LOG_MOUNT("HandleMediaInserted(%s):\n", device);
600
505 while (mp) 601 while (mp)
506 { 602 {
507 // see if the device matches mount point's block device 603 // see if the device matches mount point's block device
@@ -573,7 +669,7 @@ static void HandleRetries()
573 } 669 }
574 else if (mp->state == kUnmountingForEject || mp->state == kUnmountingForUms) 670 else if (mp->state == kUnmountingForEject || mp->state == kUnmountingForUms)
575 { 671 {
576 if (DoUnmountDevice(mp->mountPoint) == 0) 672 if (DoUnmountDevice(mp) == 0)
577 { 673 {
578 // unmounting succeeded 674 // unmounting succeeded
579 // start mass storage, if state is kUnmountingForUms 675 // start mass storage, if state is kUnmountingForUms
@@ -594,8 +690,25 @@ static void HandleRetries()
594 // send SIGKILL instead of SIGTERM if the first attempt did not succeed 690 // send SIGKILL instead of SIGTERM if the first attempt did not succeed
595 boolean sigkill = (mp->retryCount > MAX_UNMOUNT_RETRIES); 691 boolean sigkill = (mp->retryCount > MAX_UNMOUNT_RETRIES);
596 692
693 int i;
694
695 for (i = 0; i < ASEC_STORES_MAX; i++) {
696 if (mp->asecHandles[i] && AsecIsStarted(mp->asecHandles[i])) {
697 LOG_MOUNT("Killing processes for ASEC path '%s'\n",
698 AsecMountPoint(mp->asecHandles[i]));
699 KillProcessesWithOpenFiles(AsecMountPoint(mp->asecHandles[i]),
700 sigkill,
701 gExcludedPids, sizeof(gExcludedPids) / sizeof(pid_t));
702
703 // Now that we've killed the processes, try to stop the volume again
704 AsecStop(mp->asecHandles[i]);
705 }
706 }
707
597 // unmounting the device is failing, so start killing processes 708 // unmounting the device is failing, so start killing processes
598 KillProcessesWithOpenFiles(mp->mountPoint, sigkill); 709 KillProcessesWithOpenFiles(mp->mountPoint, sigkill, gExcludedPids,
710 sizeof(gExcludedPids) / sizeof(pid_t));
711
599 } 712 }
600 } 713 }
601 } 714 }
@@ -676,6 +789,8 @@ static void* AutoMountThread(void* arg)
676 int id; 789 int id;
677 struct sigaction actions; 790 struct sigaction actions;
678 791
792 gExcludedPids[1] = getpid();
793
679 memset(&actions, 0, sizeof(actions)); 794 memset(&actions, 0, sizeof(actions));
680 sigemptyset(&actions.sa_mask); 795 sigemptyset(&actions.sa_mask);
681 actions.sa_flags = 0; 796 actions.sa_flags = 0;
@@ -829,7 +944,9 @@ void EnableMassStorage(boolean enable)
829void MountMedia(const char* mountPoint) 944void MountMedia(const char* mountPoint)
830{ 945{
831 MountPoint* mp = sMountPointList; 946 MountPoint* mp = sMountPointList;
832 947
948 LOG_MOUNT("MountMedia(%s)\n", mountPoint);
949
833 pthread_mutex_lock(&sMutex); 950 pthread_mutex_lock(&sMutex);
834 while (mp) 951 while (mp)
835 { 952 {
@@ -883,27 +1000,48 @@ boolean IsMassStorageConnected()
883 * 1000 *
884 ***********************************************/ 1001 ***********************************************/
885 1002
886void AddMountPoint(const char* device, const char* mountPoint, boolean enableUms) 1003void *AddMountPoint(const char* device, const char* mountPoint, const char * driverStorePath, boolean enableUms)
887{ 1004{
888 MountPoint* newMountPoint; 1005 MountPoint* newMountPoint;
889 1006
890 LOG_MOUNT("AddMountPoint device: %s, mountPoint: %s\n", device, mountPoint); 1007 LOG_MOUNT("AddMountPoint device: %s, mountPoint: %s driverStorePath: %s\n", device, mountPoint, driverStorePath);
891 // add a new MountPoint to the head of our linked list 1008 // add a new MountPoint to the head of our linked list
892 newMountPoint = (MountPoint *)malloc(sizeof(MountPoint)); 1009 newMountPoint = (MountPoint *)malloc(sizeof(MountPoint));
893 newMountPoint->device = device; 1010 newMountPoint->device = device;
894 newMountPoint->mountPoint = mountPoint; 1011 newMountPoint->mountPoint = mountPoint;
1012 newMountPoint->driverStorePath = driverStorePath;
895 newMountPoint->enableUms = enableUms; 1013 newMountPoint->enableUms = enableUms;
896 newMountPoint->umsActive = false; 1014 newMountPoint->umsActive = false;
897 if (enableUms)
898 newMountPoint->lun = sNextLun++;
899 newMountPoint->state = kUnmounted; 1015 newMountPoint->state = kUnmounted;
900 newMountPoint->retryCount = 0; 1016 newMountPoint->retryCount = 0;
901 1017
902 // add to linked list 1018 // add to linked list
903 newMountPoint->next = sMountPointList; 1019 newMountPoint->next = sMountPointList;
904 sMountPointList = newMountPoint; 1020 sMountPointList = newMountPoint;
1021 return newMountPoint;
905} 1022}
906 1023
1024int AddAsecToMountPoint(void *Mp, const char *name, const char *backing_file, const char *size,
1025 const char *mount_point, const char *crypt)
1026{
1027 MountPoint *mp = (MountPoint *) Mp;
1028 int i;
1029
1030 for (i = 0; i < ASEC_STORES_MAX; i++) {
1031 if (!mp->asecHandles[i])
1032 break;
1033 }
1034
1035 if (i == ASEC_STORES_MAX) {
1036 LOG_ERROR("Maximum # of ASEC stores exceeded\n");
1037 return -EINVAL;
1038 }
1039
1040 if (!(mp->asecHandles[i] = AsecInit(name, mp->mountPoint, backing_file, size, mount_point, crypt)))
1041 return -1;
1042
1043 return 0;
1044}
907static void MountDevices() 1045static void MountDevices()
908{ 1046{
909 MountPoint* mp = sMountPointList; 1047 MountPoint* mp = sMountPointList;
@@ -916,6 +1054,8 @@ static void MountDevices()
916 1054
917void StartAutoMounter() 1055void StartAutoMounter()
918{ 1056{
1057 gExcludedPids[0] = getpid();
1058
919 gMassStorageConnected = ReadMassStorageState(); 1059 gMassStorageConnected = ReadMassStorageState();
920 LOG_MOUNT(gMassStorageConnected ? "USB online\n" : "USB offline\n"); 1060 LOG_MOUNT(gMassStorageConnected ? "USB online\n" : "USB offline\n");
921 1061
diff --git a/mountd/ProcessKiller.c b/mountd/ProcessKiller.c
index 3ce7aa81c..e37777446 100644
--- a/mountd/ProcessKiller.c
+++ b/mountd/ProcessKiller.c
@@ -177,7 +177,7 @@ static int get_pid(const char* s)
177} 177}
178 178
179// hunt down and kill processes that have files open on the given mount point 179// hunt down and kill processes that have files open on the given mount point
180void KillProcessesWithOpenFiles(const char* mountPoint, boolean sigkill) 180void KillProcessesWithOpenFiles(const char* mountPoint, boolean sigkill, int *excluded, int num_excluded)
181{ 181{
182 DIR* dir; 182 DIR* dir;
183 struct dirent* de; 183 struct dirent* de;
@@ -200,8 +200,21 @@ void KillProcessesWithOpenFiles(const char* mountPoint, boolean sigkill)
200 || CheckSymLink(pid, mountPoint, "exe", "executable path") // check executable path 200 || CheckSymLink(pid, mountPoint, "exe", "executable path") // check executable path
201 ) 201 )
202 { 202 {
203 LOG_ERROR("Killing process %d\n", pid); 203 int i;
204 kill(pid, (sigkill ? SIGKILL : SIGTERM)); 204 boolean hit = false;
205
206 for (i = 0; i < num_excluded; i++) {
207 if (pid == excluded[i]) {
208 LOG_ERROR("I just need a little more TIME captain!\n");
209 hit = true;
210 break;
211 }
212 }
213
214 if (!hit) {
215 LOG_ERROR("Killing process %d\n", pid);
216 kill(pid, (sigkill ? SIGKILL : SIGTERM));
217 }
205 } 218 }
206 } 219 }
207 220
diff --git a/mountd/Server.c b/mountd/Server.c
index 14b383001..64459bd88 100644
--- a/mountd/Server.c
+++ b/mountd/Server.c
@@ -19,6 +19,7 @@
19*/ 19*/
20 20
21#include "mountd.h" 21#include "mountd.h"
22#include "ASEC.h"
22 23
23#include <cutils/properties.h> 24#include <cutils/properties.h>
24#include <cutils/sockets.h> 25#include <cutils/sockets.h>
@@ -43,6 +44,10 @@ static pthread_mutex_t sWriteMutex = PTHREAD_MUTEX_INITIALIZER;
43// path for media that failed to mount before the runtime is connected 44// path for media that failed to mount before the runtime is connected
44static char* sDeferredUnmountableMediaPath = NULL; 45static char* sDeferredUnmountableMediaPath = NULL;
45 46
47// last asec msg before the runtime was connected
48static char* sAsecDeferredMessage = NULL;
49static char* sAsecDeferredArgument = NULL;
50
46static int Write(const char* message) 51static int Write(const char* message)
47{ 52{
48 int result = -1; 53 int result = -1;
@@ -107,6 +112,18 @@ static void DoCommand(const char* command)
107 { 112 {
108 const char* path = command + strlen(MOUNTD_EJECT_MEDIA); 113 const char* path = command + strlen(MOUNTD_EJECT_MEDIA);
109 UnmountMedia(path); 114 UnmountMedia(path);
115 }
116 else if (strncmp(command, ASEC_CMD_ENABLE, strlen(ASEC_CMD_ENABLE)) == 0) {
117 LOG_ASEC("Got ASEC_CMD_ENABLE\n");
118 // XXX: SAN: Impliment
119 }
120 else if (strncmp(command, ASEC_CMD_DISABLE, strlen(ASEC_CMD_DISABLE)) == 0) {
121 LOG_ASEC("Got ASEC_CMD_DISABLE\n");
122 // XXX: SAN: Impliment
123 }
124 else if (strncmp(command, ASEC_CMD_SEND_STATUS, strlen(ASEC_CMD_SEND_STATUS)) == 0) {
125 LOG_ASEC("Got ASEC_CMD_SEND_STATUS\n");
126 // XXX: SAN: Impliment
110 } 127 }
111 else 128 else
112 LOGE("unknown command %s\n", command); 129 LOGE("unknown command %s\n", command);
@@ -145,6 +162,15 @@ int RunServer()
145 sDeferredUnmountableMediaPath = NULL; 162 sDeferredUnmountableMediaPath = NULL;
146 } 163 }
147 164
165 if (sAsecDeferredMessage) {
166
167 if (Write2(sAsecDeferredMessage, sAsecDeferredArgument) < 0)
168 LOG_ERROR("Failed to deliver deferred ASEC msg to framework\n");
169 free(sAsecDeferredMessage);
170 free(sAsecDeferredArgument);
171 sAsecDeferredMessage = sAsecDeferredArgument = NULL;
172 }
173
148 while (1) 174 while (1)
149 { 175 {
150 char buffer[101]; 176 char buffer[101];
@@ -187,6 +213,61 @@ void SendUnmountRequest(const char* path)
187 Write2(MOUNTD_REQUEST_EJECT, path); 213 Write2(MOUNTD_REQUEST_EJECT, path);
188} 214}
189 215
216void NotifyAsecState(AsecState state, const char *argument)
217{
218 const char *event = NULL;
219 const char *status = NULL;
220 boolean deferr = true;;
221
222 switch (state) {
223 case ASEC_DISABLED:
224 event = ASEC_EVENT_DISABLED;
225 status = ASEC_STATUS_DISABLED;
226 break;
227 case ASEC_AVAILABLE:
228 event = ASEC_EVENT_AVAILABLE;
229 status = ASEC_STATUS_AVAILABLE;
230 break;
231 case ASEC_BUSY:
232 event = ASEC_EVENT_BUSY;
233 status = ASEC_STATUS_BUSY;
234 deferr = false;
235 break;
236 case ASEC_FAILED_INTERR:
237 event = ASEC_EVENT_FAILED_INTERR;
238 status = ASEC_STATUS_FAILED_INTERR;
239 break;
240 case ASEC_FAILED_NOMEDIA:
241 event = ASEC_EVENT_FAILED_NOMEDIA;
242 status = ASEC_STATUS_FAILED_NOMEDIA;
243 break;
244 case ASEC_FAILED_BADMEDIA:
245 event = ASEC_EVENT_FAILED_BADMEDIA;
246 status = ASEC_STATUS_FAILED_BADMEDIA;
247 break;
248 case ASEC_FAILED_BADKEY:
249 event = ASEC_EVENT_FAILED_BADKEY;
250 status = ASEC_STATUS_FAILED_BADKEY;
251 break;
252 default:
253 LOG_ERROR("unknown AsecState %d in NotifyAsecState\n", state);
254 return;
255 }
256
257 property_set(ASEC_STATUS, status);
258
259 int result = Write2(event, argument);
260 if ((result < 0) && deferr) {
261 if (sAsecDeferredMessage)
262 free(sAsecDeferredMessage);
263 sAsecDeferredMessage = strdup(event);
264 if (sAsecDeferredArgument)
265 free(sAsecDeferredArgument);
266 sAsecDeferredArgument = strdup(argument);
267 LOG_ASEC("Deferring event '%s' arg '%s' until framework connects\n", event, argument);
268 }
269}
270
190void NotifyMediaState(const char* path, MediaState state, boolean readOnly) 271void NotifyMediaState(const char* path, MediaState state, boolean readOnly)
191{ 272{
192 const char* event = NULL; 273 const char* event = NULL;
diff --git a/mountd/dm-ioctl.h b/mountd/dm-ioctl.h
new file mode 100644
index 000000000..ee5c3508b
--- /dev/null
+++ b/mountd/dm-ioctl.h
@@ -0,0 +1,304 @@
1/*
2 * Copyright (C) 2001 - 2003 Sistina Software (UK) Limited.
3 * Copyright (C) 2004 - 2005 Red Hat, Inc. All rights reserved.
4 *
5 * This file is released under the LGPL.
6 */
7
8#ifndef _LINUX_DM_IOCTL_V4_H
9#define _LINUX_DM_IOCTL_V4_H
10
11#ifdef linux
12# include <linux/types.h>
13#endif
14
15#define DM_DIR "mapper" /* Slashes not supported */
16#define DM_MAX_TYPE_NAME 16
17#define DM_NAME_LEN 128
18#define DM_UUID_LEN 129
19
20/*
21 * A traditional ioctl interface for the device mapper.
22 *
23 * Each device can have two tables associated with it, an
24 * 'active' table which is the one currently used by io passing
25 * through the device, and an 'inactive' one which is a table
26 * that is being prepared as a replacement for the 'active' one.
27 *
28 * DM_VERSION:
29 * Just get the version information for the ioctl interface.
30 *
31 * DM_REMOVE_ALL:
32 * Remove all dm devices, destroy all tables. Only really used
33 * for debug.
34 *
35 * DM_LIST_DEVICES:
36 * Get a list of all the dm device names.
37 *
38 * DM_DEV_CREATE:
39 * Create a new device, neither the 'active' or 'inactive' table
40 * slots will be filled. The device will be in suspended state
41 * after creation, however any io to the device will get errored
42 * since it will be out-of-bounds.
43 *
44 * DM_DEV_REMOVE:
45 * Remove a device, destroy any tables.
46 *
47 * DM_DEV_RENAME:
48 * Rename a device.
49 *
50 * DM_SUSPEND:
51 * This performs both suspend and resume, depending which flag is
52 * passed in.
53 * Suspend: This command will not return until all pending io to
54 * the device has completed. Further io will be deferred until
55 * the device is resumed.
56 * Resume: It is no longer an error to issue this command on an
57 * unsuspended device. If a table is present in the 'inactive'
58 * slot, it will be moved to the active slot, then the old table
59 * from the active slot will be _destroyed_. Finally the device
60 * is resumed.
61 *
62 * DM_DEV_STATUS:
63 * Retrieves the status for the table in the 'active' slot.
64 *
65 * DM_DEV_WAIT:
66 * Wait for a significant event to occur to the device. This
67 * could either be caused by an event triggered by one of the
68 * targets of the table in the 'active' slot, or a table change.
69 *
70 * DM_TABLE_LOAD:
71 * Load a table into the 'inactive' slot for the device. The
72 * device does _not_ need to be suspended prior to this command.
73 *
74 * DM_TABLE_CLEAR:
75 * Destroy any table in the 'inactive' slot (ie. abort).
76 *
77 * DM_TABLE_DEPS:
78 * Return a set of device dependencies for the 'active' table.
79 *
80 * DM_TABLE_STATUS:
81 * Return the targets status for the 'active' table.
82 *
83 * DM_TARGET_MSG:
84 * Pass a message string to the target at a specific offset of a device.
85 *
86 * DM_DEV_SET_GEOMETRY:
87 * Set the geometry of a device by passing in a string in this format:
88 *
89 * "cylinders heads sectors_per_track start_sector"
90 *
91 * Beware that CHS geometry is nearly obsolete and only provided
92 * for compatibility with dm devices that can be booted by a PC
93 * BIOS. See struct hd_geometry for range limits. Also note that
94 * the geometry is erased if the device size changes.
95 */
96
97/*
98 * All ioctl arguments consist of a single chunk of memory, with
99 * this structure at the start. If a uuid is specified any
100 * lookup (eg. for a DM_INFO) will be done on that, *not* the
101 * name.
102 */
103struct dm_ioctl {
104 /*
105 * The version number is made up of three parts:
106 * major - no backward or forward compatibility,
107 * minor - only backwards compatible,
108 * patch - both backwards and forwards compatible.
109 *
110 * All clients of the ioctl interface should fill in the
111 * version number of the interface that they were
112 * compiled with.
113 *
114 * All recognised ioctl commands (ie. those that don't
115 * return -ENOTTY) fill out this field, even if the
116 * command failed.
117 */
118 uint32_t version[3]; /* in/out */
119 uint32_t data_size; /* total size of data passed in
120 * including this struct */
121
122 uint32_t data_start; /* offset to start of data
123 * relative to start of this struct */
124
125 uint32_t target_count; /* in/out */
126 int32_t open_count; /* out */
127 uint32_t flags; /* in/out */
128 uint32_t event_nr; /* in/out */
129 uint32_t padding;
130
131 uint64_t dev; /* in/out */
132
133 char name[DM_NAME_LEN]; /* device name */
134 char uuid[DM_UUID_LEN]; /* unique identifier for
135 * the block device */
136 char data[7]; /* padding or data */
137};
138
139/*
140 * Used to specify tables. These structures appear after the
141 * dm_ioctl.
142 */
143struct dm_target_spec {
144 uint64_t sector_start;
145 uint64_t length;
146 int32_t status; /* used when reading from kernel only */
147
148 /*
149 * Location of the next dm_target_spec.
150 * - When specifying targets on a DM_TABLE_LOAD command, this value is
151 * the number of bytes from the start of the "current" dm_target_spec
152 * to the start of the "next" dm_target_spec.
153 * - When retrieving targets on a DM_TABLE_STATUS command, this value
154 * is the number of bytes from the start of the first dm_target_spec
155 * (that follows the dm_ioctl struct) to the start of the "next"
156 * dm_target_spec.
157 */
158 uint32_t next;
159
160 char target_type[DM_MAX_TYPE_NAME];
161
162 /*
163 * Parameter string starts immediately after this object.
164 * Be careful to add padding after string to ensure correct
165 * alignment of subsequent dm_target_spec.
166 */
167};
168
169/*
170 * Used to retrieve the target dependencies.
171 */
172struct dm_target_deps {
173 uint32_t count; /* Array size */
174 uint32_t padding; /* unused */
175 uint64_t dev[0]; /* out */
176};
177
178/*
179 * Used to get a list of all dm devices.
180 */
181struct dm_name_list {
182 uint64_t dev;
183 uint32_t next; /* offset to the next record from
184 the _start_ of this */
185 char name[0];
186};
187
188/*
189 * Used to retrieve the target versions
190 */
191struct dm_target_versions {
192 uint32_t next;
193 uint32_t version[3];
194
195 char name[0];
196};
197
198/*
199 * Used to pass message to a target
200 */
201struct dm_target_msg {
202 uint64_t sector; /* Device sector */
203
204 char message[0];
205};
206
207/*
208 * If you change this make sure you make the corresponding change
209 * to dm-ioctl.c:lookup_ioctl()
210 */
211enum {
212 /* Top level cmds */
213 DM_VERSION_CMD = 0,
214 DM_REMOVE_ALL_CMD,
215 DM_LIST_DEVICES_CMD,
216
217 /* device level cmds */
218 DM_DEV_CREATE_CMD,
219 DM_DEV_REMOVE_CMD,
220 DM_DEV_RENAME_CMD,
221 DM_DEV_SUSPEND_CMD,
222 DM_DEV_STATUS_CMD,
223 DM_DEV_WAIT_CMD,
224
225 /* Table level cmds */
226 DM_TABLE_LOAD_CMD,
227 DM_TABLE_CLEAR_CMD,
228 DM_TABLE_DEPS_CMD,
229 DM_TABLE_STATUS_CMD,
230
231 /* Added later */
232 DM_LIST_VERSIONS_CMD,
233 DM_TARGET_MSG_CMD,
234 DM_DEV_SET_GEOMETRY_CMD
235};
236
237#define DM_IOCTL 0xfd
238
239#define DM_VERSION _IOWR(DM_IOCTL, DM_VERSION_CMD, struct dm_ioctl)
240#define DM_REMOVE_ALL _IOWR(DM_IOCTL, DM_REMOVE_ALL_CMD, struct dm_ioctl)
241#define DM_LIST_DEVICES _IOWR(DM_IOCTL, DM_LIST_DEVICES_CMD, struct dm_ioctl)
242
243#define DM_DEV_CREATE _IOWR(DM_IOCTL, DM_DEV_CREATE_CMD, struct dm_ioctl)
244#define DM_DEV_REMOVE _IOWR(DM_IOCTL, DM_DEV_REMOVE_CMD, struct dm_ioctl)
245#define DM_DEV_RENAME _IOWR(DM_IOCTL, DM_DEV_RENAME_CMD, struct dm_ioctl)
246#define DM_DEV_SUSPEND _IOWR(DM_IOCTL, DM_DEV_SUSPEND_CMD, struct dm_ioctl)
247#define DM_DEV_STATUS _IOWR(DM_IOCTL, DM_DEV_STATUS_CMD, struct dm_ioctl)
248#define DM_DEV_WAIT _IOWR(DM_IOCTL, DM_DEV_WAIT_CMD, struct dm_ioctl)
249
250#define DM_TABLE_LOAD _IOWR(DM_IOCTL, DM_TABLE_LOAD_CMD, struct dm_ioctl)
251#define DM_TABLE_CLEAR _IOWR(DM_IOCTL, DM_TABLE_CLEAR_CMD, struct dm_ioctl)
252#define DM_TABLE_DEPS _IOWR(DM_IOCTL, DM_TABLE_DEPS_CMD, struct dm_ioctl)
253#define DM_TABLE_STATUS _IOWR(DM_IOCTL, DM_TABLE_STATUS_CMD, struct dm_ioctl)
254
255#define DM_LIST_VERSIONS _IOWR(DM_IOCTL, DM_LIST_VERSIONS_CMD, struct dm_ioctl)
256
257#define DM_TARGET_MSG _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, struct dm_ioctl)
258#define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
259
260#define DM_VERSION_MAJOR 4
261#define DM_VERSION_MINOR 13
262#define DM_VERSION_PATCHLEVEL 0
263#define DM_VERSION_EXTRA "-ioctl (2007-10-18)"
264
265/* Status bits */
266#define DM_READONLY_FLAG (1 << 0) /* In/Out */
267#define DM_SUSPEND_FLAG (1 << 1) /* In/Out */
268#define DM_PERSISTENT_DEV_FLAG (1 << 3) /* In */
269
270/*
271 * Flag passed into ioctl STATUS command to get table information
272 * rather than current status.
273 */
274#define DM_STATUS_TABLE_FLAG (1 << 4) /* In */
275
276/*
277 * Flags that indicate whether a table is present in either of
278 * the two table slots that a device has.
279 */
280#define DM_ACTIVE_PRESENT_FLAG (1 << 5) /* Out */
281#define DM_INACTIVE_PRESENT_FLAG (1 << 6) /* Out */
282
283/*
284 * Indicates that the buffer passed in wasn't big enough for the
285 * results.
286 */
287#define DM_BUFFER_FULL_FLAG (1 << 8) /* Out */
288
289/*
290 * This flag is now ignored.
291 */
292#define DM_SKIP_BDGET_FLAG (1 << 9) /* In */
293
294/*
295 * Set this to avoid attempting to freeze any filesystem when suspending.
296 */
297#define DM_SKIP_LOCKFS_FLAG (1 << 10) /* In */
298
299/*
300 * Set this to suspend without flushing queued ios.
301 */
302#define DM_NOFLUSH_FLAG (1 << 11) /* In */
303
304#endif /* _LINUX_DM_IOCTL_H */
diff --git a/mountd/mountd.c b/mountd/mountd.c
index fb54fe68d..27ec8de90 100644
--- a/mountd/mountd.c
+++ b/mountd/mountd.c
@@ -39,6 +39,54 @@
39FILE* logFile; 39FILE* logFile;
40#endif 40#endif
41 41
42struct asec_cfg {
43 const char *name;
44 const char *backing_file;
45 const char *size;
46 const char *mount_point;
47 const char *crypt;
48};
49
50static int ProcessAsecData(cnode *node, struct asec_cfg *stores, int idx)
51{
52 cnode *child = node->first_child;
53 const char *name = NULL;
54 const char *file = NULL;
55 const char *size = NULL;
56 const char *mp = NULL;
57 const char *crypt = NULL;
58
59 LOG_ASEC("ProcessAsecData(%s, %p, %d)\n", node->name, stores, idx);
60
61 while (child) {
62 if (!strcmp(child->name, "name"))
63 name = child->value;
64 else if (!strcmp(child->name, "backing_file"))
65 file = child->value;
66 else if (!strcmp(child->name, "size"))
67 size = child->value;
68 else if (!strcmp(child->name, "mount_point"))
69 mp = child->value;
70 else if (!strcmp(child->name, "crypt"))
71 crypt = child->value;
72 child = child->next;
73 }
74
75 if (!name || !file || !size || !mp || !crypt) {
76 LOG_ERROR("Missing required token from config. Skipping ASEC volume\n");
77 return -1;
78 } else if (idx == ASEC_STORES_MAX) {
79 LOG_ERROR("Maximum # of ASEC stores already defined\n");
80 return -1;
81 }
82
83 stores[idx].name = name;
84 stores[idx].backing_file = file;
85 stores[idx].size = size;
86 stores[idx].mount_point = mp;
87 stores[idx].crypt = crypt;
88 return ++idx;
89}
42 90
43static void ReadConfigFile(const char* path) 91static void ReadConfigFile(const char* path)
44{ 92{
@@ -54,18 +102,31 @@ static void ReadConfigFile(const char* path)
54 { 102 {
55 const char* block_device = NULL; 103 const char* block_device = NULL;
56 const char* mount_point = NULL; 104 const char* mount_point = NULL;
105 const char* driver_store_path = NULL;
57 boolean enable_ums = false; 106 boolean enable_ums = false;
58 cnode* child = node->first_child; 107 cnode* child = node->first_child;
59 108 struct asec_cfg asec_stores[ASEC_STORES_MAX];
109 int asec_idx = 0;
110
111 memset(asec_stores, 0, sizeof(asec_stores));
112
60 while (child) 113 while (child)
61 { 114 {
62 const char* name = child->name; 115 const char* name = child->name;
63 const char* value = child->value; 116 const char* value = child->value;
64 117
65 if (strcmp(name, "block_device") == 0) 118 if (!strncmp(name, "asec_", 5)) {
119 int rc = ProcessAsecData(child, asec_stores, asec_idx);
120 if (rc < 0) {
121 LOG_ERROR("Error processing ASEC cfg data\n");
122 } else
123 asec_idx = rc;
124 } else if (strcmp(name, "block_device") == 0)
66 block_device = value; 125 block_device = value;
67 else if (strcmp(name, "mount_point") == 0) 126 else if (strcmp(name, "mount_point") == 0)
68 mount_point = value; 127 mount_point = value;
128 else if (strcmp(name, "driver_store_path") == 0)
129 driver_store_path = value;
69 else if (strcmp(name, "enable_ums") == 0 && 130 else if (strcmp(name, "enable_ums") == 0 &&
70 strcmp(value, "true") == 0) 131 strcmp(value, "true") == 0)
71 enable_ums = true; 132 enable_ums = true;
@@ -76,7 +137,14 @@ static void ReadConfigFile(const char* path)
76 // mount point and removable fields are optional 137 // mount point and removable fields are optional
77 if (block_device && mount_point) 138 if (block_device && mount_point)
78 { 139 {
79 AddMountPoint(block_device, mount_point, enable_ums); 140 void *mp = AddMountPoint(block_device, mount_point, driver_store_path, enable_ums);
141 int i;
142
143 for (i = 0; i < asec_idx; i++) {
144 AddAsecToMountPoint(mp, asec_stores[i].name, asec_stores[i].backing_file,
145 asec_stores[i].size, asec_stores[i].mount_point,
146 asec_stores[i].crypt);
147 }
80 } 148 }
81 } 149 }
82 150
diff --git a/mountd/mountd.h b/mountd/mountd.h
index 746a41483..9b6248479 100644
--- a/mountd/mountd.h
+++ b/mountd/mountd.h
@@ -20,21 +20,28 @@
20#define LOG_TAG "mountd" 20#define LOG_TAG "mountd"
21#include "cutils/log.h" 21#include "cutils/log.h"
22 22
23#include "ASEC.h"
24
23typedef int boolean; 25typedef int boolean;
24enum { 26enum {
25 false = 0, 27 false = 0,
26 true = 1 28 true = 1
27}; 29};
28 30
31#define WEXITSTATUS(status) (((status) & 0xff00) >> 8)
32
29// Set this for logging error messages 33// Set this for logging error messages
30#define ENABLE_LOG_ERROR 34#define ENABLE_LOG_ERROR
31 35
32// set this to log automounter events 36// set this to log automounter events
33//#define ENABLE_LOG_MOUNT 37#define ENABLE_LOG_MOUNT
34 38
35// set this to log server events 39// set this to log server events
36//#define ENABLE_LOG_SERVER 40//#define ENABLE_LOG_SERVER
37 41
42// set this to log ASEC events
43#define ENABLE_LOG_ASEC
44
38#ifdef ENABLE_LOG_ERROR 45#ifdef ENABLE_LOG_ERROR
39#define LOG_ERROR(fmt, args...) \ 46#define LOG_ERROR(fmt, args...) \
40 { LOGE(fmt , ## args); } 47 { LOGE(fmt , ## args); }
@@ -59,6 +66,14 @@ enum {
59 do { } while (0) 66 do { } while (0)
60#endif /* ENABLE_LOG_SERVER */ 67#endif /* ENABLE_LOG_SERVER */
61 68
69#ifdef ENABLE_LOG_ASEC
70#define LOG_ASEC(fmt, args...) \
71 { LOGD(fmt , ## args); }
72#else
73#define LOG_ASEC(fmt, args...) \
74 do { } while (0)
75#endif /* ENABLE_LOG_ASEC */
76
62 77
63typedef enum MediaState { 78typedef enum MediaState {
64 // no media in SD card slot 79 // no media in SD card slot
@@ -135,7 +150,11 @@ void UnmountMedia(const char* mountPoint);
135void EnableMassStorage(boolean enable); 150void EnableMassStorage(boolean enable);
136 151
137// call this before StartAutoMounter() to add a mount point to monitor 152// call this before StartAutoMounter() to add a mount point to monitor
138void AddMountPoint(const char* device, const char* mountPoint, boolean enableUms); 153void *AddMountPoint(const char* device, const char* mountPoint, const char* driverStorePath,
154 boolean enableUms);
155
156int AddAsecToMountPoint(void *Mp, const char *name, const char *backing_file,
157 const char *size, const char *mount_point, const char *crypt);
139 158
140// start automounter thread 159// start automounter thread
141void StartAutoMounter(); 160void StartAutoMounter();
@@ -144,9 +163,19 @@ void StartAutoMounter();
144void NotifyExistingMounts(); 163void NotifyExistingMounts();
145 164
146 165
166// ASEC.c
167
168void *AsecInit(const char *Name, const char *SrcPath, const char *BackingFile,
169 const char *Size, const char *DstPath, const char *Crypt);
170int AsecStart(void *Handle);
171int AsecStop(void *Handle);
172void AsecDeinit(void *Handle);
173boolean AsecIsStarted(void *Handle);
174const char *AsecMountPoint(void *Handle);
175
147// ProcessKiller.c 176// ProcessKiller.c
148 177
149void KillProcessesWithOpenFiles(const char* mountPoint, boolean sigkill); 178void KillProcessesWithOpenFiles(const char* mountPoint, boolean sigkill, pid_t *excluded, int num_excluded);
150 179
151 180
152// Server.c 181// Server.c
@@ -155,5 +184,5 @@ int RunServer();
155void SendMassStorageConnected(boolean connected); 184void SendMassStorageConnected(boolean connected);
156void SendUnmountRequest(const char* path); 185void SendUnmountRequest(const char* path);
157void NotifyMediaState(const char* path, MediaState state, boolean readOnly); 186void NotifyMediaState(const char* path, MediaState state, boolean readOnly);
158 187void NotifyAsecState(AsecState state, const char *argument);
159#endif // MOUNTD_H__ 188#endif // MOUNTD_H__
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 756005b30..7ff1a74a1 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -7,8 +7,7 @@ copy_from := \
7 etc/mountd.conf \ 7 etc/mountd.conf \
8 etc/dbus.conf \ 8 etc/dbus.conf \
9 etc/init.goldfish.sh \ 9 etc/init.goldfish.sh \
10 etc/hosts \ 10 etc/hosts
11 etc/hcid.conf
12 11
13dont_copy := \ 12dont_copy := \
14 etc/init.gprs-pppd \ 13 etc/init.gprs-pppd \
@@ -28,10 +27,13 @@ ALL_PREBUILT += $(copy_to)
28 27
29# files that live under /... 28# files that live under /...
30 29
30# Only copy init.rc if the target doesn't have its own.
31ifneq ($(TARGET_PROVIDES_INIT_RC),true)
31file := $(TARGET_ROOT_OUT)/init.rc 32file := $(TARGET_ROOT_OUT)/init.rc
32$(file) : $(LOCAL_PATH)/init.rc | $(ACP) 33$(file) : $(LOCAL_PATH)/init.rc | $(ACP)
33 $(transform-prebuilt-to-target) 34 $(transform-prebuilt-to-target)
34ALL_PREBUILT += $(file) 35ALL_PREBUILT += $(file)
36endif
35 37
36file := $(TARGET_ROOT_OUT)/init.goldfish.rc 38file := $(TARGET_ROOT_OUT)/init.goldfish.rc
37$(file) : $(LOCAL_PATH)/etc/init.goldfish.rc | $(ACP) 39$(file) : $(LOCAL_PATH)/etc/init.goldfish.rc | $(ACP)
diff --git a/rootdir/etc/dbus.conf b/rootdir/etc/dbus.conf
index 8742345eb..75586b92d 100644
--- a/rootdir/etc/dbus.conf
+++ b/rootdir/etc/dbus.conf
@@ -5,9 +5,6 @@
5 <!-- Our well-known bus type, do not change this --> 5 <!-- Our well-known bus type, do not change this -->
6 <type>system</type> 6 <type>system</type>
7 7
8 <!-- Fork into daemon mode -->
9 <fork/>
10
11 <!-- Only allow socket-credentials-based authentication --> 8 <!-- Only allow socket-credentials-based authentication -->
12 <auth>EXTERNAL</auth> 9 <auth>EXTERNAL</auth>
13 10
@@ -17,51 +14,14 @@
17 systems.) --> 14 systems.) -->
18 <listen>unix:path=/dev/socket/dbus</listen> 15 <listen>unix:path=/dev/socket/dbus</listen>
19 16
17 <!-- Allow everything, D-Bus socket is protected by unix filesystem
18 permissions -->
20 <policy context="default"> 19 <policy context="default">
21 <!-- Deny everything then punch holes --> 20 <allow send_interface="*"/>
22 <deny send_interface="*"/> 21 <allow receive_interface="*"/>
23 <deny receive_interface="*"/> 22 <allow own="*"/>
24 <deny own="*"/>
25 <!-- But allow all users to connect -->
26 <allow user="*"/> 23 <allow user="*"/>
27 <!-- Allow anyone to talk to the message bus -->
28 <!-- FIXME I think currently these allow rules are always implicit
29 even if they aren't in here -->
30 <allow send_destination="org.freedesktop.DBus"/>
31 <allow receive_sender="org.freedesktop.DBus"/>
32 <!-- valid replies are always allowed -->
33 <allow send_requested_reply="true"/> 24 <allow send_requested_reply="true"/>
34 <allow receive_requested_reply="true"/> 25 <allow receive_requested_reply="true"/>
35 </policy> 26 </policy>
36
37
38 <!-- Now punch holes for bluetooth -->
39
40 <policy context="default">
41 <allow own="*"/>
42 <allow user="*"/>
43 <allow send_destination="org.bluez.PasskeyAgent"/>
44 <allow receive_sender="org.bluez.PasskeyAgent"/>
45 <allow send_path="/org/bluez/PasskeyAgent"/>
46 </policy>
47
48 <policy user="root">
49 <allow own="org.bluez"/>
50 </policy>
51
52 <policy at_console="true">
53 <allow send_destination="org.bluez.Adapter"/>
54 <allow receive_sender="org.bluez.Adapter"/>
55
56 <allow send_path="/org/bluez/Adapter"/>
57
58 <allow send_destination="org.bluez.Manager"/>
59 <allow receive_sender="org.bluez.Manager"/>
60
61 <allow send_path="/org/bluez/Manager"/>
62
63 <allow send_destination="org.bluez.Security"/>
64 <allow receive_sender="org.bluez.Security"/>
65 </policy>
66
67</busconfig> 27</busconfig>
diff --git a/rootdir/etc/hcid.conf b/rootdir/etc/hcid.conf
deleted file mode 100644
index 56df63a2d..000000000
--- a/rootdir/etc/hcid.conf
+++ /dev/null
@@ -1,64 +0,0 @@
1#
2# HCI daemon configuration file.
3#
4
5# HCId options
6options {
7 # Automatically initialize new devices
8 autoinit yes;
9
10 # Security Manager mode
11 # none - Security manager disabled
12 # auto - Use local PIN for incoming connections
13 # user - Always ask user for a PIN
14 #
15 security user;
16
17 # Pairing mode
18 # none - Pairing disabled
19 # multi - Allow pairing with already paired devices
20 # once - Pair once and deny successive attempts
21 pairing multi;
22}
23
24# Default settings for HCI devices
25device {
26 # Local device name
27 # %d - device id
28 # %h - host name
29 # %b - ro.product.brand
30 # %m - ro.product.model
31 # %n - ro.product.name
32 name "%m";
33
34 # Local device class
35 # 0x400000 - Service class: Telephony
36 # 0x000200 - Major class: Phone
37 # 0x00000C - Minor class: Smart phone
38 class 0x40020C;
39
40 # Default packet type
41 #pkt_type DH1,DM1,HV1;
42
43 # Inquiry and Page scan
44 iscan disable;
45 pscan enable;
46
47 # Page timeout (in 0.625ms slots): 10 seconds
48 pageto 16384;
49
50 # Default link mode
51 # none - no specific policy
52 # accept - always accept incoming connections
53 # master - become master on incoming connections,
54 # deny role switch on outgoing connections
55 lm accept;
56
57 # Default link policy
58 # none - no specific policy
59 # rswitch - allow role switch
60 # hold - allow hold mode
61 # sniff - allow sniff mode
62 # park - allow park mode
63 lp rswitch,hold,sniff,park;
64}
diff --git a/rootdir/etc/init.goldfish.rc b/rootdir/etc/init.goldfish.rc
index 5975974b0..96480f3e8 100644
--- a/rootdir/etc/init.goldfish.rc
+++ b/rootdir/etc/init.goldfish.rc
@@ -16,11 +16,11 @@ on boot
16 stop dund 16 stop dund
17 stop akmd 17 stop akmd
18 18
19 setprop app.setupwizard.disable 1 19 setprop ro.setupwizard.mode EMULATOR
20 20
21# enable Google-specific location features, 21# enable Google-specific location features,
22# like NetworkLocationProvider and LocationCollector 22# like NetworkLocationProvider and LocationCollector
23 setprop ro.com.google.enable_google_location_features 1 23 setprop ro.com.google.locationfeatures 1
24 24
25# For the emulator, which bypasses Setup Wizard, you can specify 25# For the emulator, which bypasses Setup Wizard, you can specify
26# account info for the device via these two properties. Google 26# account info for the device via these two properties. Google
@@ -39,8 +39,9 @@ service goldfish-setup /system/etc/init.goldfish.sh
39 oneshot 39 oneshot
40 40
41service qemud /system/bin/qemud 41service qemud /system/bin/qemud
42 socket qemud_gsm stream 666 42 socket qemud_gsm stream 666
43 socket qemud_gps stream 666 43 socket qemud_gps stream 666
44 socket qemud_control stream 666
44 oneshot 45 oneshot
45 46
46# -Q is a special logcat option that forces the 47# -Q is a special logcat option that forces the
diff --git a/rootdir/etc/mountd.conf b/rootdir/etc/mountd.conf
index d9dfdede3..094a2c7af 100644
--- a/rootdir/etc/mountd.conf
+++ b/rootdir/etc/mountd.conf
@@ -10,4 +10,10 @@ mount {
10 10
11 ## true if this mount point can be shared via USB mass storage 11 ## true if this mount point can be shared via USB mass storage
12 enable_ums true 12 enable_ums true
13
14 ## path to the UMS driver file for specifying the block device path
15 ## use this for the mass_storage function driver
16 driver_store_path /sys/devices/platform/usb_mass_storage/lun0/file
17 ## use this for android_usb composite gadget driver
18 ##driver_store_path /sys/devices/platform/msm_hsusb/gadget/lun0/file
13} 19}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 23daa0b00..3f8c6a01b 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -1,6 +1,8 @@
1 1
2on init 2on init
3 3
4sysclktz 0
5
4loglevel 3 6loglevel 3
5 7
6# setup the global environment 8# setup the global environment
@@ -118,6 +120,12 @@ on boot
118 chown radio system /sys/android_power/acquire_full_wake_lock 120 chown radio system /sys/android_power/acquire_full_wake_lock
119 chown radio system /sys/android_power/acquire_partial_wake_lock 121 chown radio system /sys/android_power/acquire_partial_wake_lock
120 chown radio system /sys/android_power/release_wake_lock 122 chown radio system /sys/android_power/release_wake_lock
123 chown radio system /sys/power/state
124 chown radio system /sys/power/wake_lock
125 chown radio system /sys/power/wake_unlock
126 chmod 0660 /sys/power/state
127 chmod 0660 /sys/power/wake_lock
128 chmod 0660 /sys/power/wake_unlock
121 chown system system /sys/class/timed_output/vibrator/enable 129 chown system system /sys/class/timed_output/vibrator/enable
122 chown system system /sys/class/leds/keyboard-backlight/brightness 130 chown system system /sys/class/leds/keyboard-backlight/brightness
123 chown system system /sys/class/leds/lcd-backlight/brightness 131 chown system system /sys/class/leds/lcd-backlight/brightness
@@ -193,6 +201,7 @@ service ril-daemon /system/bin/rild
193service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server 201service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
194 socket zygote stream 666 202 socket zygote stream 666
195 onrestart write /sys/android_power/request_state wake 203 onrestart write /sys/android_power/request_state wake
204 onrestart write /sys/power/state on
196 205
197service media /system/bin/mediaserver 206service media /system/bin/mediaserver
198 user media 207 user media
@@ -208,7 +217,8 @@ service dbus /system/bin/dbus-daemon --system --nofork
208 user bluetooth 217 user bluetooth
209 group bluetooth net_bt_admin 218 group bluetooth net_bt_admin
210 219
211service hcid /system/bin/hcid -s -n -f /etc/hcid.conf 220#STOPSHIP: disable the verbose logging
221service hcid /system/bin/logwrapper /system/bin/hcid -d -s -n -f /etc/bluez/hcid.conf
212 socket bluetooth stream 660 bluetooth bluetooth 222 socket bluetooth stream 660 bluetooth bluetooth
213 socket dbus_bluetooth stream 660 bluetooth bluetooth 223 socket dbus_bluetooth stream 660 bluetooth bluetooth
214 # init.rc does not yet support applying capabilities, so run as root and 224 # init.rc does not yet support applying capabilities, so run as root and
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index df8ba9fb6..b0c241e7d 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -83,3 +83,8 @@ $(SYMLINKS): $(LOCAL_INSTALLED_MODULE) $(LOCAL_PATH)/Android.mk
83 $(hide) ln -sf $(TOOLBOX_BINARY) $@ 83 $(hide) ln -sf $(TOOLBOX_BINARY) $@
84 84
85ALL_DEFAULT_INSTALLED_MODULES += $(SYMLINKS) 85ALL_DEFAULT_INSTALLED_MODULES += $(SYMLINKS)
86
87# We need this so that the installed files could be picked up based on the
88# local module name
89ALL_MODULES.$(LOCAL_MODULE).INSTALLED := \
90 $(ALL_MODULES.$(LOCAL_MODULE).INSTALLED) $(SYMLINKS)