diff options
author | The Android Open Source Project | 2008-12-17 20:08:08 -0600 |
---|---|---|
committer | The Android Open Source Project | 2008-12-17 20:08:08 -0600 |
commit | 35237d135807af84bf9b0e5b8d7f8633e58db6f5 (patch) | |
tree | d8bcf3ada2182d248604728285dd80abb466f22a | |
parent | 4f6e8d7a00cbeda1e70cc15be9c4af1018bdad53 (diff) | |
download | platform-system-core-35237d135807af84bf9b0e5b8d7f8633e58db6f5.tar.gz platform-system-core-35237d135807af84bf9b0e5b8d7f8633e58db6f5.tar.xz platform-system-core-35237d135807af84bf9b0e5b8d7f8633e58db6f5.zip |
Code drop from //branches/cupcake/...@124589
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)) |
20 | else | 20 | else |
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 | # ========================================================= |
10 | ifneq ($(TARGET_SIMULATOR),true) # not 64 bit clean (also unused with the sim) | ||
10 | include $(CLEAR_VARS) | 11 | include $(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 | ||
57 | ifneq ($(USE_SYSDEPS_WIN32),) | 59 | ifneq ($(USE_SYSDEPS_WIN32),) |
@@ -69,6 +71,8 @@ endif | |||
69 | 71 | ||
70 | include $(BUILD_HOST_EXECUTABLE) | 72 | include $(BUILD_HOST_EXECUTABLE) |
71 | 73 | ||
74 | $(call dist-for-goals,droid,$(LOCAL_BUILT_MODULE)) | ||
75 | |||
72 | ifeq ($(HOST_OS),windows) | 76 | ifeq ($(HOST_OS),windows) |
73 | $(LOCAL_INSTALLED_MODULE): $(HOST_OUT_EXECUTABLES)/AdbWinApi.dll | 77 | $(LOCAL_INSTALLED_MODULE): $(HOST_OUT_EXECUTABLES)/AdbWinApi.dll |
74 | endif | 78 | endif |
@@ -81,10 +85,25 @@ LOCAL_MODULE := kdbg | |||
81 | include $(BUILD_HOST_EXECUTABLE) | 85 | include $(BUILD_HOST_EXECUTABLE) |
82 | endif | 86 | endif |
83 | 87 | ||
88 | endif | ||
84 | 89 | ||
85 | # adbd device daemon | 90 | # adbd device daemon |
86 | # ========================================================= | 91 | # ========================================================= |
87 | ifeq ($(TARGET_ARCH),arm) | 92 | |
93 | # build adbd in all non-simulator builds | ||
94 | BUILD_ADBD := false | ||
95 | ifneq ($(TARGET_SIMULATOR),true) | ||
96 | BUILD_ADBD := true | ||
97 | endif | ||
98 | |||
99 | # build adbd for the Linux simulator build | ||
100 | # so we can use it to test the adb USB gadget driver on x86 | ||
101 | ifeq ($(HOST_OS),linux) | ||
102 | BUILD_ADBD := true | ||
103 | endif | ||
104 | |||
105 | |||
106 | ifeq ($(BUILD_ADBD),true) | ||
88 | include $(CLEAR_VARS) | 107 | include $(CLEAR_VARS) |
89 | 108 | ||
90 | LOCAL_SRC_FILES := \ | 109 | LOCAL_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 | 124 | LOCAL_CFLAGS := -O2 -g -DADB_HOST=0 -Wall -Wno-unused-parameter | |
105 | LOCAL_CFLAGS := -O2 -g -DADB_HOST=0 -DANDROID_GADGET=1 -Wall -Wno-unused-parameter | ||
106 | LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE | 125 | LOCAL_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. | ||
129 | ifeq ($(TARGET_ARCH),arm) | ||
130 | LOCAL_CFLAGS += -DANDROID_GADGET=1 | ||
131 | endif | ||
132 | |||
107 | LOCAL_MODULE := adbd | 133 | LOCAL_MODULE := adbd |
108 | 134 | ||
109 | LOCAL_FORCE_STATIC_EXECUTABLE := true | 135 | LOCAL_FORCE_STATIC_EXECUTABLE := true |
110 | LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN) | 136 | LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN) |
111 | LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED) | 137 | LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED) |
112 | 138 | ||
113 | LOCAL_STATIC_LIBRARIES := libcutils libc | 139 | ifeq ($(TARGET_SIMULATOR),true) |
140 | LOCAL_STATIC_LIBRARIES := libcutils | ||
141 | LOCAL_LDLIBS += -lpthread | ||
142 | include $(BUILD_HOST_EXECUTABLE) | ||
143 | else | ||
144 | LOCAL_STATIC_LIBRARIES := libcutils libc | ||
145 | include $(BUILD_EXECUTABLE) | ||
146 | endif | ||
114 | 147 | ||
115 | include $(BUILD_EXECUTABLE) | ||
116 | endif | 148 | endif |
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 @@ | |||
1 | Implementation notes regarding ADB. | ||
2 | |||
3 | I. General Overview: | ||
4 | |||
5 | The 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 | |||
14 | As 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 | |||
77 | II. 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 @@ | |||
1 | This file tries to document all requests a client can make | ||
2 | to the ADB server of an adbd daemon. See the OVERVIEW.TXT document | ||
3 | to understand what's going on here. | ||
4 | |||
5 | HOST SERVICES: | ||
6 | |||
7 | host: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 | |||
14 | host: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 | |||
19 | host: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 | |||
25 | host: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 | |||
33 | host: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 | |||
43 | host: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 | |||
49 | host: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 | |||
54 | host: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 | |||
59 | host: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 | |||
65 | host-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 | |||
71 | host-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 | |||
75 | host-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 | |||
79 | host:<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 | |||
117 | LOCAL SERVICES: | ||
118 | |||
119 | All the queries below assumed that you already switched the transport | ||
120 | to a real device, or that you have used a query prefix as described | ||
121 | above. | ||
122 | |||
123 | shell: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 | |||
132 | shell: | ||
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 | |||
138 | bootdebug: | ||
139 | Ask debugging information to the bootloader. The adbd daemon will | ||
140 | respond with FAIL to this request. | ||
141 | |||
142 | bootloader:<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 | |||
147 | remount: | ||
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 | |||
155 | dev:<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 | |||
161 | tcp:<port> | ||
162 | Tries to connect to tcp port <port> on localhost. | ||
163 | |||
164 | tcp:<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 | |||
169 | local:<path> | ||
170 | Tries to connect to a Unix domain socket <path> on the device | ||
171 | |||
172 | localreserved:<path> | ||
173 | localabstract:<path> | ||
174 | localfilesystem:<path> | ||
175 | Variants of local:<path> that are used to access other Android | ||
176 | socket namespaces. | ||
177 | |||
178 | log:<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 | |||
183 | framebuffer: | ||
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 | |||
205 | dns:<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 | |||
214 | recover:<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 | |||
226 | jdwp:<pid> | ||
227 | Connects to the JDWP thread running in the VM of process <pid>. | ||
228 | |||
229 | track-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 | |||
242 | sync: | ||
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 | ||
@@ -67,59 +67,59 @@ int adb_trace_mask; | |||
67 | */ | 67 | */ |
68 | void adb_trace_init(void) | 68 | void 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(); |
@@ -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 | */ |
311 | typedef enum { | 316 | typedef 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. */ |
516 | static char * | 516 | static char * |
517 | dupAndQuote(const char *s) | 517 | dupAndQuote(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 | ||
1313 | int uninstall_app(transport_type transport, char* serial, int argc, char** argv) | 1313 | int 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, ×tamp, &mode, &size)) | 708 | if(sync_finish_readtime(fd, ×tamp, &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 | ||
64 | done: | 65 | done: |
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 | ||
21 | void get_my_path(char exe[PATH_MAX]) | 21 | void 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 | */ | ||
57 | static asocket local_socket_closing_list = { | ||
58 | .next = &local_socket_closing_list, | ||
59 | .prev = &local_socket_closing_list, | ||
60 | }; | ||
61 | |||
53 | asocket *find_local_socket(unsigned id) | 62 | asocket *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 | ||
76 | static void | ||
77 | insert_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 | |||
67 | void install_local_socket(asocket *s) | 86 | void 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 | ||
180 | static void local_socket_close_locked(asocket *s) | 195 | // be sure to hold the socket list lock when calling this |
196 | static 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 | |||
216 | static 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 | |||
210 | static void local_socket_event_func(int fd, unsigned ev, void *_s) | 246 | static 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 | ||
975 | Exit: | 975 | Exit: |
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 | |||
991 | bip_buffer_read( BipBuffer bip, void* dst, int len ) | 991 | bip_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 | ||
1083 | typedef struct SocketPairRec_ | 1083 | typedef 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 | ||
1092 | void _fh_socketpair_init( FH f ) | 1092 | void _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) | |||
1587 | static void fdevent_unregister(fdevent *fde) | 1587 | static 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) | |||
1689 | void fdevent_set(fdevent *fde, unsigned events) | 1689 | void 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) | |||
1727 | void fdevent_loop() | 1727 | void 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 ) | |||
1793 | static void _event_socket_prepare( EventHook hook ) | 1793 | static 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 | ||
1896 | static void _event_socketpair_prepare( EventHook hook ) | 1896 | static 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) | |||
79 | static int remote_write(apacket *p, atransport *t) | 79 | static 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 | ¬ificationIterators[i]); | 112 | ¬ificationIterators[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 | |||
21 | char* | ||
22 | buff_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 | |||
39 | char* | ||
40 | buff_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 | |||
47 | char* | ||
48 | buff_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 | |||
71 | char* | ||
72 | buff_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 | */ | ||
45 | char* buff_addc (char* buff, char* buffEnd, int c); | ||
46 | |||
47 | /* tries to add a string to the buffer */ | ||
48 | char* 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 | */ | ||
53 | char* buff_addb (char* buff, char* buffEnd, const void* data, int len); | ||
54 | |||
55 | /* tries to add a formatted string to a bounded buffer */ | ||
56 | char* 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 | ||
11 | include $(BUILD_HOST_EXECUTABLE) | 11 | include $(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 | ||
3 | ifeq ($(TARGET_ARCH),arm) | ||
4 | |||
3 | LOCAL_PATH:= $(call my-dir) | 5 | LOCAL_PATH:= $(call my-dir) |
4 | include $(CLEAR_VARS) | 6 | include $(CLEAR_VARS) |
5 | 7 | ||
@@ -20,3 +22,5 @@ LOCAL_MODULE_TAGS := eng | |||
20 | #LOCAL_FORCE_STATIC_EXECUTABLE := true | 22 | #LOCAL_FORCE_STATIC_EXECUTABLE := true |
21 | LOCAL_SHARED_LIBRARIES := libcutils libc | 23 | LOCAL_SHARED_LIBRARIES := libcutils libc |
22 | include $(BUILD_EXECUTABLE) | 24 | include $(BUILD_EXECUTABLE) |
25 | |||
26 | endif # 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 */ |
384 | static _Unwind_Reason_Code log_function(_Unwind_Context *context, int tfd, | 384 | static _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 */ |
69 | const mapinfo *pc_to_mapinfo(mapinfo *mi, unsigned pc) | 70 | const 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); | |||
45 | extern void get_remote_struct(int pid, void *src, void *dst, size_t size); | 45 | extern 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 */ |
48 | const mapinfo *pc_to_mapinfo (mapinfo *mi, unsigned pc); | 48 | const 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 */ |
51 | const char *map_to_name(mapinfo *mi, unsigned pc, const char* def); | 51 | const 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 | |||
43 | LOCAL_STATIC_LIBRARIES := $(EXTRA_STATIC_LIBS) libzipfile libunz | 43 | LOCAL_STATIC_LIBRARIES := $(EXTRA_STATIC_LIBS) libzipfile libunz |
44 | 44 | ||
45 | include $(BUILD_HOST_EXECUTABLE) | 45 | include $(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 | ||
48 | ifeq ($(HOST_OS),linux) | 48 | ifeq ($(HOST_OS),linux) |
49 | include $(CLEAR_VARS) | 49 | include $(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; | |||
47 | static const char *product = 0; | 47 | static const char *product = 0; |
48 | static const char *cmdline = 0; | 48 | static const char *cmdline = 0; |
49 | static int wipe_data = 0; | 49 | static int wipe_data = 0; |
50 | static unsigned short vendor_id = 0; | ||
50 | 51 | ||
51 | void die(const char *fmt, ...) | 52 | void die(const char *fmt, ...) |
52 | { | 53 | { |
@@ -135,7 +136,8 @@ oops: | |||
135 | 136 | ||
136 | int match_fastboot(usb_ifc_info *info) | 137 | int 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" { | |||
24 | time_t mktime_tz(struct tm * const tmp, char const * tz); | 24 | time_t mktime_tz(struct tm * const tmp, char const * tz); |
25 | void localtime_tz(const time_t * const timep, struct tm * tmp, const char* tz); | 25 | void localtime_tz(const time_t * const timep, struct tm * tmp, const char* tz); |
26 | 26 | ||
27 | struct 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 | |||
40 | size_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 ) | |||
147 | GGL_RESERVE_NEEDS( P_RESERVED1, 10,22 ) | 147 | GGL_RESERVE_NEEDS( P_RESERVED1, 10,22 ) |
148 | 148 | ||
149 | GGL_RESERVE_NEEDS( T_FORMAT, 0, 6 ) | 149 | GGL_RESERVE_NEEDS( T_FORMAT, 0, 6 ) |
150 | GGL_RESERVE_NEEDS( T_RESERVED0, 6, 2 ) | 150 | GGL_RESERVE_NEEDS( T_RESERVED0, 6, 1 ) |
151 | GGL_RESERVE_NEEDS( T_POT, 7, 1 ) | ||
151 | GGL_RESERVE_NEEDS( T_S_WRAP, 8, 2 ) | 152 | GGL_RESERVE_NEEDS( T_S_WRAP, 8, 2 ) |
152 | GGL_RESERVE_NEEDS( T_T_WRAP, 10, 2 ) | 153 | GGL_RESERVE_NEEDS( T_T_WRAP, 10, 2 ) |
153 | GGL_RESERVE_NEEDS( T_ENV, 12, 2 ) | 154 | GGL_RESERVE_NEEDS( T_ENV, 12, 3 ) |
154 | GGL_RESERVE_NEEDS( T_POT, 14, 1 ) | ||
155 | GGL_RESERVE_NEEDS( T_LINEAR, 15, 1 ) | 155 | GGL_RESERVE_NEEDS( T_LINEAR, 15, 1 ) |
156 | 156 | ||
157 | const int GGL_NEEDS_WRAP_CLAMP_TO_EDGE = 0; | 157 | const 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 | ||
189 | inline uint32_t ggl_needs_to_env(uint32_t n) { | 190 | inline 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 @@ | |||
1 | this version of init contains code to perform "bootcharting", i.e. generating log | 1 | This version of init contains code to perform "bootcharting", i.e. generating log |
2 | files that can be later processed by the tools provided by www.bootchart.org. | 2 | files that can be later processed by the tools provided by www.bootchart.org. |
3 | 3 | ||
4 | to activate it, you need to define build 'init' with the INIT_BOOTCHART environment | 4 | To activate it, you need to define build 'init' with the INIT_BOOTCHART environment |
5 | variable defined to 'true', then create a file on the /data partition with a command | 5 | variable defined to 'true', for example: |
6 | like the following: | ||
7 | 6 | ||
8 | adb shell 'echo 1 > /data/bootchart' | 7 | touch system/init/init.c |
8 | m INIT_BOOTCHART=true | ||
9 | 9 | ||
10 | if the '/data/bootchart' file doesn't exist, or doesn't contain a '1' in its first | 10 | On the emulator, use the new -bootchart <timeout> option to boot with bootcharting |
11 | byte, init will proceed normally. | 11 | activated for <timeout> seconds. |
12 | 12 | ||
13 | by default, the bootchart log stops after 2 minutes, but you can stop it earlier | 13 | Otherwise, flash your device, and start it. Then create a file on the /data partition |
14 | with the following command while the device is booting: | 14 | with a command like the following: |
15 | |||
16 | adb shell 'echo $TIMEOUT > /data/bootchart-start' | ||
17 | |||
18 | Where the value of $TIMEOUT corresponds to the wanted bootcharted period in seconds; | ||
19 | for example, to bootchart for 2 minutes, do: | ||
20 | |||
21 | adb shell 'echo 120 > /data/bootchart-start' | ||
22 | |||
23 | Reboot your device, bootcharting will begin and stop after the period you gave. | ||
24 | You 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 | ||
18 | note that /data/bootchart-stop is deleted automatically by init at the end of the | 28 | Note that /data/bootchart-stop is deleted automatically by init at the end of the |
19 | bootcharting. this is not the case of /data/bootchart, so don't forget to delete it | 29 | bootcharting. This is not the case of /data/bootchart-start, so don't forget to delete it |
20 | when you're done collecting data: | 30 | when you're done collecting data: |
21 | 31 | ||
22 | adb shell rm /data/bootchart | 32 | adb shell rm /data/bootchart-start |
23 | 33 | ||
24 | the log files are placed in /tmp/bootchart/. you must run the script tools/grab-bootchart.sh | 34 | The log files are placed in /data/bootchart/. you must run the script tools/grab-bootchart.sh |
25 | which will use ADB to retrieve them and create a bootchart.tgz file that can be used with | 35 | which will use ADB to retrieve them and create a bootchart.tgz file that can be used with |
26 | the bootchart parser/renderer, or even uploaded directly to the form located at: | 36 | the 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 | ||
40 | NOTE: 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 | |||
30 | technical note: | 48 | technical note: |
31 | 49 | ||
32 | this implementation of bootcharting does use the 'bootchartd' script provided by | 50 | this 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 | ||
32 | static int | 49 | static 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 | ||
64 | typedef struct { | 80 | typedef 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 | |||
26 | extern int bootchart_init(void); | ||
27 | extern int bootchart_step(void); | ||
28 | extern 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 | ||
67 | static int insmod(const char *filename) | 67 | static 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 | |||
176 | static 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 | |||
175 | int do_insmod(int nargs, char **args) | 193 | int 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 | ||
180 | int do_import(int nargs, char **args) | 206 | int 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 | ||
355 | int 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 | |||
329 | int do_write(int nargs, char **args) | 369 | int 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 | |||
9 | rm -rf $TMPDIR | 9 | rm -rf $TMPDIR |
10 | mkdir -p $TMPDIR | 10 | mkdir -p $TMPDIR |
11 | 11 | ||
12 | LOGROOT=/tmp/bootchart | 12 | LOGROOT=/data/bootchart |
13 | TARBALL=bootchart.tgz | 13 | TARBALL=bootchart.tgz |
14 | 14 | ||
15 | FILES="header proc_stat.log proc_ps.log proc_diskstats.log kernel_pacct" | 15 | FILES="header proc_stat.log proc_ps.log proc_diskstats.log kernel_pacct" |
16 | 16 | ||
17 | for f in $FILES; do | 17 | for f in $FILES; do |
18 | adb pull $LOGROOT/$f $TMPDIR/$f &> /dev/null | 18 | adb pull $LOGROOT/$f $TMPDIR/$f 2>&1 > /dev/null |
19 | done | 19 | done |
20 | (cd $TMPDIR && tar -czf $TARBALL $FILES) | 20 | (cd $TMPDIR && tar -czf $TARBALL $FILES) |
21 | cp -f $TMPDIR/$TARBALL ./$TARBALL | 21 | cp -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 | ||
51 | static int property_triggers_enabled = 0; | 48 | static int property_triggers_enabled = 0; |
52 | 49 | ||
53 | #if BOOTCHART | 50 | #if BOOTCHART |
54 | static int bootchart_count; | 51 | static int bootchart_count; |
55 | extern int bootchart_init(void); | ||
56 | extern int bootchart_step(void); | ||
57 | extern 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 | ||
63 | static char console[32]; | 54 | static 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); | |||
19 | int do_stop(int nargs, char **args); | 19 | int do_stop(int nargs, char **args); |
20 | int do_trigger(int nargs, char **args); | 20 | int do_trigger(int nargs, char **args); |
21 | int do_symlink(int nargs, char **args); | 21 | int do_symlink(int nargs, char **args); |
22 | int do_sysclktz(int nargs, char **args); | ||
22 | int do_write(int nargs, char **args); | 23 | int do_write(int nargs, char **args); |
23 | int do_chown(int nargs, char **args); | 24 | int do_chown(int nargs, char **args); |
24 | int do_chmod(int nargs, char **args); | 25 | int 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> | |||
194 | symlink <target> <path> | 194 | symlink <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 | ||
197 | sysclktz <mins_west_of_gmt> | ||
198 | Set the system clock base (0 if system clock ticks in GMT) | ||
199 | |||
197 | trigger <event> | 200 | trigger <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 |
65 | endif | 66 | endif |
@@ -91,8 +92,14 @@ else #!sim | |||
91 | # ======================================================== | 92 | # ======================================================== |
92 | include $(CLEAR_VARS) | 93 | include $(CLEAR_VARS) |
93 | LOCAL_MODULE := libcutils | 94 | LOCAL_MODULE := libcutils |
94 | LOCAL_SRC_FILES := $(commonSources) memset32.S atomic-android-arm.S mq.c \ | 95 | LOCAL_SRC_FILES := $(commonSources) ashmem-dev.c mq.c |
95 | ashmem-dev.c | 96 | |
97 | ifeq ($(TARGET_ARCH),arm) | ||
98 | LOCAL_SRC_FILES += memset32.S atomic-android-arm.S | ||
99 | else # !arm | ||
100 | LOCAL_SRC_FILES += memory.c | ||
101 | endif # !arm | ||
102 | |||
96 | LOCAL_C_INCLUDES := $(KERNEL_HEADERS) | 103 | LOCAL_C_INCLUDES := $(KERNEL_HEADERS) |
97 | LOCAL_STATIC_LIBRARIES := liblog | 104 | LOCAL_STATIC_LIBRARIES := liblog |
98 | include $(BUILD_STATIC_LIBRARY) | 105 | include $(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: | |||
59 | 1: @ android_atomic_write | 61 | 1: @ 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: | |||
78 | 1: @ android_atomic_inc | 86 | 1: @ 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: | |||
99 | 1: @ android_atomic_dec | 114 | 1: @ 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: | |||
121 | 1: @ android_atomic_add | 143 | 1: @ 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: | |||
144 | 1: @ android_atomic_and | 173 | 1: @ 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: | |||
167 | 1: @ android_atomic_or | 204 | 1: @ 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 */ |
203 | 1: @ android_atomic_cmpxchg | 248 | 1: @ 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 | ||
3 | static 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 | ||
35 | static 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 | |||
43 | static char * _add P((const char *, char *, const char *, int)); | ||
44 | static char * _conv P((int, const char *, char *, const char *)); | ||
45 | static char * _fmt P((const char *, const struct tm *, char *, const char *, | ||
46 | int *, const struct strftime_locale *Locale)); | ||
47 | static char * _yconv P((int, int, int, int, char *, const char *, int)); | ||
48 | static char * getformat P((int, char *, char *, char *, char *)); | ||
49 | |||
50 | extern 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 | |||
94 | size_t | ||
95 | strftime_tz(s, maxsize, format, t, Locale) | ||
96 | char * const s; | ||
97 | const size_t maxsize; | ||
98 | const char * const format; | ||
99 | const struct tm * const t; | ||
100 | const 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 | |||
129 | static 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 | |||
145 | static char * | ||
146 | _fmt(format, t, pt, ptlim, warnp, Locale) | ||
147 | const char * format; | ||
148 | const struct tm * const t; | ||
149 | char * pt; | ||
150 | const char * const ptlim; | ||
151 | int * warnp; | ||
152 | const struct strftime_locale *Locale; | ||
153 | { | ||
154 | for ( ; *format; ++format) { | ||
155 | if (*format == '%') { | ||
156 | int modifier = 0; | ||
157 | label: | ||
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 | |||
612 | static char * | ||
613 | _conv(n, format, pt, ptlim) | ||
614 | const int n; | ||
615 | const char * const format; | ||
616 | char * const pt; | ||
617 | const 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 | |||
625 | static char * | ||
626 | _add(str, pt, ptlim, modifier) | ||
627 | const char * str; | ||
628 | char * pt; | ||
629 | const char * const ptlim; | ||
630 | int 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 | |||
677 | static char * | ||
678 | _yconv(a, b, convert_top, convert_yy, pt, ptlim, modifier) | ||
679 | const int a; | ||
680 | const int b; | ||
681 | const int convert_top; | ||
682 | const int convert_yy; | ||
683 | char * pt; | ||
684 | const char * const ptlim; | ||
685 | int 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 | ||
716 | static 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 | |||
825 | bad_lbuf: | ||
826 | free(lbuf); | ||
827 | bad_locale: | ||
828 | (void) close(fd); | ||
829 | no_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 | */ | ||
187 | int 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 | |||
184 | char *dhcp_get_errmsg() { | 200 | char *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) | |||
85 | LOCAL_WHOLE_STATIC_LIBRARIES := libpixelflinger_armv6 | 85 | LOCAL_WHOLE_STATIC_LIBRARIES := libpixelflinger_armv6 |
86 | endif | 86 | endif |
87 | include $(BUILD_STATIC_LIBRARY) | 87 | include $(BUILD_STATIC_LIBRARY) |
88 | |||
89 | |||
90 | include $(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 | ||
905 | void GGLAssembler::build_masking(pixel_t& pixel, Scratch& regs) | 919 | void 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) | |||
168 | void GGLAssembler::expand(component_t& d, const component_t& s, int dbits) | 168 | void 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 | ||
1208 | void 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 @@ | |||
21 | namespace android { | 21 | namespace android { |
22 | 22 | ||
23 | static GGLFormat const gPixelFormatInfos[] = | 23 | static 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 | // ---------------------------------------------------------------------------- |
62 | namespace android { | 64 | namespace 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 @@ | |||
1 | LOCAL_PATH:= $(call my-dir) | ||
2 | include $(CLEAR_VARS) | ||
3 | |||
4 | LOCAL_SRC_FILES:= \ | ||
5 | codegen.cpp | ||
6 | |||
7 | LOCAL_SHARED_LIBRARIES := \ | ||
8 | libcutils \ | ||
9 | libpixelflinger | ||
10 | |||
11 | LOCAL_MODULE:= test-opengl-codegen | ||
12 | |||
13 | LOCAL_MODULE_TAGS := tests | ||
14 | |||
15 | include $(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 | |||
4 | extern "C" void ggl_test_codegen( | ||
5 | uint32_t n, uint32_t p, uint32_t t0, uint32_t t1); | ||
6 | |||
7 | |||
8 | int 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 @@ | |||
244 | 50000 menu_item_selected (Menu type where 0 is options and 1 is context|1|5),(Menu item title|3) | 244 | 50000 menu_item_selected (Menu type where 0 is options and 1 is context|1|5),(Menu item title|3) |
245 | 50001 menu_opened (Menu type where 0 is options and 1 is context|1|5) | 245 | 50001 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) |
251 | 50020 connectivity_state_changed (custom|1|5) | 251 | 50020 connectivity_state_changed (custom|1|5) |
@@ -271,8 +271,9 @@ | |||
271 | 50024 wifi_interface_configuration_state_changed (IP_configuration|1|5) | 271 | 50024 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) | ||
276 | 50025 wifi_supplicant_connection_state_changed (connected|1|5) | 277 | 50025 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. |
292 | 50104 pdp_reregister_network (out_packet_count|1|1) | 293 | 50104 pdp_reregister_network (out_packet_count|1|1) |
293 | 294 | ||
295 | # PDP Setup failures | ||
296 | 50105 pdp_setup_fail (cause|1|5), (cid|1|5), (network_type|1|5) | ||
297 | |||
298 | # Call drops | ||
299 | 50106 call_drop (cause|1|5), (cid|1|5), (network_type|1|5) | ||
300 | |||
301 | # Data network registration failed after successful voice registration | ||
302 | 50107 data_network_registration_fail (op_numeric|1|5), (cid|1|5) | ||
303 | |||
304 | # Suspicious status of data connection while radio poweroff | ||
305 | 50108 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 | ||
27 | void fatal(const char *msg) { | 29 | void fatal(const char *msg) { |
@@ -32,48 +34,74 @@ void fatal(const char *msg) { | |||
32 | 34 | ||
33 | void usage() { | 35 | void 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 | ||
42 | void parent(const char *tag, int parent_read) { | 47 | void 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 | ||
79 | void child(int argc, char* argv[]) { | 107 | void child(int argc, char* argv[]) { |
@@ -91,35 +119,62 @@ void child(int argc, char* argv[]) { | |||
91 | 119 | ||
92 | int main(int argc, char* argv[]) { | 120 | int 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 | ||
9 | include $(BUILD_HOST_EXECUTABLE) | 9 | include $(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 | |||
46 | extern int init_module(void *, unsigned long, const char *); | ||
47 | extern int delete_module(const char *, unsigned int); | ||
48 | |||
49 | struct 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 | |||
66 | static 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 }; | ||
71 | static const char KEY_PATH[] = "/data/system/asec.key"; | ||
72 | static const char MODULE_PATH[] = "/system/lib/modules"; | ||
73 | static const char MKE2FS_PATH[] = "/system/bin/mke2fs"; | ||
74 | static const char E2FSCK_PATH[] = "/system/bin/e2fsck"; | ||
75 | |||
76 | boolean AsecIsStarted(void *Handle) | ||
77 | { | ||
78 | struct asec_context *ctx = (struct asec_context *) Handle; | ||
79 | |||
80 | return ctx->started; | ||
81 | } | ||
82 | |||
83 | const char *AsecMountPoint(void *Handle) | ||
84 | { | ||
85 | struct asec_context *ctx = (struct asec_context *) Handle; | ||
86 | |||
87 | return ctx->dstPath; | ||
88 | } | ||
89 | |||
90 | static 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 | |||
102 | void *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 | |||
135 | void 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 | |||
148 | static 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 | |||
176 | static 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 | |||
200 | static 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 | |||
208 | static 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 | |||
236 | static 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 | |||
263 | static 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 | |||
296 | static 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 | |||
349 | static void AsecCloseCache(struct asec_context *ctx) | ||
350 | { | ||
351 | close(ctx->cacheFd); | ||
352 | } | ||
353 | |||
354 | static 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 | |||
361 | static 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 | |||
426 | static 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 | |||
441 | static 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 | |||
494 | out_free: | ||
495 | free (io); | ||
496 | out_nofree: | ||
497 | close (dmFd); | ||
498 | return rc; | ||
499 | } | ||
500 | |||
501 | static 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 | |||
524 | out_free: | ||
525 | free (io); | ||
526 | out_nofree: | ||
527 | close (dmFd); | ||
528 | return rc; | ||
529 | } | ||
530 | |||
531 | static 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 | |||
551 | static 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 | |||
565 | static 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 | |||
595 | static 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 | |||
622 | static 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 | |||
644 | int 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 | |||
725 | int 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 | |||
7 | typedef 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 | ||
11 | LOCAL_MODULE:= mountd | 12 | LOCAL_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) |
102 | static MountPoint* sMountPointList = NULL; | 105 | static MountPoint* sMountPointList = NULL; |
103 | static int sNextLun = 0; | ||
104 | boolean gMassStorageEnabled = false; | 106 | boolean gMassStorageEnabled = false; |
105 | boolean gMassStorageConnected = false; | 107 | boolean gMassStorageConnected = false; |
106 | 108 | ||
107 | static pthread_t sAutoMountThread = 0; | 109 | static pthread_t sAutoMountThread = 0; |
110 | static pid_t gExcludedPids[2] = {-1, -1}; | ||
111 | |||
112 | static 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 |
110 | static int sRetriesPending = 0; | 115 | static 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. |
117 | static void SetBackingStore(MountPoint* mp, boolean enable) | 122 | static 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 | ||
203 | static 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 | |||
195 | static int DoMountDevice(const char* device, const char* mountPoint) | 253 | static 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 | ||
270 | static int DoUnmountDevice(const char* mountPoint) | 357 | static 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) | |||
829 | void MountMedia(const char* mountPoint) | 944 | void 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 | ||
886 | void AddMountPoint(const char* device, const char* mountPoint, boolean enableUms) | 1003 | void *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 | ||
1024 | int 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 | } | ||
907 | static void MountDevices() | 1045 | static void MountDevices() |
908 | { | 1046 | { |
909 | MountPoint* mp = sMountPointList; | 1047 | MountPoint* mp = sMountPointList; |
@@ -916,6 +1054,8 @@ static void MountDevices() | |||
916 | 1054 | ||
917 | void StartAutoMounter() | 1055 | void 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 |
180 | void KillProcessesWithOpenFiles(const char* mountPoint, boolean sigkill) | 180 | void 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 |
44 | static char* sDeferredUnmountableMediaPath = NULL; | 45 | static char* sDeferredUnmountableMediaPath = NULL; |
45 | 46 | ||
47 | // last asec msg before the runtime was connected | ||
48 | static char* sAsecDeferredMessage = NULL; | ||
49 | static char* sAsecDeferredArgument = NULL; | ||
50 | |||
46 | static int Write(const char* message) | 51 | static 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 | ||
216 | void 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 | |||
190 | void NotifyMediaState(const char* path, MediaState state, boolean readOnly) | 271 | void 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 | */ | ||
103 | struct 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 | */ | ||
143 | struct 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 | */ | ||
172 | struct 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 | */ | ||
181 | struct 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 | */ | ||
191 | struct 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 | */ | ||
201 | struct 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 | */ | ||
211 | enum { | ||
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 @@ | |||
39 | FILE* logFile; | 39 | FILE* logFile; |
40 | #endif | 40 | #endif |
41 | 41 | ||
42 | struct 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 | |||
50 | static 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 | ||
43 | static void ReadConfigFile(const char* path) | 91 | static 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 | |||
23 | typedef int boolean; | 25 | typedef int boolean; |
24 | enum { | 26 | enum { |
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 | ||
63 | typedef enum MediaState { | 78 | typedef 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); | |||
135 | void EnableMassStorage(boolean enable); | 150 | void 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 |
138 | void AddMountPoint(const char* device, const char* mountPoint, boolean enableUms); | 153 | void *AddMountPoint(const char* device, const char* mountPoint, const char* driverStorePath, |
154 | boolean enableUms); | ||
155 | |||
156 | int 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 |
141 | void StartAutoMounter(); | 160 | void StartAutoMounter(); |
@@ -144,9 +163,19 @@ void StartAutoMounter(); | |||
144 | void NotifyExistingMounts(); | 163 | void NotifyExistingMounts(); |
145 | 164 | ||
146 | 165 | ||
166 | // ASEC.c | ||
167 | |||
168 | void *AsecInit(const char *Name, const char *SrcPath, const char *BackingFile, | ||
169 | const char *Size, const char *DstPath, const char *Crypt); | ||
170 | int AsecStart(void *Handle); | ||
171 | int AsecStop(void *Handle); | ||
172 | void AsecDeinit(void *Handle); | ||
173 | boolean AsecIsStarted(void *Handle); | ||
174 | const char *AsecMountPoint(void *Handle); | ||
175 | |||
147 | // ProcessKiller.c | 176 | // ProcessKiller.c |
148 | 177 | ||
149 | void KillProcessesWithOpenFiles(const char* mountPoint, boolean sigkill); | 178 | void 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(); | |||
155 | void SendMassStorageConnected(boolean connected); | 184 | void SendMassStorageConnected(boolean connected); |
156 | void SendUnmountRequest(const char* path); | 185 | void SendUnmountRequest(const char* path); |
157 | void NotifyMediaState(const char* path, MediaState state, boolean readOnly); | 186 | void NotifyMediaState(const char* path, MediaState state, boolean readOnly); |
158 | 187 | void 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 | ||
13 | dont_copy := \ | 12 | dont_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. | ||
31 | ifneq ($(TARGET_PROVIDES_INIT_RC),true) | ||
31 | file := $(TARGET_ROOT_OUT)/init.rc | 32 | file := $(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) |
34 | ALL_PREBUILT += $(file) | 35 | ALL_PREBUILT += $(file) |
36 | endif | ||
35 | 37 | ||
36 | file := $(TARGET_ROOT_OUT)/init.goldfish.rc | 38 | file := $(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 | ||
6 | options { | ||
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 | ||
25 | device { | ||
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 | ||
41 | service qemud /system/bin/qemud | 41 | service 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 | ||
2 | on init | 2 | on init |
3 | 3 | ||
4 | sysclktz 0 | ||
5 | |||
4 | loglevel 3 | 6 | loglevel 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 | |||
193 | service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server | 201 | service 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 | ||
197 | service media /system/bin/mediaserver | 206 | service 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 | ||
211 | service hcid /system/bin/hcid -s -n -f /etc/hcid.conf | 220 | #STOPSHIP: disable the verbose logging |
221 | service 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 | ||
85 | ALL_DEFAULT_INSTALLED_MODULES += $(SYMLINKS) | 85 | ALL_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 | ||
89 | ALL_MODULES.$(LOCAL_MODULE).INSTALLED := \ | ||
90 | $(ALL_MODULES.$(LOCAL_MODULE).INSTALLED) $(SYMLINKS) | ||