Merge "Remove more simulator support code. Bug: 5010576"

This commit is contained in:
Jeff Brown 2011-07-11 13:41:26 -07:00 committed by Android (Google) Code Review
commit 716c2e5ce9
8 changed files with 0 additions and 1190 deletions

View File

@ -1,30 +0,0 @@
ifeq ($(TARGET_SIMULATOR),true)
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
ServiceManager.cpp \
SignalHandler.cpp \
main_runtime.cpp
LOCAL_SHARED_LIBRARIES := \
libutils \
libbinder \
libandroid_runtime \
libcutils \
libui \
libsystem_server \
libhardware_legacy
LOCAL_C_INCLUDES := \
$(JNI_H_INCLUDE)
ifeq ($(TARGET_OS),linux)
LOCAL_CFLAGS += -DXP_UNIX
endif
LOCAL_MODULE:= runtime
include $(BUILD_EXECUTABLE)
endif

View File

@ -1,190 +0,0 @@
Copyright (c) 2005-2008, The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

View File

@ -1,74 +0,0 @@
//
// Copyright 2005 The Android Open Source Project
//
#define LOG_TAG "ServiceManager"
#include "ServiceManager.h"
#include "SignalHandler.h"
#include <utils/Debug.h>
#include <utils/Log.h>
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <binder/ProcessState.h>
#include <private/utils/Static.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
namespace android {
BServiceManager::BServiceManager()
{
}
sp<IBinder> BServiceManager::getService(const String16& name) const
{
AutoMutex _l(mLock);
ssize_t i = mServices.indexOfKey(name);
LOGV("ServiceManager: getService(%s) -> %d\n", String8(name).string(), i);
if (i >= 0) return mServices.valueAt(i);
return NULL;
}
sp<IBinder> BServiceManager::checkService(const String16& name) const
{
AutoMutex _l(mLock);
ssize_t i = mServices.indexOfKey(name);
LOGV("ServiceManager: getService(%s) -> %d\n", String8(name).string(), i);
if (i >= 0) return mServices.valueAt(i);
return NULL;
}
status_t BServiceManager::addService(const String16& name, const sp<IBinder>& service)
{
AutoMutex _l(mLock);
LOGI("ServiceManager: addService(%s, %p)\n", String8(name).string(), service.get());
const ssize_t res = mServices.add(name, service);
if (res >= NO_ERROR) {
mChanged.broadcast();
return NO_ERROR;
}
return res;
}
Vector<String16> BServiceManager::listServices()
{
Vector<String16> res;
AutoMutex _l(mLock);
const size_t N = mServices.size();
for (size_t i=0; i<N; i++) {
res.add(mServices.keyAt(i));
}
return res;
}
}; // namespace android

View File

@ -1,38 +0,0 @@
//
// Copyright 2005 The Android Open Source Project
//
#ifndef ANDROID_SERVICE_MANAGER_H
#define ANDROID_SERVICE_MANAGER_H
#include <binder/IServiceManager.h>
#include <utils/KeyedVector.h>
#include <utils/threads.h>
namespace android {
// ----------------------------------------------------------------------
class BServiceManager : public BnServiceManager
{
public:
BServiceManager();
virtual sp<IBinder> getService( const String16& name) const;
virtual sp<IBinder> checkService( const String16& name) const;
virtual status_t addService( const String16& name,
const sp<IBinder>& service);
virtual Vector<String16> listServices();
private:
mutable Mutex mLock;
mutable Condition mChanged;
sp<IPermissionController> mPermissionController;
KeyedVector<String16, sp<IBinder> > mServices;
};
// ----------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_SERVICE_MANAGER_H

View File

@ -1,249 +0,0 @@
//
// Copyright 2005 The Android Open Source Project
//
#define LOG_TAG "SignalHandler"
#include "SignalHandler.h"
#include <utils/Atomic.h>
#include <utils/Debug.h>
#include <utils/Log.h>
#include <errno.h>
#include <sys/wait.h>
#include <unistd.h>
namespace android {
class SignalHandler::ProcessThread : public Thread
{
public:
ProcessThread(SignalHandler& sh)
: Thread(false)
, mOwner(sh)
{
}
virtual bool threadLoop()
{
char buffer[32];
read(mOwner.mAvailMsg[0], buffer, sizeof(buffer));
LOGV("Signal command processing thread woke up!");
if (mOwner.mLostCommands) {
LOGE("Lost %d signals!", mOwner.mLostCommands);
mOwner.mLostCommands = 0;
}
int cur;
while ((cur=mOwner.mCommandBottom) != mOwner.mCommandTop) {
if (mOwner.mCommands[cur].filled == 0) {
LOGV("Command at %d is not yet filled", cur);
break;
}
LOGV("Processing command at %d, top is %d",
cur, mOwner.mCommandTop);
processCommand(mOwner.mCommands[cur]);
mOwner.mCommands[cur].filled = 0;
int next = mOwner.mCommandBottom+1;
if (next >= COMMAND_QUEUE_SIZE) {
next = 0;
}
mOwner.mCommandBottom = next;
}
return true;
}
void processCommand(const CommandEntry& entry)
{
switch (entry.signum) {
case SIGCHLD: {
mOwner.mLock.lock();
ssize_t i = mOwner.mChildHandlers.indexOfKey(entry.info.si_pid);
ChildHandler ch;
if (i >= 0) {
ch = mOwner.mChildHandlers.valueAt(i);
mOwner.mChildHandlers.removeItemsAt(i);
}
mOwner.mLock.unlock();
LOGD("SIGCHLD: pid=%d, handle index=%d", entry.info.si_pid, i);
if (i >= 0) {
int res = waitpid(entry.info.si_pid, NULL, WNOHANG);
LOGW_IF(res == 0,
"Received SIGCHLD, but pid %d is not yet stopped",
entry.info.si_pid);
if (ch.handler) {
ch.handler(entry.info.si_pid, ch.userData);
}
} else {
LOGW("Unhandled SIGCHLD for pid %d", entry.info.si_pid);
}
} break;
}
}
SignalHandler& mOwner;
};
Mutex SignalHandler::mInstanceLock;
SignalHandler* SignalHandler::mInstance = NULL;
status_t SignalHandler::setChildHandler(pid_t childPid,
int tag,
child_callback_t handler,
void* userData)
{
SignalHandler* const self = getInstance();
self->mLock.lock();
// First make sure this child hasn't already exited.
pid_t res = waitpid(childPid, NULL, WNOHANG);
if (res != 0) {
if (res < 0) {
LOGW("setChildHandler waitpid of %d failed: %d (%s)",
childPid, res, strerror(errno));
} else {
LOGW("setChildHandler waitpid of %d said %d already dead",
childPid, res);
}
// Some kind of error... just handle the exit now.
self->mLock.unlock();
if (handler) {
handler(childPid, userData);
}
// Return an error code -- 0 means it already exited.
return (status_t)res;
}
ChildHandler entry;
entry.childPid = childPid;
entry.tag = tag;
entry.handler = handler;
entry.userData = userData;
// Note: this replaces an existing entry for this pid, if there already
// is one. This is the required behavior.
LOGD("setChildHandler adding pid %d, tag %d, handler %p, data %p",
childPid, tag, handler, userData);
self->mChildHandlers.add(childPid, entry);
self->mLock.unlock();
return NO_ERROR;
}
void SignalHandler::killAllChildren(int tag)
{
SignalHandler* const self = getInstance();
AutoMutex _l (self->mLock);
const size_t N = self->mChildHandlers.size();
for (size_t i=0; i<N; i++) {
const ChildHandler& ch(self->mChildHandlers.valueAt(i));
if (tag == 0 || ch.tag == tag) {
const pid_t pid = ch.childPid;
LOGI("Killing child %d (tag %d)\n", pid, ch.tag);
kill(pid, SIGKILL);
}
}
}
SignalHandler::SignalHandler()
: mCommandTop(0)
, mCommandBottom(0)
, mLostCommands(0)
{
memset(mCommands, 0, sizeof(mCommands));
int res = pipe(mAvailMsg);
LOGE_IF(res != 0, "Unable to create signal handler pipe: %s", strerror(errno));
mProcessThread = new ProcessThread(*this);
mProcessThread->run("SignalHandler", PRIORITY_HIGHEST);
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = sigAction;
sa.sa_flags = SA_NOCLDSTOP|SA_SIGINFO;
sigaction(SIGCHLD, &sa, NULL);
}
SignalHandler::~SignalHandler()
{
}
SignalHandler* SignalHandler::getInstance()
{
AutoMutex _l(mInstanceLock);
if (mInstance == NULL) {
mInstance = new SignalHandler();
}
return mInstance;
}
void SignalHandler::sigAction(int signum, siginfo_t* info, void*)
{
static const char wakeupMsg[1] = { 0xff };
// If our signal handler is being called, then we know we have
// already initialized the SignalHandler class and thus mInstance
// is valid.
SignalHandler* const self = mInstance;
// XXX This is not safe!
#if 0
LOGV("Signal %d: signo=%d, errno=%d, code=%d, pid=%d\n",
signum,
info->si_signo, info->si_errno, info->si_code,
info->si_pid);
#endif
int32_t oldTop, newTop;
// Find the next command slot...
do {
oldTop = self->mCommandTop;
newTop = oldTop + 1;
if (newTop >= COMMAND_QUEUE_SIZE) {
newTop = 0;
}
if (newTop == self->mCommandBottom) {
// The buffer is filled up! Ouch!
// XXX This is not safe!
#if 0
LOGE("Command buffer overflow! newTop=%d\n", newTop);
#endif
android_atomic_add(1, &self->mLostCommands);
write(self->mAvailMsg[1], wakeupMsg, sizeof(wakeupMsg));
return;
}
} while(android_atomic_cmpxchg(oldTop, newTop, &(self->mCommandTop)));
// Fill in the command data...
self->mCommands[oldTop].signum = signum;
self->mCommands[oldTop].info = *info;
// And now make this command available.
self->mCommands[oldTop].filled = 1;
// Wake up the processing thread.
write(self->mAvailMsg[1], wakeupMsg, sizeof(wakeupMsg));
}
}; // namespace android

View File

@ -1,137 +0,0 @@
//
// Copyright 2005 The Android Open Source Project
//
#ifndef ANDROID_SIGNAL_HANDLER_H
#define ANDROID_SIGNAL_HANDLER_H
#include <utils/KeyedVector.h>
#include <utils/threads.h>
#include <signal.h>
namespace android {
// ----------------------------------------------------------------------
enum {
DEFAULT_PROCESS_TAG = 1
};
class SignalHandler
{
public:
typedef void (*child_callback_t)(pid_t child, void* userData);
/**
* Set a handler for when a child process exits. By calling
* this, a waitpid() will be done when the child exits to remove
* it from the zombie state. You can also optionally specify a
* handler to be called when the child exits.
*
* If there is already a handler for this child process, it is
* replaced by this new handler. In this case the old handler's
* function is not called.
*
* @param childPid Process ID of child to watch.
* @param childTag User-defined tag for this child. Must be
* greater than zero.
* @param handler If non-NULL, this will be called when the
* child exits. It may be called in either a
* separate signal handling thread, or
* immediately if the child has already exited.
* @param userData Propageted as-is to handler.
*
* @return status_t NO_ERROR if all is well.
*/
static status_t setChildHandler(pid_t childPid,
int childTag = DEFAULT_PROCESS_TAG,
child_callback_t handler = NULL,
void* userData = NULL);
/**
* Kill all of the child processes for which we have a waiting
* handler, whose tag is the given value. If tag is 0, all
* children are killed.
*
* @param tag
*/
static void killAllChildren(int tag = 0);
private:
SignalHandler();
~SignalHandler();
static SignalHandler* getInstance();
static void sigAction(int, siginfo_t*, void*);
// --------------------------------------------------
// Shared state... all of this is protected by mLock.
// --------------------------------------------------
mutable Mutex mLock;
struct ChildHandler
{
pid_t childPid;
int tag;
child_callback_t handler;
void* userData;
};
KeyedVector<pid_t, ChildHandler> mChildHandlers;
// --------------------------------------------------
// Commmand queue... data is inserted by the signal
// handler using atomic ops, and retrieved by the
// signal processing thread. Because these are touched
// by the signal handler, no lock is used.
// --------------------------------------------------
enum {
COMMAND_QUEUE_SIZE = 64
};
struct CommandEntry
{
int filled;
int signum;
siginfo_t info;
};
// The top of the queue. This is incremented atomically by the
// signal handler before placing a command in the queue.
volatile int32_t mCommandTop;
// The bottom of the queue. Only modified by the processing
// thread; the signal handler reads it only to determine if the
// queue is full.
int32_t mCommandBottom;
// Incremented each time we receive a signal and don't have room
// for it on the command queue.
volatile int32_t mLostCommands;
// The command processing thread.
class ProcessThread;
sp<Thread> mProcessThread;
// Pipe used to tell command processing thread when new commands.
// are available. The thread blocks on the read end, the signal
// handler writes when it enqueues new commands.
int mAvailMsg[2];
// The commands.
CommandEntry mCommands[COMMAND_QUEUE_SIZE];
// --------------------------------------------------
// Singleton.
// --------------------------------------------------
static Mutex mInstanceLock;
static SignalHandler* mInstance;
};
// ----------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_SIGNAL_HANDLER_H

View File

@ -1,472 +0,0 @@
//
// Copyright 2005 The Android Open Source Project
//
// Main entry point for runtime.
//
#include "ServiceManager.h"
#include "SignalHandler.h"
#include <utils/threads.h>
#include <utils/Errors.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <utils/Log.h>
#include <cutils/zygote.h>
#include <cutils/properties.h>
#include <private/utils/Static.h>
#include <surfaceflinger/ISurfaceComposer.h>
#include <android_runtime/AndroidRuntime.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <getopt.h>
#include <signal.h>
#include <errno.h>
#include <sys/stat.h>
#include <linux/capability.h>
#include <linux/ioctl.h>
#ifdef HAVE_ANDROID_OS
# include <linux/android_alarm.h>
#endif
#undef LOG_TAG
#define LOG_TAG "runtime"
static const char* ZYGOTE_ARGV[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,3001,3002,3003",
/* CAP_SYS_TTY_CONFIG & CAP_SYS_RESOURCE & CAP_NET_BROADCAST &
* CAP_NET_ADMIN & CAP_NET_RAW & CAP_NET_BIND_SERVICE & CAP_KILL &
* CAP_SYS_BOOT CAP_SYS_NICE
*/
"--capabilities=96549920,96549920",
"--runtime-init",
"--nice-name=system_server",
"com.android.server.SystemServer"
};
using namespace android;
extern "C" status_t system_init();
enum {
SYSTEM_PROCESS_TAG = DEFAULT_PROCESS_TAG+1
};
extern Mutex gEventQMutex;
extern Condition gEventQCondition;
namespace android {
extern void set_finish_init_func(void (*func)());
/**
* This class is used to kill this process (runtime) when the system_server dies.
*/
class GrimReaper : public IBinder::DeathRecipient {
public:
GrimReaper() { }
virtual void binderDied(const wp<IBinder>& who)
{
LOGI("Grim Reaper killing runtime...");
kill(getpid(), SIGKILL);
}
};
extern void QuickTests();
/*
* Print usage info.
*/
static void usage(const char* argv0)
{
fprintf(stderr,
"Usage: runtime [-g gamma] [-l logfile] [-n]\n"
" [-j app-component] [-v app-verb] [-d app-data]\n"
"\n"
"-l: File to send log messages to\n"
"-n: Don't print to stdout/stderr\n"
"-j: Custom home app component name\n"
"-v: Custom home app intent verb\n"
"-d: Custom home app intent data\n"
);
exit(1);
}
// Selected application to run.
static const char* gInitialApplication = NULL;
static const char* gInitialVerb = NULL;
static const char* gInitialData = NULL;
static void writeStringToParcel(Parcel& parcel, const char* str)
{
if (str) {
parcel.writeString16(String16(str));
} else {
parcel.writeString16(NULL, 0);
}
}
/*
* Starting point for program logic.
*
* Returns with an exit status code (0 on success, nonzero on error).
*/
static int run(sp<ProcessState>& proc)
{
// Temporary hack to call startRunning() on the activity manager.
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> am;
while ((am = sm->getService(String16("activity"))) == NULL) {
LOGI("Waiting for activity manager...");
}
Parcel data, reply;
// XXX Need to also supply a package name for this to work again.
// IActivityManager::getInterfaceDescriptor() is the token for invoking on this interface;
// hardcoding it here avoids having to link with the full Activity Manager library
data.writeInterfaceToken(String16("android.app.IActivityManager"));
writeStringToParcel(data, NULL);
writeStringToParcel(data, gInitialApplication);
writeStringToParcel(data, gInitialVerb);
writeStringToParcel(data, gInitialData);
LOGI("run() sending FIRST_CALL_TRANSACTION to activity manager");
am->transact(IBinder::FIRST_CALL_TRANSACTION, data, &reply);
// Now we link to the Activity Manager waiting for it to die. If it does kill ourself.
// initd will restart this process and bring the system back up.
sp<GrimReaper> grim = new GrimReaper();
am->linkToDeath(grim, grim.get(), 0);
// Now join the thread pool. Note this is needed so that the message enqueued in the driver
// for the linkToDeath gets processed.
IPCThreadState::self()->joinThreadPool();
return 1;
}
}; // namespace android
/*
* Post-system-process initialization.
*
* This function continues initialization after the system process
* has been initialized. It needs to be separate because the system
* initialization needs to care of starting the Android runtime if it is not
* running in its own process, which doesn't return until the runtime is
* being shut down. So it will call back to here from inside of Dalvik,
* to allow us to continue booting up.
*/
static void finish_system_init(sp<ProcessState>& proc)
{
proc->startThreadPool();
}
// This function can be used to enforce security to different
// root contexts. For now, we just give every access.
static bool contextChecker(
const String16& name, const sp<IBinder>& caller, void* userData)
{
return true;
}
/*
* Initialization of boot services.
*
* This is where we perform initialization of all of our low-level
* boot services. Most importantly, here we become the context
* manager and use that to publish the service manager that will provide
* access to all other services.
*/
static void boot_init()
{
LOGI("Entered boot_init()!\n");
sp<ProcessState> proc(ProcessState::self());
LOGD("ProcessState: %p\n", proc.get());
proc->becomeContextManager(contextChecker, NULL);
LOGI("Binder driver opened.\n");
sp<BServiceManager> sm = new BServiceManager;
proc->setContextObject(sm);
}
/*
* Redirect stdin/stdout/stderr to /dev/null.
*/
static void redirectStdFds(void)
{
int fd = open("/dev/null", O_RDWR, 0);
if (fd < 0) {
LOGW("Unable to open /dev/null: %s\n", strerror(errno));
} else {
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
close(fd);
}
}
static int hasDir(const char* dir)
{
struct stat s;
int res = stat(dir, &s);
if (res == 0) {
return S_ISDIR(s.st_mode);
}
return 0;
}
static void validateTime()
{
#if HAVE_ANDROID_OS
int fd;
int res;
time_t min_time = 1167652800; // jan 1 2007, type 'date -ud "1/1 12:00" +%s' to get value for current year
struct timespec ts;
fd = open("/dev/alarm", O_RDWR);
if(fd < 0) {
LOGW("Unable to open alarm driver: %s\n", strerror(errno));
return;
}
res = ioctl(fd, ANDROID_ALARM_GET_TIME(ANDROID_ALARM_RTC_WAKEUP), &ts);
if(res < 0) {
LOGW("Unable to read rtc, %s\n", strerror(errno));
}
else if(ts.tv_sec >= min_time) {
goto done;
}
LOGW("Invalid time detected, %ld set to %ld\n", ts.tv_sec, min_time);
ts.tv_sec = min_time;
ts.tv_nsec = 0;
res = ioctl(fd, ANDROID_ALARM_SET_RTC, &ts);
if(res < 0) {
LOGW("Unable to set rtc to %ld: %s\n", ts.tv_sec, strerror(errno));
}
done:
close(fd);
#endif
}
#ifndef HAVE_ANDROID_OS
class QuickRuntime : public AndroidRuntime
{
public:
QuickRuntime() {}
virtual void onStarted()
{
printf("QuickRuntime: onStarted\n");
}
};
#endif
static status_t start_process(const char* name);
static void restart_me(pid_t child, void* userData)
{
start_process((const char*)userData);
}
static status_t start_process(const char* name)
{
String8 path(name);
Vector<const char*> args;
String8 leaf(path.getPathLeaf());
String8 parentDir(path.getPathDir());
args.insertAt(leaf.string(), 0);
args.add(parentDir.string());
args.add(NULL);
pid_t child = fork();
if (child < 0) {
status_t err = errno;
LOGE("*** fork of child %s failed: %s", leaf.string(), strerror(err));
return -errno;
} else if (child == 0) {
LOGI("Executing: %s", path.string());
execv(path.string(), const_cast<char**>(args.array()));
int err = errno;
LOGE("Exec failed: %s\n", strerror(err));
_exit(err);
} else {
SignalHandler::setChildHandler(child, DEFAULT_PROCESS_TAG,
restart_me, (void*)name);
}
return -errno;
}
/*
* Application entry point.
*
* Parse arguments, set some values, and pass control off to Run().
*
* This is redefined to "SDL_main" on SDL simulator builds, and
* "runtime_main" on wxWidgets builds.
*/
extern "C"
int main(int argc, char* const argv[])
{
const char* logFile = NULL;
int ic;
int result = 1;
pid_t systemPid;
sp<ProcessState> proc;
#ifndef HAVE_ANDROID_OS
/* Set stdout/stderr to unbuffered for MinGW/MSYS. */
//setvbuf(stdout, NULL, _IONBF, 0);
//setvbuf(stderr, NULL, _IONBF, 0);
LOGI("commandline args:\n");
for (int i = 0; i < argc; i++)
LOGI(" %2d: '%s'\n", i, argv[i]);
#endif
while (1) {
ic = getopt(argc, argv, "g:j:v:d:l:n");
if (ic < 0)
break;
switch (ic) {
case 'g':
break;
case 'j':
gInitialApplication = optarg;
break;
case 'v':
gInitialVerb = optarg;
break;
case 'd':
gInitialData = optarg;
break;
case 'l':
logFile = optarg;
break;
case 'n':
redirectStdFds();
break;
case '?':
default:
LOGE("runtime: unrecognized flag -%c\n", ic);
usage(argv[0]);
break;
}
}
if (optind < argc) {
LOGE("runtime: extra stuff: %s\n", argv[optind]);
usage(argv[0]);
}
if (logFile != NULL) {
android_logToFile(NULL, logFile);
}
/*
* Set up ANDROID_* environment variables.
*
* TODO: the use of $ANDROID_PRODUCT_OUT will go away soon.
*/
static const char* kSystemDir = "/system";
static const char* kDataDir = "/data";
static const char* kAppSubdir = "/app";
const char* out = NULL;
#ifndef HAVE_ANDROID_OS
//out = getenv("ANDROID_PRODUCT_OUT");
#endif
if (out == NULL)
out = "";
char* systemDir = (char*) malloc(strlen(out) + strlen(kSystemDir) +1);
char* dataDir = (char*) malloc(strlen(out) + strlen(kDataDir) +1);
sprintf(systemDir, "%s%s", out, kSystemDir);
sprintf(dataDir, "%s%s", out, kDataDir);
setenv("ANDROID_ROOT", systemDir, 1);
setenv("ANDROID_DATA", dataDir, 1);
char* assetDir = (char*) malloc(strlen(systemDir) + strlen(kAppSubdir) +1);
sprintf(assetDir, "%s%s", systemDir, kAppSubdir);
LOGI("Startup: sys='%s' asset='%s' data='%s'\n",
systemDir, assetDir, dataDir);
free(systemDir);
free(dataDir);
#ifdef HAVE_ANDROID_OS
/* set up a process group for easier killing on the device */
setpgid(0, getpid());
#endif
// Change to asset dir. This is only necessary if we've changed to
// a different directory, but there's little harm in doing it regardless.
//
// Expecting assets to live in the current dir is not a great idea,
// because some of our code or one of our libraries could change the
// directory out from under us. Preserve the behavior for now.
if (chdir(assetDir) != 0) {
LOGW("WARNING: could not change dir to '%s': %s\n",
assetDir, strerror(errno));
}
free(assetDir);
#if 0
// Hack to keep libc from beating the filesystem to death. It's
// hitting /etc/localtime frequently,
//
// This statement locks us into Pacific time. We could do better,
// but there's not much point until we're sure that the library
// can't be changed to do more along the lines of what we want.
#ifndef XP_WIN
setenv("TZ", "PST+8PDT,M4.1.0/2,M10.5.0/2", true);
#endif
#endif
/* track our progress through the boot sequence */
const int LOG_BOOT_PROGRESS_START = 3000;
LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,
ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
validateTime();
proc = ProcessState::self();
boot_init();
// Have zygote spawn the system server process and call system_init().
// If stdio logging is on, system_server should not inherit our stdio
// The dalvikvm instance will copy stdio to the log on its own
char propBuf[PROPERTY_VALUE_MAX];
bool logStdio = false;
property_get("log.redirect-stdio", propBuf, "");
logStdio = (strcmp(propBuf, "true") == 0);
zygote_run_oneshot((int)(!logStdio),
sizeof(ZYGOTE_ARGV) / sizeof(ZYGOTE_ARGV[0]),
ZYGOTE_ARGV);
finish_system_init(proc);
run(proc);
bail:
if (proc != NULL) {
proc->setContextObject(NULL);
}
return 0;
}