summaryrefslogtreecommitdiffstats
path: root/cmds
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:31:44 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:31:44 -0800
commit9066cfe9886ac131c34d59ed0e2d287b0e3c0087 (patch)
treed88beb88001f2482911e3d28e43833b50e4b4e97 /cmds
parentd83a98f4ce9cfa908f5c54bbd70f03eec07e7553 (diff)
downloadframeworks_base-9066cfe9886ac131c34d59ed0e2d287b0e3c0087.zip
frameworks_base-9066cfe9886ac131c34d59ed0e2d287b0e3c0087.tar.gz
frameworks_base-9066cfe9886ac131c34d59ed0e2d287b0e3c0087.tar.bz2
auto import from //depot/cupcake/@135843
Diffstat (limited to 'cmds')
-rw-r--r--cmds/am/Android.mk14
-rw-r--r--cmds/am/MODULE_LICENSE_APACHE20
-rw-r--r--cmds/am/NOTICE190
-rwxr-xr-xcmds/am/am7
-rw-r--r--cmds/am/src/com/android/commands/am/Am.java487
-rw-r--r--cmds/app_process/Android.mk14
-rw-r--r--cmds/app_process/MODULE_LICENSE_APACHE20
-rw-r--r--cmds/app_process/NOTICE190
-rw-r--r--cmds/app_process/app_main.cpp180
-rw-r--r--cmds/dumpstate/Android.mk25
-rw-r--r--cmds/dumpstate/dumpstate.c293
-rw-r--r--cmds/dumpstate/dumpstate.h138
-rw-r--r--cmds/dumpstate/utils.c230
-rw-r--r--cmds/dumpsys/Android.mk17
-rw-r--r--cmds/dumpsys/MODULE_LICENSE_APACHE20
-rw-r--r--cmds/dumpsys/NOTICE190
-rw-r--r--cmds/dumpsys/dumpsys.cpp81
-rw-r--r--cmds/ime/Android.mk15
-rw-r--r--cmds/ime/MODULE_LICENSE_APACHE20
-rw-r--r--cmds/ime/NOTICE190
-rwxr-xr-xcmds/ime/ime7
-rw-r--r--cmds/ime/src/com/android/commands/ime/Ime.java248
-rw-r--r--cmds/input/Android.mk13
-rw-r--r--cmds/input/MODULE_LICENSE_APACHE20
-rw-r--r--cmds/input/NOTICE190
-rw-r--r--cmds/input/input7
-rwxr-xr-xcmds/input/src/com/android/commands/input/Input.java144
-rw-r--r--cmds/installd/Android.mk21
-rw-r--r--cmds/installd/commands.c568
-rw-r--r--cmds/installd/installd.c259
-rw-r--r--cmds/installd/installd.h100
-rw-r--r--cmds/installd/utils.c149
-rw-r--r--cmds/pm/Android.mk15
-rw-r--r--cmds/pm/MODULE_LICENSE_APACHE20
-rw-r--r--cmds/pm/NOTICE190
-rwxr-xr-xcmds/pm/pm7
-rw-r--r--cmds/pm/src/com/android/commands/pm/Pm.java845
-rw-r--r--cmds/runtime/Android.mk29
-rw-r--r--cmds/runtime/MODULE_LICENSE_APACHE20
-rw-r--r--cmds/runtime/NOTICE190
-rw-r--r--cmds/runtime/ServiceManager.cpp74
-rw-r--r--cmds/runtime/ServiceManager.h38
-rw-r--r--cmds/runtime/SignalHandler.cpp249
-rw-r--r--cmds/runtime/SignalHandler.h137
-rw-r--r--cmds/runtime/main_runtime.cpp514
-rw-r--r--cmds/service/Android.mk17
-rw-r--r--cmds/service/MODULE_LICENSE_APACHE20
-rw-r--r--cmds/service/NOTICE190
-rw-r--r--cmds/service/service.cpp275
-rw-r--r--cmds/servicemanager/Android.mk14
-rw-r--r--cmds/servicemanager/bctest.c102
-rw-r--r--cmds/servicemanager/binder.c616
-rw-r--r--cmds/servicemanager/binder.h119
-rw-r--r--cmds/servicemanager/service_manager.c260
-rw-r--r--cmds/surfaceflinger/Android.mk16
-rw-r--r--cmds/surfaceflinger/main_surfaceflinger.cpp18
-rw-r--r--cmds/svc/Android.mk15
-rw-r--r--cmds/svc/MODULE_LICENSE_APACHE20
-rw-r--r--cmds/svc/NOTICE190
-rw-r--r--cmds/svc/src/com/android/commands/svc/DataCommand.java81
-rw-r--r--cmds/svc/src/com/android/commands/svc/PowerCommand.java74
-rw-r--r--cmds/svc/src/com/android/commands/svc/Svc.java99
-rw-r--r--cmds/svc/src/com/android/commands/svc/WifiCommand.java78
-rwxr-xr-xcmds/svc/svc7
-rw-r--r--cmds/system_server/Android.mk19
-rw-r--r--cmds/system_server/MODULE_LICENSE_APACHE20
-rw-r--r--cmds/system_server/NOTICE190
-rw-r--r--cmds/system_server/library/Android.mk27
-rw-r--r--cmds/system_server/library/system_init.cpp109
-rw-r--r--cmds/system_server/system_main.cpp61
70 files changed, 8832 insertions, 0 deletions
diff --git a/cmds/am/Android.mk b/cmds/am/Android.mk
new file mode 100644
index 0000000..170849d
--- /dev/null
+++ b/cmds/am/Android.mk
@@ -0,0 +1,14 @@
+# Copyright 2008 The Android Open Source Project
+#
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_MODULE := am
+include $(BUILD_JAVA_LIBRARY)
+
+include $(CLEAR_VARS)
+ALL_PREBUILT += $(TARGET_OUT)/bin/am
+$(TARGET_OUT)/bin/am : $(LOCAL_PATH)/am | $(ACP)
+ $(transform-prebuilt-to-target)
+
diff --git a/cmds/am/MODULE_LICENSE_APACHE2 b/cmds/am/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cmds/am/MODULE_LICENSE_APACHE2
diff --git a/cmds/am/NOTICE b/cmds/am/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/cmds/am/NOTICE
@@ -0,0 +1,190 @@
+
+ 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
+
diff --git a/cmds/am/am b/cmds/am/am
new file mode 100755
index 0000000..a5b13f9
--- /dev/null
+++ b/cmds/am/am
@@ -0,0 +1,7 @@
+# Script to start "am" on the device, which has a very rudimentary
+# shell.
+#
+base=/system
+export CLASSPATH=$base/framework/am.jar
+exec app_process $base/bin com.android.commands.am.Am $*
+
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
new file mode 100644
index 0000000..b86d40a
--- /dev/null
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -0,0 +1,487 @@
+/*
+**
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+
+package com.android.commands.am;
+
+import android.app.ActivityManagerNative;
+import android.app.IActivityManager;
+import android.app.IInstrumentationWatcher;
+import android.app.Instrumentation;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.view.IWindowManager;
+
+import java.util.Iterator;
+import java.util.Set;
+
+public class Am {
+
+ private IActivityManager mAm;
+ private String[] mArgs;
+ private int mNextArg;
+ private String mCurArgData;
+
+ private boolean mDebugOption = false;
+
+ /**
+ * Command-line entry point.
+ *
+ * @param args The command-line arguments
+ */
+ public static void main(String[] args) {
+ (new Am()).run(args);
+ }
+
+ private void run(String[] args) {
+ if (args.length < 1) {
+ showUsage();
+ return;
+ }
+
+ mAm = ActivityManagerNative.getDefault();
+ if (mAm == null) {
+ System.err.println("Error type 2");
+ System.err.println("Error: Unable to connect to activity manager; is the system running?");
+ showUsage();
+ return;
+ }
+
+ mArgs = args;
+
+ String op = args[0];
+ mNextArg = 1;
+ if (op.equals("start")) {
+ runStart();
+ } else if (op.equals("instrument")) {
+ runInstrument();
+ } else if (op.equals("broadcast")) {
+ sendBroadcast();
+ } else {
+ System.err.println("Error: Unknown command: " + op);
+ showUsage();
+ return;
+ }
+ }
+
+ private Intent makeIntent() {
+ Intent intent = new Intent();
+ boolean hasIntentInfo = false;
+
+ mDebugOption = false;
+ Uri data = null;
+ String type = null;
+
+ try {
+ String opt;
+ while ((opt=nextOption()) != null) {
+ if (opt.equals("-a")) {
+ intent.setAction(nextOptionData());
+ hasIntentInfo = true;
+ } else if (opt.equals("-d")) {
+ data = Uri.parse(nextOptionData());
+ hasIntentInfo = true;
+ } else if (opt.equals("-t")) {
+ type = nextOptionData();
+ hasIntentInfo = true;
+ } else if (opt.equals("-c")) {
+ intent.addCategory(nextOptionData());
+ hasIntentInfo = true;
+ } else if (opt.equals("-e") || opt.equals("--es")) {
+ String key = nextOptionData();
+ String value = nextOptionData();
+ intent.putExtra(key, value);
+ hasIntentInfo = true;
+ } else if (opt.equals("--ei")) {
+ String key = nextOptionData();
+ String value = nextOptionData();
+ intent.putExtra(key, Integer.valueOf(value));
+ hasIntentInfo = true;
+ } else if (opt.equals("--ez")) {
+ String key = nextOptionData();
+ String value = nextOptionData();
+ intent.putExtra(key, Boolean.valueOf(value));
+ hasIntentInfo = true;
+ } else if (opt.equals("-n")) {
+ String str = nextOptionData();
+ ComponentName cn = ComponentName.unflattenFromString(str);
+ if (cn == null) {
+ System.err.println("Error: Bad component name: " + str);
+ showUsage();
+ return null;
+ }
+ intent.setComponent(cn);
+ hasIntentInfo = true;
+ } else if (opt.equals("-f")) {
+ String str = nextOptionData();
+ intent.setFlags(Integer.decode(str).intValue());
+ } else if (opt.equals("-D")) {
+ mDebugOption = true;
+ } else {
+ System.err.println("Error: Unknown option: " + opt);
+ showUsage();
+ return null;
+ }
+ }
+ } catch (RuntimeException ex) {
+ System.err.println("Error: " + ex.toString());
+ showUsage();
+ return null;
+ }
+ intent.setDataAndType(data, type);
+
+ String uri = nextArg();
+ if (uri != null) {
+ try {
+ Intent oldIntent = intent;
+ try {
+ intent = Intent.getIntent(uri);
+ } catch (java.net.URISyntaxException ex) {
+ System.err.println("Bad URI: " + uri);
+ showUsage();
+ return null;
+ }
+ if (oldIntent.getAction() != null) {
+ intent.setAction(oldIntent.getAction());
+ }
+ if (oldIntent.getData() != null || oldIntent.getType() != null) {
+ intent.setDataAndType(oldIntent.getData(), oldIntent.getType());
+ }
+ Set cats = oldIntent.getCategories();
+ if (cats != null) {
+ Iterator it = cats.iterator();
+ while (it.hasNext()) {
+ intent.addCategory((String)it.next());
+ }
+ }
+ } catch (RuntimeException ex) {
+ System.err.println("Error creating from URI: " + ex.toString());
+ showUsage();
+ return null;
+ }
+ } else if (!hasIntentInfo) {
+ System.err.println("Error: No intent supplied");
+ showUsage();
+ return null;
+ }
+
+ return intent;
+ }
+
+ private void runStart() {
+ Intent intent = makeIntent();
+
+ if (intent != null) {
+ System.out.println("Starting: " + intent);
+ try {
+ intent.addFlags(intent.FLAG_ACTIVITY_NEW_TASK);
+ // XXX should do something to determine the MIME type.
+ int res = mAm.startActivity(null, intent, intent.getType(),
+ null, 0, null, null, 0, false, mDebugOption);
+ switch (res) {
+ case IActivityManager.START_SUCCESS:
+ break;
+ case IActivityManager.START_CLASS_NOT_FOUND:
+ System.err.println("Error type 3");
+ System.err.println("Error: Activity class " +
+ intent.getComponent().toShortString()
+ + " does not exist.");
+ break;
+ case IActivityManager.START_DELIVERED_TO_TOP:
+ System.err.println(
+ "Warning: Activity not started, intent has "
+ + "been delivered to currently running "
+ + "top-most instance.");
+ break;
+ case IActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
+ System.err.println(
+ "Error: Activity not started, you requested to "
+ + "both forward and receive its result");
+ break;
+ case IActivityManager.START_INTENT_NOT_RESOLVED:
+ System.err.println(
+ "Error: Activity not started, unable to "
+ + "resolve " + intent.toString());
+ break;
+ case IActivityManager.START_RETURN_INTENT_TO_CALLER:
+ System.err.println(
+ "Warning: Activity not started because intent "
+ + "should be handled by the caller");
+ break;
+ case IActivityManager.START_TASK_TO_FRONT:
+ System.err.println(
+ "Warning: Activity not started, its current "
+ + "task has been brought to the front");
+ break;
+ default:
+ System.err.println(
+ "Error: Activity not started, unknown error "
+ + "code " + res);
+ break;
+ }
+ } catch (RemoteException e) {
+ System.err.println("Error type 1");
+ System.err.println(
+ "Error: Activity not started, unable to "
+ + "call on to activity manager service");
+ }
+ }
+ }
+
+ private void sendBroadcast() {
+ Intent intent = makeIntent();
+
+ if (intent != null) {
+ System.out.println("Broadcasting: " + intent);
+ try {
+ mAm.broadcastIntent(null, intent, null, null, 0, null, null,
+ null, true, false);
+ } catch (RemoteException e) {
+ }
+ }
+ }
+
+ private void runInstrument() {
+ String profileFile = null;
+ boolean wait = false;
+ boolean rawMode = false;
+ boolean no_window_animation = false;
+ Bundle args = new Bundle();
+ String argKey = null, argValue = null;
+ IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
+
+ try {
+ String opt;
+ while ((opt=nextOption()) != null) {
+ if (opt.equals("-p")) {
+ profileFile = nextOptionData();
+ } else if (opt.equals("-w")) {
+ wait = true;
+ } else if (opt.equals("-r")) {
+ rawMode = true;
+ } else if (opt.equals("-e")) {
+ argKey = nextOptionData();
+ argValue = nextOptionData();
+ args.putString(argKey, argValue);
+ } else if (opt.equals("--no_window_animation")) {
+ no_window_animation = true;
+ } else {
+ System.err.println("Error: Unknown option: " + opt);
+ showUsage();
+ return;
+ }
+ }
+ } catch (RuntimeException ex) {
+ System.err.println("Error: " + ex.toString());
+ showUsage();
+ return;
+ }
+
+ String cnArg = nextArg();
+ if (cnArg == null) {
+ System.err.println("Error: No instrumentation component supplied");
+ showUsage();
+ return;
+ }
+
+ ComponentName cn = ComponentName.unflattenFromString(cnArg);
+ if (cn == null) {
+ System.err.println("Error: Bad component name: " + cnArg);
+ showUsage();
+ return;
+ }
+
+ InstrumentationWatcher watcher = null;
+ if (wait) {
+ watcher = new InstrumentationWatcher();
+ watcher.setRawOutput(rawMode);
+ }
+ float[] oldAnims = null;
+ if (no_window_animation) {
+ try {
+ oldAnims = wm.getAnimationScales();
+ wm.setAnimationScale(0, 0.0f);
+ wm.setAnimationScale(1, 0.0f);
+ } catch (RemoteException e) {
+ }
+ }
+
+ try {
+ if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher)) {
+ System.out.println("INSTRUMENTATION_FAILED: " +
+ cn.flattenToString());
+ showUsage();
+ return;
+ }
+ } catch (RemoteException e) {
+ }
+
+ if (watcher != null) {
+ if (!watcher.waitForFinish()) {
+ System.out.println("INSTRUMENTATION_ABORTED: System has crashed.");
+ }
+ }
+
+ if (oldAnims != null) {
+ try {
+ wm.setAnimationScales(oldAnims);
+ } catch (RemoteException e) {
+ }
+ }
+ }
+
+ private class InstrumentationWatcher extends IInstrumentationWatcher.Stub {
+ private boolean mFinished = false;
+ private boolean mRawMode = false;
+
+ /**
+ * Set or reset "raw mode". In "raw mode", all bundles are dumped. In "pretty mode",
+ * if a bundle includes Instrumentation.REPORT_KEY_STREAMRESULT, just print that.
+ * @param rawMode true for raw mode, false for pretty mode.
+ */
+ public void setRawOutput(boolean rawMode) {
+ mRawMode = rawMode;
+ }
+
+ public void instrumentationStatus(ComponentName name, int resultCode, Bundle results) {
+ synchronized (this) {
+ // pretty printer mode?
+ String pretty = null;
+ if (!mRawMode && results != null) {
+ pretty = results.getString(Instrumentation.REPORT_KEY_STREAMRESULT);
+ }
+ if (pretty != null) {
+ System.out.print(pretty);
+ } else {
+ if (results != null) {
+ for (String key : results.keySet()) {
+ System.out.println(
+ "INSTRUMENTATION_STATUS: " + key + "=" + results.get(key));
+ }
+ }
+ System.out.println("INSTRUMENTATION_STATUS_CODE: " + resultCode);
+ }
+ notifyAll();
+ }
+ }
+
+ public void instrumentationFinished(ComponentName name, int resultCode,
+ Bundle results) {
+ synchronized (this) {
+ // pretty printer mode?
+ String pretty = null;
+ if (!mRawMode && results != null) {
+ pretty = results.getString(Instrumentation.REPORT_KEY_STREAMRESULT);
+ }
+ if (pretty != null) {
+ System.out.println(pretty);
+ } else {
+ if (results != null) {
+ for (String key : results.keySet()) {
+ System.out.println(
+ "INSTRUMENTATION_RESULT: " + key + "=" + results.get(key));
+ }
+ }
+ System.out.println("INSTRUMENTATION_CODE: " + resultCode);
+ }
+ mFinished = true;
+ notifyAll();
+ }
+ }
+
+ public boolean waitForFinish() {
+ synchronized (this) {
+ while (!mFinished) {
+ try {
+ if (!mAm.asBinder().pingBinder()) {
+ return false;
+ }
+ wait(1000);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ return true;
+ }
+ }
+
+ private String nextOption() {
+ if (mNextArg >= mArgs.length) {
+ return null;
+ }
+ String arg = mArgs[mNextArg];
+ if (!arg.startsWith("-")) {
+ return null;
+ }
+ mNextArg++;
+ if (arg.equals("--")) {
+ return null;
+ }
+ if (arg.length() > 1 && arg.charAt(1) != '-') {
+ if (arg.length() > 2) {
+ mCurArgData = arg.substring(2);
+ return arg.substring(0, 2);
+ } else {
+ mCurArgData = null;
+ return arg;
+ }
+ }
+ mCurArgData = null;
+ return arg;
+ }
+
+ private String nextOptionData() {
+ if (mCurArgData != null) {
+ return mCurArgData;
+ }
+ if (mNextArg >= mArgs.length) {
+ return null;
+ }
+ String data = mArgs[mNextArg];
+ mNextArg++;
+ return data;
+ }
+
+ private String nextArg() {
+ if (mNextArg >= mArgs.length) {
+ return null;
+ }
+ String arg = mArgs[mNextArg];
+ mNextArg++;
+ return arg;
+ }
+
+ private void showUsage() {
+ System.err.println("usage: am [start|broadcast|instrument]");
+ System.err.println(" am start -D INTENT");
+ System.err.println(" am broadcast INTENT");
+ System.err.println(" am instrument [-r] [-e <ARG_NAME> <ARG_VALUE>] [-p <PROF_FILE>]");
+ System.err.println(" [-w] <COMPONENT> ");
+ System.err.println("");
+ System.err.println(" INTENT is described with:");
+ System.err.println(" [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]");
+ System.err.println(" [-c <CATEGORY> [-c <CATEGORY>] ...]");
+ System.err.println(" [-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]");
+ System.err.println(" [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]");
+ System.err.println(" [-e|--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]");
+ System.err.println(" [-n <COMPONENT>] [-f <FLAGS>] [<URI>]");
+ }
+}
diff --git a/cmds/app_process/Android.mk b/cmds/app_process/Android.mk
new file mode 100644
index 0000000..a33f5cc
--- /dev/null
+++ b/cmds/app_process/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ app_main.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ libutils \
+ libandroid_runtime
+
+LOCAL_MODULE:= app_process
+
+include $(BUILD_EXECUTABLE)
diff --git a/cmds/app_process/MODULE_LICENSE_APACHE2 b/cmds/app_process/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cmds/app_process/MODULE_LICENSE_APACHE2
diff --git a/cmds/app_process/NOTICE b/cmds/app_process/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/cmds/app_process/NOTICE
@@ -0,0 +1,190 @@
+
+ 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
+
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
new file mode 100644
index 0000000..d825d5a
--- /dev/null
+++ b/cmds/app_process/app_main.cpp
@@ -0,0 +1,180 @@
+/*
+ * Main entry of app process.
+ *
+ * Starts the interpreted runtime, then starts up the application.
+ *
+ */
+
+#define LOG_TAG "appproc"
+
+#include <utils/IPCThreadState.h>
+#include <utils/ProcessState.h>
+#include <utils/Log.h>
+#include <cutils/process_name.h>
+#include <cutils/memory.h>
+#include <android_runtime/AndroidRuntime.h>
+
+#include <stdio.h>
+#include <unistd.h>
+
+namespace android {
+
+void app_usage()
+{
+ fprintf(stderr,
+ "Usage: app_process [java-options] cmd-dir start-class-name [options]\n");
+}
+
+status_t app_init(const char* className, int argc, const char* const argv[])
+{
+ LOGV("Entered app_init()!\n");
+
+ AndroidRuntime* jr = AndroidRuntime::getRuntime();
+ jr->callMain(className, argc, argv);
+
+ LOGV("Exiting app_init()!\n");
+ return NO_ERROR;
+}
+
+class AppRuntime : public AndroidRuntime
+{
+public:
+ AppRuntime()
+ : mParentDir(NULL)
+ , mClassName(NULL)
+ , mArgC(0)
+ , mArgV(NULL)
+ {
+ }
+
+#if 0
+ // this appears to be unused
+ const char* getParentDir() const
+ {
+ return mParentDir;
+ }
+#endif
+
+ const char* getClassName() const
+ {
+ return mClassName;
+ }
+
+ virtual void onStarted()
+ {
+ sp<ProcessState> proc = ProcessState::self();
+ if (proc->supportsProcesses()) {
+ LOGV("App process: starting thread pool.\n");
+ proc->startThreadPool();
+ }
+
+ app_init(mClassName, mArgC, mArgV);
+
+ if (ProcessState::self()->supportsProcesses()) {
+ IPCThreadState::self()->stopProcess();
+ }
+ }
+
+ virtual void onZygoteInit()
+ {
+ sp<ProcessState> proc = ProcessState::self();
+ if (proc->supportsProcesses()) {
+ LOGV("App process: starting thread pool.\n");
+ proc->startThreadPool();
+ }
+ }
+
+ virtual void onExit(int code)
+ {
+ if (mClassName == NULL) {
+ // if zygote
+ if (ProcessState::self()->supportsProcesses()) {
+ IPCThreadState::self()->stopProcess();
+ }
+ }
+
+ AndroidRuntime::onExit(code);
+ }
+
+
+ const char* mParentDir;
+ const char* mClassName;
+ int mArgC;
+ const char* const* mArgV;
+};
+
+}
+
+using namespace android;
+
+/*
+ * sets argv0 to as much of newArgv0 as will fit
+ */
+static void setArgv0(const char *argv0, const char *newArgv0)
+{
+ strlcpy(const_cast<char *>(argv0), newArgv0, strlen(argv0));
+}
+
+int main(int argc, const char* const argv[])
+{
+ // These are global variables in ProcessState.cpp
+ mArgC = argc;
+ mArgV = argv;
+
+ mArgLen = 0;
+ for (int i=0; i<argc; i++) {
+ mArgLen += strlen(argv[i]) + 1;
+ }
+ mArgLen--;
+
+ AppRuntime runtime;
+ const char *arg;
+ const char *argv0;
+
+ argv0 = argv[0];
+
+ // Process command line arguments
+ // ignore argv[0]
+ argc--;
+ argv++;
+
+ // Everything up to '--' or first non '-' arg goes to the vm
+
+ int i = runtime.addVmArguments(argc, argv);
+
+ // Next arg is parent directory
+ if (i < argc) {
+ runtime.mParentDir = argv[i++];
+ }
+
+ // Next arg is startup classname or "--zygote"
+ if (i < argc) {
+ arg = argv[i++];
+ if (0 == strcmp("--zygote", arg)) {
+ bool startSystemServer = (i < argc) ?
+ strcmp(argv[i], "--start-system-server") == 0 : false;
+ setArgv0(argv0, "zygote");
+ set_process_name("zygote");
+ runtime.start("com.android.internal.os.ZygoteInit",
+ startSystemServer);
+ } else {
+ set_process_name(argv0);
+
+ runtime.mClassName = arg;
+
+ // Remainder of args get passed to startup class main()
+ runtime.mArgC = argc-i;
+ runtime.mArgV = argv+i;
+
+ LOGV("App process is starting with pid=%d, class=%s.\n",
+ getpid(), runtime.getClassName());
+ runtime.start();
+ }
+ } else {
+ LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
+ fprintf(stderr, "Error: no class name or --zygote supplied.\n");
+ app_usage();
+ return 10;
+ }
+
+}
diff --git a/cmds/dumpstate/Android.mk b/cmds/dumpstate/Android.mk
new file mode 100644
index 0000000..f61d7ec
--- /dev/null
+++ b/cmds/dumpstate/Android.mk
@@ -0,0 +1,25 @@
+ifneq ($(TARGET_SIMULATOR),true)
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= dumpstate.c utils.c
+
+LOCAL_MODULE:= dumpstate
+
+LOCAL_SHARED_LIBRARIES := libcutils
+
+include $(BUILD_EXECUTABLE)
+
+COMMANDS = dumpcrash bugreport
+SYMLINKS := $(addprefix $(TARGET_OUT_EXECUTABLES)/,$(COMMANDS))
+$(SYMLINKS): DUMPSTATE_BINARY := dumpstate
+$(SYMLINKS): $(LOCAL_INSTALLED_MODULE) $(LOCAL_PATH)/Android.mk
+ @echo "Symlink: $@ -> $(DUMPSTATE_BINARY)"
+ @mkdir -p $(dir $@)
+ @rm -rf $@
+ $(hide) ln -sf $(DUMPSTATE_BINARY) $@
+
+ALL_DEFAULT_INSTALLED_MODULES += $(SYMLINKS)
+
+endif
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
new file mode 100644
index 0000000..e08230f
--- /dev/null
+++ b/cmds/dumpstate/dumpstate.c
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include "private/android_filesystem_config.h"
+
+#include "dumpstate.h"
+
+static char* const gzip_args[] = { "gzip", "-6", 0 };
+static int start_pattern[] = { 150, 0 };
+static int end_pattern[] = { 75, 50, 75, 50, 75, 0 };
+
+static struct tm now;
+
+/* dumps the current system state to stdout */
+static void dumpstate(int full) {
+ if (full) {
+ PRINT("========================================================");
+ PRINT("== dumpstate");
+ PRINT("========================================================");
+ PRINT("------ MEMORY INFO ------");
+ DUMP("/proc/meminfo");
+ PRINT("------ CPU INFO ------");
+ EXEC7("top", "-n", "1", "-d", "1", "-m", "30", "-t");
+ PRINT("------ PROCRANK ------");
+ EXEC_XBIN("procrank");
+ PRINT("------ VIRTUAL MEMORY STATS ------");
+ DUMP("/proc/vmstat");
+ PRINT("------ SLAB INFO ------");
+ DUMP("/proc/slabinfo");
+ PRINT("------ ZONEINFO ------");
+ DUMP("/proc/zoneinfo");
+ PRINT("------ SYSTEM LOG ------");
+ EXEC4("logcat", "-v", "time", "-d", "*:v");
+ PRINT("------ VM TRACES ------");
+ DUMP("/data/anr/traces.txt");
+ PRINT("------ EVENT LOG TAGS ------");
+ DUMP("/etc/event-log-tags");
+ PRINT("------ EVENT LOG ------");
+ EXEC6("logcat", "-b", "events", "-v", "time", "-d", "*:v");
+ PRINT("------ RADIO LOG ------");
+ EXEC6("logcat", "-b", "radio", "-v", "time", "-d", "*:v");
+ PRINT("------ NETWORK STATE ------");
+ PRINT("Interfaces:");
+ EXEC("netcfg");
+ PRINT("");
+ PRINT("Routes:");
+ DUMP("/proc/net/route");
+ PRINT("------ SYSTEM PROPERTIES ------");
+ print_properties();
+ PRINT("------ KERNEL LOG ------");
+ EXEC("dmesg");
+ PRINT("------ KERNEL WAKELOCKS ------");
+ DUMP("/proc/wakelocks");
+ PRINT("");
+ PRINT("------ PROCESSES ------");
+ EXEC("ps");
+ PRINT("------ PROCESSES AND THREADS ------");
+ EXEC2("ps", "-t", "-p");
+ PRINT("------ LIBRANK ------");
+ EXEC_XBIN("librank");
+ PRINT("------ BINDER FAILED TRANSACTION LOG ------");
+ DUMP("/proc/binder/failed_transaction_log");
+ PRINT("");
+ PRINT("------ BINDER TRANSACTION LOG ------");
+ DUMP("/proc/binder/transaction_log");
+ PRINT("");
+ PRINT("------ BINDER TRANSACTIONS ------");
+ DUMP("/proc/binder/transactions");
+ PRINT("");
+ PRINT("------ BINDER STATS ------");
+ DUMP("/proc/binder/stats");
+ PRINT("");
+ PRINT("------ BINDER PROCESS STATE: $i ------");
+ DUMP_FILES("/proc/binder/proc");
+ PRINT("------ FILESYSTEMS ------");
+ EXEC("df");
+ PRINT("------ PACKAGE SETTINGS ------");
+ DUMP("/data/system/packages.xml");
+ PRINT("------ PACKAGE UID ERRORS ------");
+ DUMP("/data/system/uiderrors.txt");
+ PRINT("------ LAST KERNEL LOG ------");
+ DUMP("/proc/last_kmsg");
+ }
+ PRINT("========================================================");
+ PRINT("== build.prop");
+ PRINT("========================================================");
+
+ /* the crash server parses key-value pairs between the VERSION INFO and
+ * END lines so we can aggregate crash reports based on this data.
+ */
+ PRINT("------ VERSION INFO ------");
+ print_date("currenttime=", &now);
+ DUMP_PROMPT("kernel.version=", "/proc/version");
+ DUMP_PROMPT("kernel.cmdline=", "/proc/cmdline");
+ DUMP("/system/build.prop");
+ PROPERTY("gsm.version.ril-impl");
+ PROPERTY("gsm.version.baseband");
+ PROPERTY("gsm.imei");
+ PROPERTY("gsm.sim.operator.numeric");
+ PROPERTY("gsm.operator.alpha");
+ PRINT("------ END ------");
+
+ if (full) {
+ PRINT("========================================================");
+ PRINT("== dumpsys");
+ PRINT("========================================================");
+ EXEC("dumpsys");
+ }
+}
+
+/* used to check the file name passed via argv[0] */
+static int check_command_name(const char* name, const char* test) {
+ int name_length, test_length;
+
+ if (!strcmp(name, test))
+ return 1;
+
+ name_length = strlen(name);
+ test_length = strlen(test);
+
+ if (name_length > test_length + 2) {
+ name += (name_length - test_length);
+ if (name[-1] != '/')
+ return 0;
+ if (!strcmp(name, test))
+ return 1;
+ }
+
+ return 0;
+}
+
+int main(int argc, char *argv[]) {
+ int dumpcrash = check_command_name(argv[0], "dumpcrash");
+ int bugreport = check_command_name(argv[0], "bugreport");
+ int add_date = 0;
+ char* outfile = 0;
+ int vibrate = 0;
+ int compress = 0;
+ int c, fd, vibrate_fd, fds[2];
+ char path[PATH_MAX];
+ pid_t pid;
+
+ /* set as high priority, and protect from OOM killer */
+ setpriority(PRIO_PROCESS, 0, -20);
+ protect_from_oom_killer();
+
+ get_time(&now);
+
+ if (bugreport) {
+ do {
+ c = getopt(argc, argv, "do:vz");
+ if (c == EOF)
+ break;
+ switch (c) {
+ case 'd':
+ add_date = 1;
+ break;
+ case 'o':
+ outfile = optarg;
+ break;
+ case 'v':
+ vibrate = 1;
+ break;
+ case 'z':
+ compress = 1;
+ break;
+ case '?':
+ fprintf(stderr, "%s: invalid option -%c\n",
+ argv[0], optopt);
+ exit(1);
+ }
+ } while (1);
+ }
+
+ /* open vibrator before switching user */
+ if (vibrate) {
+ vibrate_fd = open("/sys/class/timed_output/vibrator/enable", O_WRONLY);
+ if (vibrate_fd > 0)
+ fcntl(vibrate_fd, F_SETFD, FD_CLOEXEC);
+ } else
+ vibrate_fd = -1;
+
+ /* switch to non-root user and group */
+ setgid(AID_LOG);
+ setuid(AID_SHELL);
+
+ /* make it safe to use both printf and STDOUT_FILENO */
+ setvbuf(stdout, 0, _IONBF, 0);
+
+ if (outfile) {
+ if (strlen(outfile) > sizeof(path) - 100)
+ exit(1);
+
+ strcpy(path, outfile);
+ if (add_date) {
+ char date[260];
+ strftime(date, sizeof(date),
+ "-%Y-%m-%d-%H-%M-%S",
+ &now);
+ strcat(path, date);
+ }
+ if (compress)
+ strcat(path, ".gz");
+ else
+ strcat(path, ".txt");
+
+ /* ensure that all directories in the path exist */
+ create_directories(path);
+ fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if (fd < 0)
+ return fd;
+
+ if (compress) {
+ pipe(fds);
+
+ /* redirect our stdout to the pipe */
+ dup2(fds[1], STDOUT_FILENO);
+ close(fds[1]);
+
+ if ((pid = fork()) < 0)
+ {
+ fprintf(stderr, "fork error\n");
+ exit(1);
+ }
+
+ if (pid) {
+ /* parent case */
+
+ /* close our copy of the input to gzip */
+ close(fds[0]);
+ /* close our copy of the output file */
+ close(fd);
+ } else {
+ /* child case */
+
+ /* redirect our input pipe to stdin */
+ dup2(fds[0], STDIN_FILENO);
+ close(fds[0]);
+
+ /* redirect stdout to the output file */
+ dup2(fd, STDOUT_FILENO);
+ close(fd);
+
+ /* run gzip to postprocess our output */
+ execv("/system/bin/gzip", gzip_args);
+ fprintf(stderr, "execv returned\n");
+ }
+ } else {
+ /* redirect stdout to the output file */
+ dup2(fd, STDOUT_FILENO);
+ close(fd);
+ }
+ }
+ /* else everything will print to stdout */
+
+ if (vibrate) {
+ vibrate_pattern(vibrate_fd, start_pattern);
+ }
+ dumpstate(!dumpcrash);
+ if (vibrate) {
+ vibrate_pattern(vibrate_fd, end_pattern);
+ close(vibrate_fd);
+ }
+
+ /* so gzip will terminate */
+ close(STDOUT_FILENO);
+
+ return 0;
+}
+
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
new file mode 100644
index 0000000..4e88e4b
--- /dev/null
+++ b/cmds/dumpstate/dumpstate.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _DUMPSTATE_H_
+#define _DUMPSTATE_H_
+
+#include <time.h>
+
+// Commands time out after 15 seconds
+#define TIMEOUT 15
+
+#define PRINT(s) printf("%s\n", s)
+
+#define DUMP(file) dump_file(file)
+
+#define DUMP_FILES(path) dump_files(path)
+
+#define DUMP_PROMPT(prompt, file) \
+{ \
+ printf(prompt); \
+ dump_file(file); \
+}
+
+#define EXEC(cmd) \
+{ \
+ static struct Command c = { \
+ "/system/bin/" cmd, \
+ { cmd, 0 } \
+ }; \
+ run_command(&c, TIMEOUT); \
+}
+
+#define EXEC_XBIN(cmd) \
+{ \
+ static struct Command c = { \
+ "/system/xbin/" cmd, \
+ { cmd, 0 } \
+ }; \
+ run_command(&c, TIMEOUT); \
+}
+
+#define EXEC2(cmd, a1, a2) \
+{ \
+ static struct Command c = { \
+ "/system/bin/" cmd, \
+ { cmd, a1, a2, 0 } \
+ }; \
+ run_command(&c, TIMEOUT); \
+}
+
+#define EXEC4(cmd, a1, a2, a3, a4) \
+{ \
+ static struct Command c = { \
+ "/system/bin/" cmd, \
+ { cmd, a1, a2, a3, a4, 0 } \
+ }; \
+ run_command(&c, TIMEOUT); \
+}
+
+#define EXEC6(cmd, a1, a2, a3, a4, a5, a6) \
+{ \
+ static struct Command c = { \
+ "/system/bin/" cmd, \
+ { cmd, a1, a2, a3, a4, a5, a6, 0 } \
+ }; \
+ run_command(&c, TIMEOUT); \
+}
+
+#define EXEC7(cmd, a1, a2, a3, a4, a5, a6, a7) \
+{ \
+ static struct Command c = { \
+ "/system/bin/" cmd, \
+ { cmd, a1, a2, a3, a4, a5, a6, a7, 0 } \
+ }; \
+ run_command(&c, TIMEOUT); \
+}
+
+#define EXEC8(cmd, a1, a2, a3, a4, a5, a6, a7, a8) \
+{ \
+ static struct Command c = { \
+ "/system/bin/" cmd, \
+ { cmd, a1, a2, a3, a4, a5, a6, a7, a8, 0 } \
+ }; \
+ run_command(&c, TIMEOUT); \
+}
+
+#define PROPERTY(name) print_property(name)
+
+struct Command {
+ const char* path;
+ char* const args[];
+};
+typedef struct Command Command;
+
+/* prints the contents of a file */
+int dump_file(const char* path);
+
+/* prints the contents of all files in a directory */
+void dump_files(const char* path);
+
+/* forks a command and waits for it to finish */
+int run_command(struct Command* cmd, int timeout);
+
+/* reads the current time into tm */
+void get_time(struct tm *tm);
+
+/* prints the date in tm */
+void print_date(const char* prompt, struct tm *tm);
+
+/* prints the name and value of a system property */
+int print_property(const char* name);
+
+/* prints all the system properties */
+void print_properties();
+
+/* creates directories as needed for the given path */
+void create_directories(char *path);
+
+/* runs the vibrator using the given pattern */
+void vibrate_pattern(int fd, int* pattern);
+
+/* prevents the OOM killer from killing us */
+void protect_from_oom_killer();
+
+#endif /* _DUMPSTATE_H_ */
diff --git a/cmds/dumpstate/utils.c b/cmds/dumpstate/utils.c
new file mode 100644
index 0000000..60d845f
--- /dev/null
+++ b/cmds/dumpstate/utils.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+
+#include <cutils/properties.h>
+#include <sys/system_properties.h>
+
+#include "dumpstate.h"
+
+
+/* prints the contents of a file */
+int dump_file(const char* path) {
+ char buffer[32768];
+ int fd, amount_read;
+ int ret = 0;
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ return fd;
+
+ do {
+ ret = read(fd, buffer, sizeof(buffer));
+ if (ret > 0)
+ ret = write(STDOUT_FILENO, buffer, ret);
+ } while (ret > 0);
+
+ buffer[0] = '\n';
+ write(STDOUT_FILENO, buffer, 1);
+
+ close(fd);
+ return ret;
+}
+
+/* prints the contents of all files in a directory */
+void dump_files(const char* path) {
+ DIR* dir;
+ struct dirent* entry;
+ char buffer[PATH_MAX];
+
+ dir = opendir(path);
+ if (!dir) {
+ fprintf(stderr, "could not open directory %s\n", path);
+ return;
+ }
+
+ while ((entry = readdir(dir))) {
+ if (entry->d_type == DT_REG) {
+ snprintf(buffer, sizeof(buffer), "%s/%s", path, entry->d_name);
+ dump_file(path);
+ printf("\n");
+ }
+ }
+
+ closedir(dir);
+}
+
+/* prints the name and value of a system property */
+int print_property(const char* name) {
+ char value[PROP_VALUE_MAX];
+
+ __system_property_get(name, value);
+ printf("%s=%s\n", name, value);
+ return 0;
+}
+
+static pid_t alarm_pid = 0;
+static int timed_out = 0;
+static void sig_alarm(int sig)
+{
+ if (alarm_pid) {
+ kill(alarm_pid, SIGKILL);
+ timed_out = 1;
+ alarm_pid = 0;
+ }
+}
+
+/* forks a command and waits for it to finish */
+int run_command(struct Command* cmd, int timeout) {
+ struct sigaction sa;
+ pid_t pid;
+ int status;
+
+ pid = fork();
+ /* handle error case */
+ if (pid < 0)
+ return pid;
+
+ /* handle child case */
+ if (pid == 0) {
+ int ret = execv(cmd->path, cmd->args);
+ if (ret)
+ fprintf(stderr, "execv %s returned %d\n", cmd->path, ret);
+ exit(ret);
+ }
+
+ /* handle parent case */
+ timed_out = 0;
+ if (timeout) {
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_flags = SA_RESETHAND;
+ sa.sa_handler = sig_alarm;
+ sigaction(SIGALRM, &sa, NULL);
+
+ /* set an alarm so we don't hang forever */
+ alarm_pid = pid;
+ alarm(timeout);
+ }
+
+ waitpid(pid, &status, 0);
+
+ if (timed_out)
+ printf("ERROR: command %s timed out\n", cmd->path);
+
+ return status;
+}
+
+/* reads the current time into tm */
+void get_time(struct tm *tm) {
+ time_t t;
+
+ tzset();
+ time(&t);
+ localtime_r(&t, tm);
+}
+
+/* prints the date in tm */
+void print_date(const char* prompt, struct tm *tm) {
+ char strbuf[260];
+
+ strftime(strbuf, sizeof(strbuf),
+ "%a %b %e %H:%M:%S %Z %Y",
+ tm);
+ printf("%s%s\n", prompt, strbuf);
+}
+
+
+static void print_prop(const char *key, const char *name,
+ void *user __attribute__((unused)))
+{
+ printf("[%s]: [%s]\n", key, name);
+}
+
+/* prints all the system properties */
+void print_properties() {
+ property_list(print_prop, NULL);
+}
+
+/* creates directories as needed for the given path */
+void create_directories(char *path)
+{
+ char *chp = path;
+
+ /* skip initial slash */
+ if (chp[0] == '/')
+ chp++;
+
+ while (chp && chp[0]) {
+ chp = strchr(chp, '/');
+ if (chp) {
+ *chp = 0;
+ mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+ *chp = '/';
+ chp++;
+ }
+ }
+}
+
+/* runs the vibrator using the given pattern */
+void vibrate_pattern(int fd, int* pattern)
+{
+ struct timespec tm;
+ char buffer[10];
+
+ while (*pattern) {
+ /* read vibrate on time */
+ int on_time = *pattern++;
+ snprintf(buffer, sizeof(buffer), "%d", on_time);
+ write(fd, buffer, strlen(buffer));
+
+ /* read vibrate off time */
+ int delay = *pattern++;
+ if (delay) {
+ delay += on_time;
+
+ tm.tv_sec = delay / 1000;
+ tm.tv_nsec = (delay % 1000) * 1000000;
+ nanosleep(&tm, NULL);
+ } else
+ break;
+ }
+}
+
+/* prevents the OOM killer from killing us */
+void protect_from_oom_killer()
+{
+ int fd;
+
+ fd = open("/proc/self/oom_adj", O_WRONLY);
+ if (fd >= 0) {
+ // -17 should make us immune to OOM
+ const char* text = "-17";
+ write(fd, text, strlen(text));
+ close(fd);
+ }
+}
diff --git a/cmds/dumpsys/Android.mk b/cmds/dumpsys/Android.mk
new file mode 100644
index 0000000..0c623cc
--- /dev/null
+++ b/cmds/dumpsys/Android.mk
@@ -0,0 +1,17 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ dumpsys.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libutils
+
+ifeq ($(TARGET_OS),linux)
+ LOCAL_CFLAGS += -DXP_UNIX
+ #LOCAL_SHARED_LIBRARIES += librt
+endif
+
+LOCAL_MODULE:= dumpsys
+
+include $(BUILD_EXECUTABLE)
diff --git a/cmds/dumpsys/MODULE_LICENSE_APACHE2 b/cmds/dumpsys/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cmds/dumpsys/MODULE_LICENSE_APACHE2
diff --git a/cmds/dumpsys/NOTICE b/cmds/dumpsys/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/cmds/dumpsys/NOTICE
@@ -0,0 +1,190 @@
+
+ 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
+
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
new file mode 100644
index 0000000..a62fe55
--- /dev/null
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -0,0 +1,81 @@
+/*
+ * Command that dumps interesting system state to the log.
+ *
+ */
+
+#define LOG_TAG "dumpsys"
+
+#include <utils/Log.h>
+#include <utils/Parcel.h>
+#include <utils/ProcessState.h>
+#include <utils/IServiceManager.h>
+#include <utils/TextOutput.h>
+#include <utils/Vector.h>
+
+#include <getopt.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+using namespace android;
+
+static int sort_func(const String16* lhs, const String16* rhs)
+{
+ return lhs->compare(*rhs);
+}
+
+int main(int argc, char* const argv[])
+{
+ sp<IServiceManager> sm = defaultServiceManager();
+ fflush(stdout);
+ if (sm == NULL) {
+ LOGE("Unable to get default service manager!");
+ aerr << "dumpsys: Unable to get default service manager!" << endl;
+ return 20;
+ }
+
+ Vector<String16> services;
+ Vector<String16> args;
+ if (argc == 1) {
+ services = sm->listServices();
+ services.sort(sort_func);
+ args.add(String16("-a"));
+ } else {
+ services.add(String16(argv[1]));
+ for (int i=2; i<argc; i++) {
+ args.add(String16(argv[i]));
+ }
+ }
+
+ const size_t N = services.size();
+
+ // first print a list of the current services
+ aout << "Currently running services:" << endl;
+
+ for (size_t i=0; i<N; i++) {
+ sp<IBinder> service = sm->checkService(services[i]);
+ if (service != NULL) {
+ aout << " " << services[i] << endl;
+ }
+ }
+
+ for (size_t i=0; i<N; i++) {
+ sp<IBinder> service = sm->checkService(services[i]);
+ if (service != NULL) {
+ aout << "------------------------------------------------------------"
+ "-------------------" << endl;
+ aout << "DUMP OF SERVICE " << services[i] << ":" << endl;
+ int err = service->dump(STDOUT_FILENO, args);
+ if (err != 0) {
+ aerr << "Error dumping service info: (" << strerror(err)
+ << ") " << services[i] << endl;
+ }
+ } else {
+ aerr << "Can't find service: " << services[i] << endl;
+ }
+ }
+
+ return 0;
+}
diff --git a/cmds/ime/Android.mk b/cmds/ime/Android.mk
new file mode 100644
index 0000000..90b1c91
--- /dev/null
+++ b/cmds/ime/Android.mk
@@ -0,0 +1,15 @@
+# Copyright 2007 The Android Open Source Project
+#
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_MODULE := ime
+include $(BUILD_JAVA_LIBRARY)
+
+
+include $(CLEAR_VARS)
+ALL_PREBUILT += $(TARGET_OUT)/bin/ime
+$(TARGET_OUT)/bin/ime : $(LOCAL_PATH)/ime | $(ACP)
+ $(transform-prebuilt-to-target)
+
diff --git a/cmds/ime/MODULE_LICENSE_APACHE2 b/cmds/ime/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cmds/ime/MODULE_LICENSE_APACHE2
diff --git a/cmds/ime/NOTICE b/cmds/ime/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/cmds/ime/NOTICE
@@ -0,0 +1,190 @@
+
+ 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
+
diff --git a/cmds/ime/ime b/cmds/ime/ime
new file mode 100755
index 0000000..96c56d3
--- /dev/null
+++ b/cmds/ime/ime
@@ -0,0 +1,7 @@
+# Script to start "pm" on the device, which has a very rudimentary
+# shell.
+#
+base=/system
+export CLASSPATH=$base/framework/ime.jar
+exec app_process $base/bin com.android.commands.ime.Ime "$@"
+
diff --git a/cmds/ime/src/com/android/commands/ime/Ime.java b/cmds/ime/src/com/android/commands/ime/Ime.java
new file mode 100644
index 0000000..72a0af6
--- /dev/null
+++ b/cmds/ime/src/com/android/commands/ime/Ime.java
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.commands.ime;
+
+import com.android.internal.view.IInputMethodManager;
+
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.PrintStreamPrinter;
+import android.util.Printer;
+import android.view.inputmethod.InputMethodInfo;
+
+import java.util.List;
+
+public final class Ime {
+ IInputMethodManager mImm;
+
+ private String[] mArgs;
+ private int mNextArg;
+ private String mCurArgData;
+
+ private static final String IMM_NOT_RUNNING_ERR =
+ "Error: Could not access the Input Method Manager. Is the system running?";
+
+ public static void main(String[] args) {
+ new Ime().run(args);
+ }
+
+ public void run(String[] args) {
+ if (args.length < 1) {
+ showUsage();
+ return;
+ }
+
+ mImm = IInputMethodManager.Stub.asInterface(ServiceManager.getService("input_method"));
+ if (mImm == null) {
+ System.err.println(IMM_NOT_RUNNING_ERR);
+ return;
+ }
+
+ mArgs = args;
+ String op = args[0];
+ mNextArg = 1;
+
+ if ("list".equals(op)) {
+ runList();
+ return;
+ }
+
+ if ("enable".equals(op)) {
+ runSetEnabled(true);
+ return;
+ }
+
+ if ("disable".equals(op)) {
+ runSetEnabled(false);
+ return;
+ }
+
+ if ("set".equals(op)) {
+ runSet();
+ return;
+ }
+
+ if (op != null) {
+ System.err.println("Error: unknown command '" + op + "'");
+ }
+ showUsage();
+ }
+
+ /**
+ * Execute the list sub-command.
+ */
+ private void runList() {
+ String opt;
+ boolean all = false;
+ boolean brief = false;
+ while ((opt=nextOption()) != null) {
+ if (opt.equals("-a")) {
+ all = true;
+ } else if (opt.equals("-s")) {
+ brief = true;
+ } else {
+ System.err.println("Error: Unknown option: " + opt);
+ showUsage();
+ return;
+ }
+ }
+
+
+ List<InputMethodInfo> methods;
+ if (!all) {
+ try {
+ methods = mImm.getEnabledInputMethodList();
+ } catch (RemoteException e) {
+ System.err.println(e.toString());
+ System.err.println(IMM_NOT_RUNNING_ERR);
+ return;
+ }
+ } else {
+ try {
+ methods = mImm.getInputMethodList();
+ } catch (RemoteException e) {
+ System.err.println(e.toString());
+ System.err.println(IMM_NOT_RUNNING_ERR);
+ return;
+ }
+ }
+
+ if (methods != null) {
+ Printer pr = new PrintStreamPrinter(System.out);
+ for (int i=0; i<methods.size(); i++) {
+ InputMethodInfo imi = methods.get(i);
+ if (brief) {
+ System.out.println(imi.getId());
+ } else {
+ System.out.println(imi.getId() + ":");
+ imi.dump(pr, " ");
+ }
+ }
+ }
+ }
+
+ private void runSetEnabled(boolean state) {
+ String id = nextArg();
+ if (id == null) {
+ System.err.println("Error: no input method ID specified");
+ showUsage();
+ return;
+ }
+
+ try {
+ boolean res = mImm.setInputMethodEnabled(id, state);
+ if (state) {
+ System.out.println("Input method " + id + ": "
+ + (res ? "already enabled" : "now enabled"));
+ } else {
+ System.out.println("Input method " + id + ": "
+ + (res ? "now disabled" : "already disabled"));
+ }
+ } catch (IllegalArgumentException e) {
+ System.err.println("Error: " + e.getMessage());
+ return;
+ } catch (RemoteException e) {
+ System.err.println(e.toString());
+ System.err.println(IMM_NOT_RUNNING_ERR);
+ return;
+ }
+ }
+
+ private void runSet() {
+ String id = nextArg();
+ if (id == null) {
+ System.err.println("Error: no input method ID specified");
+ showUsage();
+ return;
+ }
+
+ try {
+ mImm.setInputMethod(null, id);
+ System.out.println("Input method " + id + " selected");
+ } catch (IllegalArgumentException e) {
+ System.err.println("Error: " + e.getMessage());
+ return;
+ } catch (RemoteException e) {
+ System.err.println(e.toString());
+ System.err.println(IMM_NOT_RUNNING_ERR);
+ return;
+ }
+ }
+
+ private String nextOption() {
+ if (mNextArg >= mArgs.length) {
+ return null;
+ }
+ String arg = mArgs[mNextArg];
+ if (!arg.startsWith("-")) {
+ return null;
+ }
+ mNextArg++;
+ if (arg.equals("--")) {
+ return null;
+ }
+ if (arg.length() > 1 && arg.charAt(1) != '-') {
+ if (arg.length() > 2) {
+ mCurArgData = arg.substring(2);
+ return arg.substring(0, 2);
+ } else {
+ mCurArgData = null;
+ return arg;
+ }
+ }
+ mCurArgData = null;
+ return arg;
+ }
+
+ private String nextOptionData() {
+ if (mCurArgData != null) {
+ return mCurArgData;
+ }
+ if (mNextArg >= mArgs.length) {
+ return null;
+ }
+ String data = mArgs[mNextArg];
+ mNextArg++;
+ return data;
+ }
+
+ private String nextArg() {
+ if (mNextArg >= mArgs.length) {
+ return null;
+ }
+ String arg = mArgs[mNextArg];
+ mNextArg++;
+ return arg;
+ }
+
+ private static void showUsage() {
+ System.err.println("usage: ime list [-a] [-s]");
+ System.err.println(" ime enable ID");
+ System.err.println(" ime disable ID");
+ System.err.println(" ime set ID");
+ System.err.println("");
+ System.err.println("The list command prints all enabled input methods. Use");
+ System.err.println("the -a option to see all input methods. Use");
+ System.err.println("the -s option to see only a single summary line of each.");
+ System.err.println("");
+ System.err.println("The enable command allows the given input method ID to be used.");
+ System.err.println("");
+ System.err.println("The disable command disallows the given input method ID from use.");
+ System.err.println("");
+ System.err.println("The set command switches to the given input method ID.");
+ }
+}
diff --git a/cmds/input/Android.mk b/cmds/input/Android.mk
new file mode 100644
index 0000000..3d56533
--- /dev/null
+++ b/cmds/input/Android.mk
@@ -0,0 +1,13 @@
+# Copyright 2008 The Android Open Source Project
+#
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_MODULE := input
+include $(BUILD_JAVA_LIBRARY)
+
+include $(CLEAR_VARS)
+ALL_PREBUILT += $(TARGET_OUT)/bin/input
+$(TARGET_OUT)/bin/input : $(LOCAL_PATH)/input | $(ACP)
+ $(transform-prebuilt-to-target)
diff --git a/cmds/input/MODULE_LICENSE_APACHE2 b/cmds/input/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cmds/input/MODULE_LICENSE_APACHE2
diff --git a/cmds/input/NOTICE b/cmds/input/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/cmds/input/NOTICE
@@ -0,0 +1,190 @@
+
+ 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
+
diff --git a/cmds/input/input b/cmds/input/input
new file mode 100644
index 0000000..fa9dced
--- /dev/null
+++ b/cmds/input/input
@@ -0,0 +1,7 @@
+# Script to start "input" on the device, which has a very rudimentary
+# shell.
+#
+base=/system
+export CLASSPATH=$base/framework/input.jar
+exec app_process $base/bin com.android.commands.input.Input $*
+
diff --git a/cmds/input/src/com/android/commands/input/Input.java b/cmds/input/src/com/android/commands/input/Input.java
new file mode 100755
index 0000000..3a1accd
--- /dev/null
+++ b/cmds/input/src/com/android/commands/input/Input.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.commands.input;
+
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.util.Log;
+import android.view.IWindowManager;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
+
+/**
+ * Command that sends key events to the device, either by their keycode, or by
+ * desired character output.
+ */
+
+public class Input {
+
+ /**
+ * Command-line entry point.
+ *
+ * @param args The command-line arguments
+ */
+ public static void main(String[] args) {
+ (new Input()).run(args);
+ }
+
+ private void run(String[] args) {
+ if (args.length < 1) {
+ showUsage();
+ return;
+ }
+
+ String command = args[0];
+
+ if (command.equals("text")) {
+ sendText(args[1]);
+ } else if (command.equals("keyevent")) {
+ sendKeyEvent(args[1]);
+ } else if (command.equals("motionevent")) {
+ System.err.println("Error: motionevent not yet supported.");
+ return;
+ }
+ else {
+ System.err.println("Error: Unknown command: " + command);
+ showUsage();
+ return;
+ }
+ }
+
+ /**
+ * Convert the characters of string text into key event's and send to
+ * device.
+ *
+ * @param text is a string of characters you want to input to the device.
+ */
+
+ private void sendText(String text) {
+
+ StringBuffer buff = new StringBuffer(text);
+
+ boolean escapeFlag = false;
+ for (int i=0; i<buff.length(); i++) {
+ if (escapeFlag) {
+ escapeFlag = false;
+ if (buff.charAt(i) == 's') {
+ buff.setCharAt(i, ' ');
+ buff.deleteCharAt(--i);
+ }
+ }
+ if (buff.charAt(i) == '%') {
+ escapeFlag = true;
+ }
+ }
+
+ char[] chars = buff.toString().toCharArray();
+
+ KeyCharacterMap mKeyCharacterMap = KeyCharacterMap.
+ load(KeyCharacterMap.BUILT_IN_KEYBOARD);
+
+ KeyEvent[] events = mKeyCharacterMap.getEvents(chars);
+
+ for(int i = 0; i < events.length; i++) {
+ KeyEvent event = events[i];
+ Log.i("SendKeyEvent", Integer.toString(event.getKeyCode()));
+ try {
+ (IWindowManager.Stub
+ .asInterface(ServiceManager.getService("window")))
+ .injectKeyEvent(event, true);
+ } catch (RemoteException e) {
+ Log.i("Input", "DeadOjbectException");
+ }
+ }
+ }
+
+ /**
+ * Send a single key event.
+ *
+ * @param event is a string representing the keycode of the key event you
+ * want to execute.
+ */
+ private void sendKeyEvent(String event) {
+ int eventCode = Integer.parseInt(event);
+ long now = SystemClock.uptimeMillis();
+ Log.i("SendKeyEvent", event);
+ try {
+ KeyEvent down = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, eventCode, 0);
+ KeyEvent up = new KeyEvent(now, now, KeyEvent.ACTION_UP, eventCode, 0);
+ (IWindowManager.Stub
+ .asInterface(ServiceManager.getService("window")))
+ .injectKeyEvent(down, true);
+ (IWindowManager.Stub
+ .asInterface(ServiceManager.getService("window")))
+ .injectKeyEvent(up, true);
+ } catch (RemoteException e) {
+ Log.i("Input", "DeadOjbectException");
+ }
+ }
+
+ private void sendMotionEvent(long downTime, int action, float x, float y,
+ float pressure, float size) {
+ }
+
+ private void showUsage() {
+ System.err.println("usage: input [text|keyevent]");
+ System.err.println(" input text <string>");
+ System.err.println(" input keyevent <event_code>");
+ }
+}
diff --git a/cmds/installd/Android.mk b/cmds/installd/Android.mk
new file mode 100644
index 0000000..6673862
--- /dev/null
+++ b/cmds/installd/Android.mk
@@ -0,0 +1,21 @@
+ifneq ($(TARGET_SIMULATOR),true)
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ installd.c commands.c utils.c
+
+LOCAL_C_INCLUDES := \
+ $(call include-path-for, system-core)/cutils
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils
+
+LOCAL_STATIC_LIBRARIES :=
+
+LOCAL_MODULE:= installd
+
+include $(BUILD_EXECUTABLE)
+
+endif # !simulator))
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
new file mode 100644
index 0000000..70a1206
--- /dev/null
+++ b/cmds/installd/commands.c
@@ -0,0 +1,568 @@
+/*
+** Copyright 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.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include "installd.h"
+
+int install(const char *pkgname, uid_t uid, gid_t gid)
+{
+ char pkgdir[PKG_PATH_MAX];
+ char libdir[PKG_PATH_MAX];
+
+ if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) {
+ LOGE("invalid uid/gid: %d %d\n", uid, gid);
+ return -1;
+
+ }
+ if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX))
+ return -1;
+ if (create_pkg_path(libdir, PKG_LIB_PREFIX, pkgname, PKG_LIB_POSTFIX))
+ return -1;
+
+ if (mkdir(pkgdir, 0755) < 0) {
+ LOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno));
+ return -errno;
+ }
+ if (chown(pkgdir, uid, gid) < 0) {
+ LOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
+ unlink(pkgdir);
+ return -errno;
+ }
+ if (mkdir(libdir, 0755) < 0) {
+ LOGE("cannot create dir '%s': %s\n", libdir, strerror(errno));
+ unlink(pkgdir);
+ return -errno;
+ }
+ if (chown(libdir, AID_SYSTEM, AID_SYSTEM) < 0) {
+ LOGE("cannot chown dir '%s': %s\n", libdir, strerror(errno));
+ unlink(libdir);
+ unlink(pkgdir);
+ return -errno;
+ }
+ return 0;
+}
+
+int uninstall(const char *pkgname)
+{
+ char pkgdir[PKG_PATH_MAX];
+
+ if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX))
+ return -1;
+
+ /* delete contents AND directory, no exceptions */
+ return delete_dir_contents(pkgdir, 1, 0);
+}
+
+int delete_user_data(const char *pkgname)
+{
+ char pkgdir[PKG_PATH_MAX];
+
+ if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX))
+ return -1;
+
+ /* delete contents, excluding "lib", but not the directory itself */
+ return delete_dir_contents(pkgdir, 0, "lib");
+}
+
+int delete_cache(const char *pkgname)
+{
+ char cachedir[PKG_PATH_MAX];
+
+ if (create_pkg_path(cachedir, CACHE_DIR_PREFIX, pkgname, CACHE_DIR_POSTFIX))
+ return -1;
+
+ /* delete contents, not the directory, no exceptions */
+ return delete_dir_contents(cachedir, 0, 0);
+}
+
+
+static int disk_free(void)
+{
+ struct statfs sfs;
+ if (statfs(PKG_DIR_PREFIX, &sfs) == 0) {
+ return sfs.f_bavail * sfs.f_bsize;
+ } else {
+ return -1;
+ }
+}
+
+
+/* Try to ensure free_size bytes of storage are available.
+ * Returns 0 on success.
+ * This is rather simple-minded because doing a full LRU would
+ * be potentially memory-intensive, and without atime it would
+ * also require that apps constantly modify file metadata even
+ * when just reading from the cache, which is pretty awful.
+ */
+int free_cache(int free_size)
+{
+ const char *name;
+ int dfd, subfd;
+ DIR *d;
+ struct dirent *de;
+ int avail;
+
+ avail = disk_free();
+ if (avail < 0) return -1;
+
+ LOGI("free_cache(%d) avail %d\n", free_size, avail);
+ if (avail >= free_size) return 0;
+
+ d = opendir(PKG_DIR_PREFIX);
+ if (d == NULL) {
+ LOGE("cannot open %s\n", PKG_DIR_PREFIX);
+ return -1;
+ }
+ dfd = dirfd(d);
+
+ while ((de = readdir(d))) {
+ if (de->d_type != DT_DIR) continue;
+ name = de->d_name;
+
+ /* always skip "." and ".." */
+ if (name[0] == '.') {
+ if (name[1] == 0) continue;
+ if ((name[1] == '.') && (name[2] == 0)) continue;
+ }
+
+ subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
+ if (subfd < 0) continue;
+
+ delete_dir_contents_fd(subfd, "cache");
+ close(subfd);
+
+ avail = disk_free();
+ if (avail >= free_size) {
+ closedir(d);
+ return 0;
+ }
+ }
+ closedir(d);
+ return -1;
+}
+
+
+/* used by move_dex, rm_dex, etc to ensure that the provided paths
+ * don't point anywhere other than at the APK_DIR_PREFIX
+ */
+static int is_valid_apk_path(const char *path)
+{
+ int len = strlen(APK_DIR_PREFIX);
+ if (strncmp(path, APK_DIR_PREFIX, len)) {
+ len = strlen(PROTECTED_DIR_PREFIX);
+ if (strncmp(path, PROTECTED_DIR_PREFIX, len)) {
+ LOGE("invalid apk path '%s' (bad prefix)\n", path);
+ return 0;
+ }
+ }
+ if (strchr(path + len, '/')) {
+ LOGE("invalid apk path '%s' (subdir?)\n", path);
+ return 0;
+ }
+ if (path[len] == '.') {
+ LOGE("invalid apk path '%s' (trickery)\n", path);
+ return 0;
+ }
+ return 1;
+}
+
+int move_dex(const char *src, const char *dst)
+{
+ char src_dex[PKG_PATH_MAX];
+ char dst_dex[PKG_PATH_MAX];
+
+ if (!is_valid_apk_path(src)) return -1;
+ if (!is_valid_apk_path(dst)) return -1;
+
+ if (create_cache_path(src_dex, src)) return -1;
+ if (create_cache_path(dst_dex, dst)) return -1;
+
+ LOGI("move %s -> %s\n", src_dex, dst_dex);
+ if (rename(src_dex, dst_dex) < 0) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+int rm_dex(const char *path)
+{
+ char dex_path[PKG_PATH_MAX];
+
+ if (!is_valid_apk_path(path)) return -1;
+ if (create_cache_path(dex_path, path)) return -1;
+
+ LOGI("unlink %s\n", dex_path);
+ if (unlink(dex_path) < 0) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+int protect(char *pkgname, gid_t gid)
+{
+ struct stat s;
+ char pkgpath[PKG_PATH_MAX];
+
+ if (gid < AID_SYSTEM) return -1;
+
+ if (create_pkg_path(pkgpath, PROTECTED_DIR_PREFIX, pkgname, ".apk"))
+ return -1;
+
+ if (stat(pkgpath, &s) < 0) return -1;
+
+ if (chown(pkgpath, s.st_uid, gid) < 0) {
+ LOGE("failed to chgrp '%s': %s\n", pkgpath, strerror(errno));
+ return -1;
+ }
+
+ if (chmod(pkgpath, S_IRUSR|S_IWUSR|S_IRGRP) < 0) {
+ LOGE("failed to chmod '%s': %s\n", pkgpath, strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int stat_size(struct stat *s)
+{
+ int blksize = s->st_blksize;
+ int size = s->st_size;
+
+ if (blksize) {
+ /* round up to filesystem block size */
+ size = (size + blksize - 1) & (~(blksize - 1));
+ }
+
+ return size;
+}
+
+static int calculate_dir_size(int dfd)
+{
+ int size = 0;
+ struct stat s;
+ DIR *d;
+ struct dirent *de;
+
+ d = fdopendir(dfd);
+ if (d == NULL) {
+ close(dfd);
+ return 0;
+ }
+
+ while ((de = readdir(d))) {
+ const char *name = de->d_name;
+ if (de->d_type == DT_DIR) {
+ int subfd;
+ /* always skip "." and ".." */
+ if (name[0] == '.') {
+ if (name[1] == 0) continue;
+ if ((name[1] == '.') && (name[2] == 0)) continue;
+ }
+ subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
+ if (subfd >= 0) {
+ size += calculate_dir_size(subfd);
+ }
+ } else {
+ if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
+ size += stat_size(&s);
+ }
+ }
+ }
+ closedir(d);
+ return size;
+}
+
+int get_size(const char *pkgname, const char *apkpath,
+ const char *fwdlock_apkpath,
+ int *_codesize, int *_datasize, int *_cachesize)
+{
+ DIR *d;
+ int dfd;
+ struct dirent *de;
+ struct stat s;
+ char path[PKG_PATH_MAX];
+
+ int codesize = 0;
+ int datasize = 0;
+ int cachesize = 0;
+
+ /* count the source apk as code -- but only if it's not
+ * on the /system partition
+ */
+ if (strncmp(apkpath, "/system", 7) != 0) {
+ if (stat(apkpath, &s) == 0) {
+ codesize += stat_size(&s);
+ }
+ }
+ /* count the forward locked apk as code if it is given
+ */
+ if (fwdlock_apkpath != NULL && fwdlock_apkpath[0] != '!') {
+ if (stat(fwdlock_apkpath, &s) == 0) {
+ codesize += stat_size(&s);
+ }
+ }
+
+
+ /* count the cached dexfile as code */
+ if (!create_cache_path(path, apkpath)) {
+ if (stat(path, &s) == 0) {
+ codesize += stat_size(&s);
+ }
+ }
+
+ if (create_pkg_path(path, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) {
+ goto done;
+ }
+
+ d = opendir(path);
+ if (d == NULL) {
+ goto done;
+ }
+ dfd = dirfd(d);
+
+ /* most stuff in the pkgdir is data, except for the "cache"
+ * directory and below, which is cache, and the "lib" directory
+ * and below, which is code...
+ */
+ while ((de = readdir(d))) {
+ const char *name = de->d_name;
+
+ if (de->d_type == DT_DIR) {
+ int subfd;
+ /* always skip "." and ".." */
+ if (name[0] == '.') {
+ if (name[1] == 0) continue;
+ if ((name[1] == '.') && (name[2] == 0)) continue;
+ }
+ subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
+ if (subfd >= 0) {
+ int size = calculate_dir_size(subfd);
+ if (!strcmp(name,"lib")) {
+ codesize += size;
+ } else if(!strcmp(name,"cache")) {
+ cachesize += size;
+ } else {
+ datasize += size;
+ }
+ }
+ } else {
+ if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
+ datasize += stat_size(&s);
+ }
+ }
+ }
+ closedir(d);
+done:
+ *_codesize = codesize;
+ *_datasize = datasize;
+ *_cachesize = cachesize;
+ return 0;
+}
+
+
+/* a simpler version of dexOptGenerateCacheFileName() */
+int create_cache_path(char path[PKG_PATH_MAX], const char *src)
+{
+ char *tmp;
+ int srclen;
+ int dstlen;
+
+ srclen = strlen(src);
+
+ /* demand that we are an absolute path */
+ if ((src == 0) || (src[0] != '/') || strstr(src,"..")) {
+ return -1;
+ }
+
+ if (srclen > PKG_PATH_MAX) { // XXX: PKG_NAME_MAX?
+ return -1;
+ }
+
+ dstlen = srclen + strlen(DALVIK_CACHE_PREFIX) +
+ strlen(DALVIK_CACHE_POSTFIX) + 1;
+
+ if (dstlen > PKG_PATH_MAX) {
+ return -1;
+ }
+
+ sprintf(path,"%s%s%s",
+ DALVIK_CACHE_PREFIX,
+ src + 1, /* skip the leading / */
+ DALVIK_CACHE_POSTFIX);
+
+ for(tmp = path + strlen(DALVIK_CACHE_PREFIX); *tmp; tmp++) {
+ if (*tmp == '/') {
+ *tmp = '@';
+ }
+ }
+
+ return 0;
+}
+
+static void run_dexopt(int zip_fd, int odex_fd, const char* input_file_name,
+ const char* dexopt_flags)
+{
+ static const char* DEX_OPT_BIN = "/system/bin/dexopt";
+ static const int MAX_INT_LEN = 12; // '-'+10dig+'\0' -OR- 0x+8dig
+ char zip_num[MAX_INT_LEN];
+ char odex_num[MAX_INT_LEN];
+
+ sprintf(zip_num, "%d", zip_fd);
+ sprintf(odex_num, "%d", odex_fd);
+
+ execl(DEX_OPT_BIN, DEX_OPT_BIN, "--zip", zip_num, odex_num, input_file_name,
+ dexopt_flags, (char*) NULL);
+ LOGE("execl(%s) failed: %s\n", DEX_OPT_BIN, strerror(errno));
+}
+
+static int wait_dexopt(pid_t pid, const char* apk_path)
+{
+ int status;
+ pid_t got_pid;
+
+ /*
+ * Wait for the optimization process to finish.
+ */
+ while (1) {
+ got_pid = waitpid(pid, &status, 0);
+ if (got_pid == -1 && errno == EINTR) {
+ printf("waitpid interrupted, retrying\n");
+ } else {
+ break;
+ }
+ }
+ if (got_pid != pid) {
+ LOGW("waitpid failed: wanted %d, got %d: %s\n",
+ (int) pid, (int) got_pid, strerror(errno));
+ return 1;
+ }
+
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
+ LOGD("DexInv: --- END '%s' (success) ---\n", apk_path);
+ return 0;
+ } else {
+ LOGW("DexInv: --- END '%s' --- status=0x%04x, process failed\n",
+ apk_path, status);
+ return status; /* always nonzero */
+ }
+}
+
+int dexopt(const char *apk_path, uid_t uid, int is_public)
+{
+ struct utimbuf ut;
+ struct stat apk_stat, dex_stat;
+ char dex_path[PKG_PATH_MAX];
+ char dexopt_flags[PROPERTY_VALUE_MAX];
+ char *end;
+ int res, zip_fd=-1, odex_fd=-1;
+
+ /* Before anything else: is there a .odex file? If so, we have
+ * pre-optimized the apk and there is nothing to do here.
+ */
+ if (strlen(apk_path) >= (PKG_PATH_MAX - 8)) {
+ return -1;
+ }
+
+ /* platform-specific flags affecting optimization and verification */
+ property_get("dalvik.vm.dexopt-flags", dexopt_flags, "");
+
+ strcpy(dex_path, apk_path);
+ end = strrchr(dex_path, '.');
+ if (end != NULL) {
+ strcpy(end, ".odex");
+ if (stat(dex_path, &dex_stat) == 0) {
+ return 0;
+ }
+ }
+
+ if (create_cache_path(dex_path, apk_path)) {
+ return -1;
+ }
+
+ memset(&apk_stat, 0, sizeof(apk_stat));
+ stat(apk_path, &apk_stat);
+
+ zip_fd = open(apk_path, O_RDONLY, 0);
+ if (zip_fd < 0) {
+ LOGE("dexopt cannot open '%s' for input\n", apk_path);
+ return -1;
+ }
+
+ unlink(dex_path);
+ odex_fd = open(dex_path, O_RDWR | O_CREAT | O_EXCL, 0644);
+ if (odex_fd < 0) {
+ LOGE("dexopt cannot open '%s' for output\n", dex_path);
+ goto fail;
+ }
+ if (fchown(odex_fd, AID_SYSTEM, uid) < 0) {
+ LOGE("dexopt cannot chown '%s'\n", dex_path);
+ goto fail;
+ }
+ if (fchmod(odex_fd,
+ S_IRUSR|S_IWUSR|S_IRGRP |
+ (is_public ? S_IROTH : 0)) < 0) {
+ LOGE("dexopt cannot chmod '%s'\n", dex_path);
+ goto fail;
+ }
+
+ LOGD("DexInv: --- BEGIN '%s' ---\n", apk_path);
+
+ pid_t pid;
+ pid = fork();
+ if (pid == 0) {
+ /* child -- drop privileges before continuing */
+ if (setgid(uid) != 0) {
+ LOGE("setgid(%d) failed during dexopt\n", uid);
+ exit(64);
+ }
+ if (setuid(uid) != 0) {
+ LOGE("setuid(%d) during dexopt\n", uid);
+ exit(65);
+ }
+ if (flock(odex_fd, LOCK_EX | LOCK_NB) != 0) {
+ LOGE("flock(%s) failed: %s\n", dex_path, strerror(errno));
+ exit(66);
+ }
+
+ run_dexopt(zip_fd, odex_fd, apk_path, dexopt_flags);
+ exit(67); /* only get here on exec failure */
+ } else {
+ res = wait_dexopt(pid, apk_path);
+ if (res != 0) {
+ LOGE("dexopt failed on '%s' res = %d\n", dex_path, res);
+ goto fail;
+ }
+ }
+
+ ut.actime = apk_stat.st_atime;
+ ut.modtime = apk_stat.st_mtime;
+ utime(dex_path, &ut);
+
+ close(odex_fd);
+ close(zip_fd);
+ return 0;
+
+fail:
+ if (odex_fd >= 0) {
+ close(odex_fd);
+ unlink(dex_path);
+ }
+ if (zip_fd >= 0) {
+ close(zip_fd);
+ }
+ return -1;
+}
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
new file mode 100644
index 0000000..7c7441f
--- /dev/null
+++ b/cmds/installd/installd.c
@@ -0,0 +1,259 @@
+/*
+** Copyright 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.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include "installd.h"
+
+
+#define BUFFER_MAX 1024 /* input buffer for commands */
+#define TOKEN_MAX 8 /* max number of arguments in buffer */
+#define REPLY_MAX 256 /* largest reply allowed */
+
+
+static int do_ping(char **arg, char reply[REPLY_MAX])
+{
+ return 0;
+}
+
+static int do_install(char **arg, char reply[REPLY_MAX])
+{
+ return install(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, gid */
+}
+
+static int do_dexopt(char **arg, char reply[REPLY_MAX])
+{
+ /* apk_path, uid, is_public */
+ return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]));
+}
+
+static int do_move_dex(char **arg, char reply[REPLY_MAX])
+{
+ return move_dex(arg[0], arg[1]); /* src, dst */
+}
+
+static int do_rm_dex(char **arg, char reply[REPLY_MAX])
+{
+ return rm_dex(arg[0]); /* pkgname */
+}
+
+static int do_remove(char **arg, char reply[REPLY_MAX])
+{
+ return uninstall(arg[0]); /* pkgname */
+}
+
+static int do_free_cache(char **arg, char reply[REPLY_MAX]) /* TODO int:free_size */
+{
+ return free_cache(atoi(arg[0])); /* free_size */
+}
+
+static int do_rm_cache(char **arg, char reply[REPLY_MAX])
+{
+ return delete_cache(arg[0]); /* pkgname */
+}
+
+static int do_protect(char **arg, char reply[REPLY_MAX])
+{
+ return protect(arg[0], atoi(arg[1])); /* pkgname, gid */
+}
+
+static int do_get_size(char **arg, char reply[REPLY_MAX])
+{
+ int codesize = 0;
+ int datasize = 0;
+ int cachesize = 0;
+ int res = 0;
+
+ /* pkgdir, apkpath */
+ res = get_size(arg[0], arg[1], arg[2], &codesize, &datasize, &cachesize);
+
+ sprintf(reply,"%d %d %d", codesize, datasize, cachesize);
+ return res;
+}
+
+static int do_rm_user_data(char **arg, char reply[REPLY_MAX])
+{
+ return delete_user_data(arg[0]); /* pkgname */
+}
+
+struct cmdinfo {
+ const char *name;
+ unsigned numargs;
+ int (*func)(char **arg, char reply[REPLY_MAX]);
+};
+
+struct cmdinfo cmds[] = {
+ { "ping", 0, do_ping },
+ { "install", 3, do_install },
+ { "dexopt", 3, do_dexopt },
+ { "movedex", 2, do_move_dex },
+ { "rmdex", 1, do_rm_dex },
+ { "remove", 1, do_remove },
+ { "freecache", 1, do_free_cache },
+ { "rmcache", 1, do_rm_cache },
+ { "protect", 2, do_protect },
+ { "getsize", 3, do_get_size },
+ { "rmuserdata", 1, do_rm_user_data },
+};
+
+static int readx(int s, void *_buf, int count)
+{
+ char *buf = _buf;
+ int n = 0, r;
+ if (count < 0) return -1;
+ while (n < count) {
+ r = read(s, buf + n, count - n);
+ if (r < 0) {
+ if (errno == EINTR) continue;
+ LOGE("read error: %s\n", strerror(errno));
+ return -1;
+ }
+ if (r == 0) {
+ LOGE("eof\n");
+ return -1; /* EOF */
+ }
+ n += r;
+ }
+ return 0;
+}
+
+static int writex(int s, const void *_buf, int count)
+{
+ const char *buf = _buf;
+ int n = 0, r;
+ if (count < 0) return -1;
+ while (n < count) {
+ r = write(s, buf + n, count - n);
+ if (r < 0) {
+ if (errno == EINTR) continue;
+ LOGE("write error: %s\n", strerror(errno));
+ return -1;
+ }
+ n += r;
+ }
+ return 0;
+}
+
+
+/* Tokenize the command buffer, locate a matching command,
+ * ensure that the required number of arguments are provided,
+ * call the function(), return the result.
+ */
+static int execute(int s, char cmd[BUFFER_MAX])
+{
+ char reply[REPLY_MAX];
+ char *arg[TOKEN_MAX+1];
+ unsigned i;
+ unsigned n = 0;
+ unsigned short count;
+ int ret = -1;
+
+// LOGI("execute('%s')\n", cmd);
+
+ /* default reply is "" */
+ reply[0] = 0;
+
+ /* n is number of args (not counting arg[0]) */
+ arg[0] = cmd;
+ while (*cmd) {
+ if (isspace(*cmd)) {
+ *cmd++ = 0;
+ n++;
+ arg[n] = cmd;
+ if (n == TOKEN_MAX) {
+ LOGE("too many arguments\n");
+ goto done;
+ }
+ }
+ cmd++;
+ }
+
+ for (i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++) {
+ if (!strcmp(cmds[i].name,arg[0])) {
+ if (n != cmds[i].numargs) {
+ LOGE("%s requires %d arguments (%d given)\n",
+ cmds[i].name, cmds[i].numargs, n);
+ } else {
+ ret = cmds[i].func(arg + 1, reply);
+ }
+ goto done;
+ }
+ }
+ LOGE("unsupported command '%s'\n", arg[0]);
+
+done:
+ if (reply[0]) {
+ n = snprintf(cmd, BUFFER_MAX, "%d %s", ret, reply);
+ } else {
+ n = snprintf(cmd, BUFFER_MAX, "%d", ret);
+ }
+ if (n > BUFFER_MAX) n = BUFFER_MAX;
+ count = n;
+
+// LOGI("reply: '%s'\n", cmd);
+ if (writex(s, &count, sizeof(count))) return -1;
+ if (writex(s, cmd, count)) return -1;
+ return 0;
+}
+
+int main(const int argc, const char *argv[]) {
+ char buf[BUFFER_MAX];
+ struct sockaddr addr;
+ socklen_t alen;
+ int lsocket, s, count;
+
+ lsocket = android_get_control_socket(SOCKET_PATH);
+ if (lsocket < 0) {
+ LOGE("Failed to get socket from environment: %s\n", strerror(errno));
+ exit(1);
+ }
+ if (listen(lsocket, 5)) {
+ LOGE("Listen on socket failed: %s\n", strerror(errno));
+ exit(1);
+ }
+ fcntl(lsocket, F_SETFD, FD_CLOEXEC);
+
+ for (;;) {
+ alen = sizeof(addr);
+ s = accept(lsocket, &addr, &alen);
+ if (s < 0) {
+ LOGE("Accept failed: %s\n", strerror(errno));
+ continue;
+ }
+ fcntl(s, F_SETFD, FD_CLOEXEC);
+
+ LOGI("new connection\n");
+ for (;;) {
+ unsigned short count;
+ if (readx(s, &count, sizeof(count))) {
+ LOGE("failed to read size\n");
+ break;
+ }
+ if ((count < 1) || (count >= BUFFER_MAX)) {
+ LOGE("invalid size %d\n", count);
+ break;
+ }
+ if (readx(s, buf, count)) {
+ LOGE("failed to read command\n");
+ break;
+ }
+ buf[count] = 0;
+ if (execute(s, buf)) break;
+ }
+ LOGI("closing connection\n");
+ close(s);
+ }
+
+ return 0;
+}
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
new file mode 100644
index 0000000..db3badd
--- /dev/null
+++ b/cmds/installd/installd.h
@@ -0,0 +1,100 @@
+/*
+**
+** Copyright 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.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#define LOG_TAG "installd"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <utime.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <cutils/sockets.h>
+#include <cutils/log.h>
+#include <cutils/properties.h>
+
+#include <private/android_filesystem_config.h>
+
+#if INCLUDE_SYS_MOUNT_FOR_STATFS
+#include <sys/mount.h>
+#else
+#include <sys/statfs.h>
+#endif
+
+#define SOCKET_PATH "installd"
+
+
+/* elements combined with a valid package name to form paths */
+
+#define PKG_DIR_PREFIX "/data/data/"
+#define PKG_DIR_POSTFIX ""
+
+#define PKG_LIB_PREFIX "/data/data/"
+#define PKG_LIB_POSTFIX "/lib"
+
+#define CACHE_DIR_PREFIX "/data/data/"
+#define CACHE_DIR_POSTFIX "/cache"
+
+#define APK_DIR_PREFIX "/data/app/"
+
+/* other handy constants */
+
+#define PROTECTED_DIR_PREFIX "/data/app-private/"
+
+#define DALVIK_CACHE_PREFIX "/data/dalvik-cache/"
+#define DALVIK_CACHE_POSTFIX "/classes.dex"
+
+
+#define PKG_NAME_MAX 128 /* largest allowed package name */
+#define PKG_PATH_MAX 256 /* max size of any path we use */
+
+
+/* util.c */
+
+int create_pkg_path(char path[PKG_PATH_MAX],
+ const char *prefix,
+ const char *pkgname,
+ const char *postfix);
+
+int create_cache_path(char path[PKG_PATH_MAX], const char *src);
+
+int delete_dir_contents(const char *pathname,
+ int also_delete_dir,
+ const char *ignore);
+
+int delete_dir_contents_fd(int dfd, const char *name);
+
+/* commands.c */
+
+int install(const char *pkgname, uid_t uid, gid_t gid);
+int uninstall(const char *pkgname);
+int delete_user_data(const char *pkgname);
+int delete_cache(const char *pkgname);
+int move_dex(const char *src, const char *dst);
+int rm_dex(const char *path);
+int protect(char *pkgname, gid_t gid);
+int get_size(const char *pkgname, const char *apkpath, const char *fwdlock_apkpath,
+ int *codesize, int *datasize, int *cachesize);
+int free_cache(int free_size);
+int dexopt(const char *apk_path, uid_t uid, int is_public);
diff --git a/cmds/installd/utils.c b/cmds/installd/utils.c
new file mode 100644
index 0000000..5db5545
--- /dev/null
+++ b/cmds/installd/utils.c
@@ -0,0 +1,149 @@
+/*
+** Copyright 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.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include "installd.h"
+
+int create_pkg_path(char path[PKG_PATH_MAX],
+ const char *prefix,
+ const char *pkgname,
+ const char *postfix)
+{
+ int len;
+ const char *x;
+
+ len = strlen(pkgname);
+ if (len > PKG_NAME_MAX) {
+ return -1;
+ }
+ if ((len + strlen(prefix) + strlen(postfix)) >= PKG_PATH_MAX) {
+ return -1;
+ }
+
+ x = pkgname;
+ while (*x) {
+ if (isalnum(*x) || (*x == '_')) {
+ /* alphanumeric or underscore are fine */
+ } else if (*x == '.') {
+ if ((x == pkgname) || (x[1] == '.') || (x[1] == 0)) {
+ /* periods must not be first, last, or doubled */
+ LOGE("invalid package name '%s'\n", pkgname);
+ return -1;
+ }
+ } else {
+ /* anything not A-Z, a-z, 0-9, _, or . is invalid */
+ LOGE("invalid package name '%s'\n", pkgname);
+ return -1;
+ }
+ x++;
+ }
+
+ sprintf(path, "%s%s%s", prefix, pkgname, postfix);
+ return 0;
+}
+
+static int _delete_dir_contents(DIR *d, const char *ignore)
+{
+ int result = 0;
+ struct dirent *de;
+ int dfd;
+
+ dfd = dirfd(d);
+
+ if (dfd < 0) return -1;
+
+ while ((de = readdir(d))) {
+ const char *name = de->d_name;
+
+ /* skip the ignore name if provided */
+ if (ignore && !strcmp(name, ignore)) continue;
+
+ if (de->d_type == DT_DIR) {
+ int r, subfd;
+ DIR *subdir;
+
+ /* always skip "." and ".." */
+ if (name[0] == '.') {
+ if (name[1] == 0) continue;
+ if ((name[1] == '.') && (name[2] == 0)) continue;
+ }
+
+ subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
+ if (subfd < 0) {
+ result = -1;
+ continue;
+ }
+ subdir = fdopendir(subfd);
+ if (subdir == NULL) {
+ close(subfd);
+ result = -1;
+ continue;
+ }
+ if (_delete_dir_contents(subdir, 0)) {
+ result = -1;
+ }
+ closedir(subdir);
+ if (unlinkat(dfd, name, AT_REMOVEDIR) < 0) {
+ result = -1;
+ }
+ } else {
+ if (unlinkat(dfd, name, 0) < 0) {
+ result = -1;
+ }
+ }
+ }
+
+ return result;
+}
+
+int delete_dir_contents(const char *pathname,
+ int also_delete_dir,
+ const char *ignore)
+{
+ int res = 0;
+ DIR *d;
+
+ d = opendir(pathname);
+ if (d == NULL) {
+ return -errno;
+ }
+ res = _delete_dir_contents(d, ignore);
+ closedir(d);
+ if (also_delete_dir) {
+ if (rmdir(pathname)) {
+ res = -1;
+ }
+ }
+ return res;
+}
+
+int delete_dir_contents_fd(int dfd, const char *name)
+{
+ int fd, res;
+ DIR *d;
+
+ fd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
+ if (fd < 0) {
+ return -1;
+ }
+ d = fdopendir(fd);
+ if (d == NULL) {
+ close(fd);
+ return -1;
+ }
+ res = _delete_dir_contents(d, 0);
+ closedir(d);
+ return res;
+}
diff --git a/cmds/pm/Android.mk b/cmds/pm/Android.mk
new file mode 100644
index 0000000..7911d62
--- /dev/null
+++ b/cmds/pm/Android.mk
@@ -0,0 +1,15 @@
+# Copyright 2007 The Android Open Source Project
+#
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_MODULE := pm
+include $(BUILD_JAVA_LIBRARY)
+
+
+include $(CLEAR_VARS)
+ALL_PREBUILT += $(TARGET_OUT)/bin/pm
+$(TARGET_OUT)/bin/pm : $(LOCAL_PATH)/pm | $(ACP)
+ $(transform-prebuilt-to-target)
+
diff --git a/cmds/pm/MODULE_LICENSE_APACHE2 b/cmds/pm/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cmds/pm/MODULE_LICENSE_APACHE2
diff --git a/cmds/pm/NOTICE b/cmds/pm/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/cmds/pm/NOTICE
@@ -0,0 +1,190 @@
+
+ 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
+
diff --git a/cmds/pm/pm b/cmds/pm/pm
new file mode 100755
index 0000000..8183838
--- /dev/null
+++ b/cmds/pm/pm
@@ -0,0 +1,7 @@
+# Script to start "pm" on the device, which has a very rudimentary
+# shell.
+#
+base=/system
+export CLASSPATH=$base/framework/pm.jar
+exec app_process $base/bin com.android.commands.pm.Pm "$@"
+
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
new file mode 100644
index 0000000..c2d8da5
--- /dev/null
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -0,0 +1,845 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.commands.pm;
+
+import android.content.ComponentName;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageDeleteObserver;
+import android.content.pm.IPackageInstallObserver;
+import android.content.pm.IPackageManager;
+import android.content.pm.InstrumentationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageItemInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PermissionGroupInfo;
+import android.content.pm.PermissionInfo;
+import android.content.res.AssetManager;
+import android.content.res.Resources;
+import android.net.Uri;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.WeakHashMap;
+
+public final class Pm {
+ IPackageManager mPm;
+
+ private WeakHashMap<String, Resources> mResourceCache
+ = new WeakHashMap<String, Resources>();
+
+ private String[] mArgs;
+ private int mNextArg;
+ private String mCurArgData;
+
+ private static final String PM_NOT_RUNNING_ERR =
+ "Error: Could not access the Package Manager. Is the system running?";
+
+ public static void main(String[] args) {
+ new Pm().run(args);
+ }
+
+ public void run(String[] args) {
+ boolean validCommand = false;
+ if (args.length < 1) {
+ showUsage();
+ return;
+ }
+
+ mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
+ if (mPm == null) {
+ System.err.println(PM_NOT_RUNNING_ERR);
+ return;
+ }
+
+ mArgs = args;
+ String op = args[0];
+ mNextArg = 1;
+
+ if ("list".equals(op)) {
+ runList();
+ return;
+ }
+
+ if ("path".equals(op)) {
+ runPath();
+ return;
+ }
+
+ if ("install".equals(op)) {
+ runInstall();
+ return;
+ }
+
+ if ("uninstall".equals(op)) {
+ runUninstall();
+ return;
+ }
+
+ if ("enable".equals(op)) {
+ runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
+ return;
+ }
+
+ if ("disable".equals(op)) {
+ runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
+ return;
+ }
+
+ try {
+ if (args.length == 1) {
+ if (args[0].equalsIgnoreCase("-l")) {
+ validCommand = true;
+ runListPackages(false);
+ } else if (args[0].equalsIgnoreCase("-lf")){
+ validCommand = true;
+ runListPackages(true);
+ }
+ } else if (args.length == 2) {
+ if (args[0].equalsIgnoreCase("-p")) {
+ validCommand = true;
+ displayPackageFilePath(args[1]);
+ }
+ }
+ } finally {
+ if (validCommand == false) {
+ if (op != null) {
+ System.err.println("Error: unknown command '" + op + "'");
+ }
+ showUsage();
+ }
+ }
+ }
+
+ /**
+ * Execute the list sub-command.
+ *
+ * pm list [package | packages]
+ * pm list permission-groups
+ * pm list permissions
+ * pm list instrumentation
+ */
+ private void runList() {
+ String type = nextArg();
+ if (type == null) {
+ System.err.println("Error: didn't specify type of data to list");
+ showUsage();
+ return;
+ }
+ if ("package".equals(type) || "packages".equals(type)) {
+ runListPackages(false);
+ } else if ("permission-groups".equals(type)) {
+ runListPermissionGroups();
+ } else if ("permissions".equals(type)) {
+ runListPermissions();
+ } else if ("instrumentation".equals(type)) {
+ runListInstrumentation();
+ } else {
+ System.err.println("Error: unknown list type '" + type + "'");
+ showUsage();
+ }
+ }
+
+ /**
+ * Lists all the installed packages.
+ */
+ private void runListPackages(boolean showApplicationPackage) {
+ try {
+ String opt;
+ while ((opt=nextOption()) != null) {
+ if (opt.equals("-l")) {
+ // old compat
+ } else if (opt.equals("-lf")) {
+ showApplicationPackage = true;
+ } else if (opt.equals("-f")) {
+ showApplicationPackage = true;
+ } else {
+ System.err.println("Error: Unknown option: " + opt);
+ showUsage();
+ return;
+ }
+ }
+ } catch (RuntimeException ex) {
+ System.err.println("Error: " + ex.toString());
+ showUsage();
+ return;
+ }
+
+ try {
+ List<PackageInfo> packages = mPm.getInstalledPackages(0 /* all */);
+
+ int count = packages.size();
+ for (int p = 0 ; p < count ; p++) {
+ PackageInfo info = packages.get(p);
+ System.out.print("package:");
+ if (showApplicationPackage) {
+ System.out.print(info.applicationInfo.sourceDir);
+ System.out.print("=");
+ }
+ System.out.println(info.packageName);
+ }
+ } catch (RemoteException e) {
+ System.err.println(e.toString());
+ System.err.println(PM_NOT_RUNNING_ERR);
+ }
+ }
+
+ /**
+ * Lists all of the installed instrumentation, or all for a given package
+ *
+ * pm list instrumentation [package] [-f]
+ */
+ private void runListInstrumentation() {
+ int flags = 0; // flags != 0 is only used to request meta-data
+ boolean showPackage = false;
+ String targetPackage = null;
+
+ try {
+ String opt;
+ while ((opt=nextArg()) != null) {
+ if (opt.equals("-f")) {
+ showPackage = true;
+ } else if (opt.charAt(0) != '-') {
+ targetPackage = opt;
+ } else {
+ System.err.println("Error: Unknown option: " + opt);
+ showUsage();
+ return;
+ }
+ }
+ } catch (RuntimeException ex) {
+ System.err.println("Error: " + ex.toString());
+ showUsage();
+ return;
+ }
+
+ try {
+ List<InstrumentationInfo> list = mPm.queryInstrumentation(targetPackage, flags);
+
+ // Sort by target package
+ Collections.sort(list, new Comparator<InstrumentationInfo>() {
+ public int compare(InstrumentationInfo o1, InstrumentationInfo o2) {
+ return o1.targetPackage.compareTo(o2.targetPackage);
+ }
+ });
+
+ int count = (list != null) ? list.size() : 0;
+ for (int p = 0; p < count; p++) {
+ InstrumentationInfo ii = list.get(p);
+ System.out.print("instrumentation:");
+ if (showPackage) {
+ System.out.print(ii.sourceDir);
+ System.out.print("=");
+ }
+ ComponentName cn = new ComponentName(ii.packageName, ii.name);
+ System.out.print(cn.flattenToShortString());
+ System.out.print(" (target=");
+ System.out.print(ii.targetPackage);
+ System.out.println(")");
+ }
+ } catch (RemoteException e) {
+ System.err.println(e.toString());
+ System.err.println(PM_NOT_RUNNING_ERR);
+ }
+ }
+
+ /**
+ * Lists all the known permission groups.
+ */
+ private void runListPermissionGroups() {
+ try {
+ List<PermissionGroupInfo> pgs = mPm.getAllPermissionGroups(0);
+
+ int count = pgs.size();
+ for (int p = 0 ; p < count ; p++) {
+ PermissionGroupInfo pgi = pgs.get(p);
+ System.out.print("permission group:");
+ System.out.println(pgi.name);
+ }
+ } catch (RemoteException e) {
+ System.err.println(e.toString());
+ System.err.println(PM_NOT_RUNNING_ERR);
+ }
+ }
+
+ private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized) {
+ if (nonLocalized != null) {
+ return nonLocalized.toString();
+ }
+ Resources r = getResources(pii);
+ if (r != null) {
+ return r.getString(res);
+ }
+ return null;
+ }
+
+ /**
+ * Lists all the permissions in a group.
+ */
+ private void runListPermissions() {
+ try {
+ boolean labels = false;
+ boolean groups = false;
+ boolean userOnly = false;
+ boolean summary = false;
+ boolean dangerousOnly = false;
+ String opt;
+ while ((opt=nextOption()) != null) {
+ if (opt.equals("-f")) {
+ labels = true;
+ } else if (opt.equals("-g")) {
+ groups = true;
+ } else if (opt.equals("-s")) {
+ groups = true;
+ labels = true;
+ summary = true;
+ } else if (opt.equals("-u")) {
+ userOnly = true;
+ } else if (opt.equals("-d")) {
+ dangerousOnly = true;
+ } else {
+ System.err.println("Error: Unknown option: " + opt);
+ showUsage();
+ return;
+ }
+ }
+
+ String grp = nextOption();
+ ArrayList<String> groupList = new ArrayList<String>();
+ if (groups) {
+ List<PermissionGroupInfo> infos =
+ mPm.getAllPermissionGroups(0);
+ for (int i=0; i<infos.size(); i++) {
+ groupList.add(infos.get(i).name);
+ }
+ groupList.add(null);
+ } else {
+ groupList.add(grp);
+ }
+
+ if (dangerousOnly) {
+ System.out.println("Dangerous Permissions:");
+ System.out.println("");
+ doListPermissions(groupList, groups, labels, summary,
+ PermissionInfo.PROTECTION_DANGEROUS,
+ PermissionInfo.PROTECTION_DANGEROUS);
+ if (userOnly) {
+ System.out.println("Normal Permissions:");
+ System.out.println("");
+ doListPermissions(groupList, groups, labels, summary,
+ PermissionInfo.PROTECTION_NORMAL,
+ PermissionInfo.PROTECTION_NORMAL);
+ }
+ } else if (userOnly) {
+ System.out.println("Dangerous and Normal Permissions:");
+ System.out.println("");
+ doListPermissions(groupList, groups, labels, summary,
+ PermissionInfo.PROTECTION_NORMAL,
+ PermissionInfo.PROTECTION_DANGEROUS);
+ } else {
+ System.out.println("All Permissions:");
+ System.out.println("");
+ doListPermissions(groupList, groups, labels, summary,
+ -10000, 10000);
+ }
+ } catch (RemoteException e) {
+ System.err.println(e.toString());
+ System.err.println(PM_NOT_RUNNING_ERR);
+ }
+ }
+
+ private void doListPermissions(ArrayList<String> groupList,
+ boolean groups, boolean labels, boolean summary,
+ int startProtectionLevel, int endProtectionLevel)
+ throws RemoteException {
+ for (int i=0; i<groupList.size(); i++) {
+ String groupName = groupList.get(i);
+ String prefix = "";
+ if (groups) {
+ if (i > 0) System.out.println("");
+ if (groupName != null) {
+ PermissionGroupInfo pgi = mPm.getPermissionGroupInfo(
+ groupName, 0);
+ if (summary) {
+ Resources res = getResources(pgi);
+ if (res != null) {
+ System.out.print(loadText(pgi, pgi.labelRes,
+ pgi.nonLocalizedLabel) + ": ");
+ } else {
+ System.out.print(pgi.name + ": ");
+
+ }
+ } else {
+ System.out.println((labels ? "+ " : "")
+ + "group:" + pgi.name);
+ if (labels) {
+ System.out.println(" package:" + pgi.packageName);
+ Resources res = getResources(pgi);
+ if (res != null) {
+ System.out.println(" label:"
+ + loadText(pgi, pgi.labelRes,
+ pgi.nonLocalizedLabel));
+ System.out.println(" description:"
+ + loadText(pgi, pgi.descriptionRes,
+ pgi.nonLocalizedDescription));
+ }
+ }
+ }
+ } else {
+ System.out.println(((labels && !summary)
+ ? "+ " : "") + "ungrouped:");
+ }
+ prefix = " ";
+ }
+ List<PermissionInfo> ps = mPm.queryPermissionsByGroup(
+ groupList.get(i), 0);
+ int count = ps.size();
+ boolean first = true;
+ for (int p = 0 ; p < count ; p++) {
+ PermissionInfo pi = ps.get(p);
+ if (groups && groupName == null && pi.group != null) {
+ continue;
+ }
+ if (pi.protectionLevel < startProtectionLevel
+ || pi.protectionLevel > endProtectionLevel) {
+ continue;
+ }
+ if (summary) {
+ if (first) {
+ first = false;
+ } else {
+ System.out.print(", ");
+ }
+ Resources res = getResources(pi);
+ if (res != null) {
+ System.out.print(loadText(pi, pi.labelRes,
+ pi.nonLocalizedLabel));
+ } else {
+ System.out.print(pi.name);
+ }
+ } else {
+ System.out.println(prefix + (labels ? "+ " : "")
+ + "permission:" + pi.name);
+ if (labels) {
+ System.out.println(prefix + " package:" + pi.packageName);
+ Resources res = getResources(pi);
+ if (res != null) {
+ System.out.println(prefix + " label:"
+ + loadText(pi, pi.labelRes,
+ pi.nonLocalizedLabel));
+ System.out.println(prefix + " description:"
+ + loadText(pi, pi.descriptionRes,
+ pi.nonLocalizedDescription));
+ }
+ String protLevel = "unknown";
+ switch(pi.protectionLevel) {
+ case PermissionInfo.PROTECTION_DANGEROUS:
+ protLevel = "dangerous";
+ break;
+ case PermissionInfo.PROTECTION_NORMAL:
+ protLevel = "normal";
+ break;
+ case PermissionInfo.PROTECTION_SIGNATURE:
+ protLevel = "signature";
+ break;
+ case PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM:
+ protLevel = "signatureOrSystem";
+ break;
+ }
+ System.out.println(prefix + " protectionLevel:" + protLevel);
+ }
+ }
+ }
+
+ if (summary) {
+ System.out.println("");
+ }
+ }
+ }
+
+ private void runPath() {
+ String pkg = nextArg();
+ if (pkg == null) {
+ System.err.println("Error: no package specified");
+ showUsage();
+ return;
+ }
+ displayPackageFilePath(pkg);
+ }
+
+ class PackageInstallObserver extends IPackageInstallObserver.Stub {
+ boolean finished;
+ int result;
+
+ public void packageInstalled(String name, int status) {
+ synchronized( this) {
+ finished = true;
+ result = status;
+ notifyAll();
+ }
+ }
+ }
+
+ private String installFailureToString(int result) {
+ String s;
+ switch (result) {
+ case PackageManager.INSTALL_FAILED_ALREADY_EXISTS:
+ s = "INSTALL_FAILED_ALREADY_EXISTS";
+ break;
+ case PackageManager.INSTALL_FAILED_INVALID_APK:
+ s = "INSTALL_FAILED_INVALID_APK";
+ break;
+ case PackageManager.INSTALL_FAILED_INVALID_URI:
+ s = "INSTALL_FAILED_INVALID_URI";
+ break;
+ case PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE:
+ s = "INSTALL_FAILED_INSUFFICIENT_STORAGE";
+ break;
+ case PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE:
+ s = "INSTALL_FAILED_DUPLICATE_PACKAGE";
+ break;
+ case PackageManager.INSTALL_FAILED_NO_SHARED_USER:
+ s = "INSTALL_FAILED_NO_SHARED_USER";
+ break;
+ case PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE:
+ s = "INSTALL_FAILED_UPDATE_INCOMPATIBLE";
+ break;
+ case PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE:
+ s = "INSTALL_FAILED_SHARED_USER_INCOMPATIBLE";
+ break;
+ case PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY:
+ s = "INSTALL_FAILED_MISSING_SHARED_LIBRARY";
+ break;
+ case PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE:
+ s = "INSTALL_FAILED_REPLACE_COULDNT_DELETE";
+ break;
+ case PackageManager.INSTALL_PARSE_FAILED_NOT_APK:
+ s = "INSTALL_PARSE_FAILED_NOT_APK";
+ break;
+ case PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST:
+ s = "INSTALL_PARSE_FAILED_BAD_MANIFEST";
+ break;
+ case PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION:
+ s = "INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION";
+ break;
+ case PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES:
+ s = "INSTALL_PARSE_FAILED_NO_CERTIFICATES";
+ break;
+ case PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES:
+ s = "INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES";
+ break;
+ case PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING:
+ s = "INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING";
+ break;
+ case PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME:
+ s = "INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME";
+ break;
+ case PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID:
+ s = "INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID";
+ break;
+ case PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED:
+ s = "INSTALL_PARSE_FAILED_MANIFEST_MALFORMED";
+ break;
+ case PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY:
+ s = "INSTALL_PARSE_FAILED_MANIFEST_EMPTY";
+ break;
+ case PackageManager.INSTALL_FAILED_OLDER_SDK:
+ s = "INSTALL_FAILED_OLDER_SDK";
+ break;
+ default:
+ s = Integer.toString(result);
+ break;
+ }
+ return s;
+ }
+
+ private void runInstall() {
+ int installFlags = 0;
+
+ String opt;
+ while ((opt=nextOption()) != null) {
+ if (opt.equals("-l")) {
+ installFlags |= PackageManager.FORWARD_LOCK_PACKAGE;
+ } else if (opt.equals("-r")) {
+ installFlags |= PackageManager.REPLACE_EXISTING_PACKAGE;
+ } else {
+ System.err.println("Error: Unknown option: " + opt);
+ showUsage();
+ return;
+ }
+ }
+
+ String apkFilePath = nextArg();
+ System.err.println("\tpkg: " + apkFilePath);
+ if (apkFilePath == null) {
+ System.err.println("Error: no package specified");
+ showUsage();
+ return;
+ }
+
+ PackageInstallObserver obs = new PackageInstallObserver();
+ try {
+ mPm.installPackage(Uri.fromFile(new File(apkFilePath)), obs, installFlags);
+
+ synchronized (obs) {
+ while (!obs.finished) {
+ try {
+ obs.wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ if (obs.result == PackageManager.INSTALL_SUCCEEDED) {
+ System.out.println("Success");
+ } else {
+ System.err.println("Failure ["
+ + installFailureToString(obs.result)
+ + "]");
+ }
+ }
+ } catch (RemoteException e) {
+ System.err.println(e.toString());
+ System.err.println(PM_NOT_RUNNING_ERR);
+ }
+ }
+
+ class PackageDeleteObserver extends IPackageDeleteObserver.Stub {
+ boolean finished;
+ boolean result;
+
+ public void packageDeleted(boolean succeeded) {
+ synchronized (this) {
+ finished = true;
+ result = succeeded;
+ notifyAll();
+ }
+ }
+ }
+
+ private void runUninstall() {
+ int unInstallFlags = 0;
+
+ String opt = nextOption();
+ if (opt != null && opt.equals("-k")) {
+ unInstallFlags = PackageManager.DONT_DELETE_DATA;
+ }
+
+ String pkg = nextArg();
+ if (pkg == null) {
+ System.err.println("Error: no package specified");
+ showUsage();
+ return;
+ }
+ boolean result = deletePackage(pkg, unInstallFlags);
+ if (result) {
+ System.out.println("Success");
+ } else {
+ System.out.println("Failure");
+ }
+ }
+
+ private boolean deletePackage(String pkg, int unInstallFlags) {
+ PackageDeleteObserver obs = new PackageDeleteObserver();
+ try {
+ mPm.deletePackage(pkg, obs, unInstallFlags);
+
+ synchronized (obs) {
+ while (!obs.finished) {
+ try {
+ obs.wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ } catch (RemoteException e) {
+ System.err.println(e.toString());
+ System.err.println(PM_NOT_RUNNING_ERR);
+ }
+ return obs.result;
+ }
+
+ private static String enabledSettingToString(int state) {
+ switch (state) {
+ case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT:
+ return "default";
+ case PackageManager.COMPONENT_ENABLED_STATE_ENABLED:
+ return "enabled";
+ case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
+ return "disabled";
+ }
+ return "unknown";
+ }
+
+ private void runSetEnabledSetting(int state) {
+ String pkg = nextArg();
+ if (pkg == null) {
+ System.err.println("Error: no package or component specified");
+ showUsage();
+ return;
+ }
+ ComponentName cn = ComponentName.unflattenFromString(pkg);
+ if (cn == null) {
+ try {
+ mPm.setApplicationEnabledSetting(pkg, state, 0);
+ System.err.println("Package " + pkg + " new state: "
+ + enabledSettingToString(
+ mPm.getApplicationEnabledSetting(pkg)));
+ } catch (RemoteException e) {
+ System.err.println(e.toString());
+ System.err.println(PM_NOT_RUNNING_ERR);
+ }
+ } else {
+ try {
+ mPm.setComponentEnabledSetting(cn, state, 0);
+ System.err.println("Component " + cn.toShortString() + " new state: "
+ + enabledSettingToString(
+ mPm.getComponentEnabledSetting(cn)));
+ } catch (RemoteException e) {
+ System.err.println(e.toString());
+ System.err.println(PM_NOT_RUNNING_ERR);
+ }
+ }
+ }
+
+ /**
+ * Displays the package file for a package.
+ * @param pckg
+ */
+ private void displayPackageFilePath(String pckg) {
+ try {
+ PackageInfo info = mPm.getPackageInfo(pckg, 0);
+ if (info != null && info.applicationInfo != null) {
+ System.out.print("package:");
+ System.out.println(info.applicationInfo.sourceDir);
+ }
+ } catch (RemoteException e) {
+ System.err.println(e.toString());
+ System.err.println(PM_NOT_RUNNING_ERR);
+ }
+ }
+
+ private Resources getResources(PackageItemInfo pii) {
+ Resources res = mResourceCache.get(pii.packageName);
+ if (res != null) return res;
+
+ try {
+ ApplicationInfo ai = mPm.getApplicationInfo(pii.packageName, 0);
+ AssetManager am = new AssetManager();
+ am.addAssetPath(ai.publicSourceDir);
+ res = new Resources(am, null, null);
+ mResourceCache.put(pii.packageName, res);
+ return res;
+ } catch (RemoteException e) {
+ System.err.println(e.toString());
+ System.err.println(PM_NOT_RUNNING_ERR);
+ return null;
+ }
+ }
+
+ private String nextOption() {
+ if (mNextArg >= mArgs.length) {
+ return null;
+ }
+ String arg = mArgs[mNextArg];
+ if (!arg.startsWith("-")) {
+ return null;
+ }
+ mNextArg++;
+ if (arg.equals("--")) {
+ return null;
+ }
+ if (arg.length() > 1 && arg.charAt(1) != '-') {
+ if (arg.length() > 2) {
+ mCurArgData = arg.substring(2);
+ return arg.substring(0, 2);
+ } else {
+ mCurArgData = null;
+ return arg;
+ }
+ }
+ mCurArgData = null;
+ return arg;
+ }
+
+ private String nextOptionData() {
+ if (mCurArgData != null) {
+ return mCurArgData;
+ }
+ if (mNextArg >= mArgs.length) {
+ return null;
+ }
+ String data = mArgs[mNextArg];
+ mNextArg++;
+ return data;
+ }
+
+ private String nextArg() {
+ if (mNextArg >= mArgs.length) {
+ return null;
+ }
+ String arg = mArgs[mNextArg];
+ mNextArg++;
+ return arg;
+ }
+
+ private static void showUsage() {
+ System.err.println("usage: pm [list|path|install|uninstall]");
+ System.err.println(" pm list packages [-f]");
+ System.err.println(" pm list permission-groups");
+ System.err.println(" pm list permissions [-g] [-f] [-d] [-u] [GROUP]");
+ System.err.println(" pm list instrumentation [-f] [TARGET-PACKAGE]");
+ System.err.println(" pm path PACKAGE");
+ System.err.println(" pm install [-l] [-r] PATH");
+ System.err.println(" pm uninstall [-k] PACKAGE");
+ System.err.println(" pm enable PACKAGE_OR_COMPONENT");
+ System.err.println(" pm disable PACKAGE_OR_COMPONENT");
+ System.err.println("");
+ System.err.println("The list packages command prints all packages. Use");
+ System.err.println("the -f option to see their associated file.");
+ System.err.println("");
+ System.err.println("The list permission-groups command prints all known");
+ System.err.println("permission groups.");
+ System.err.println("");
+ System.err.println("The list permissions command prints all known");
+ System.err.println("permissions, optionally only those in GROUP. Use");
+ System.err.println("the -g option to organize by group. Use");
+ System.err.println("the -f option to print all information. Use");
+ System.err.println("the -s option for a short summary. Use");
+ System.err.println("the -d option to only list dangerous permissions. Use");
+ System.err.println("the -u option to list only the permissions users will see.");
+ System.err.println("");
+ System.err.println("The list instrumentation command prints all instrumentations,");
+ System.err.println("or only those that target a specified package. Use the -f option");
+ System.err.println("to see their associated file.");
+ System.err.println("");
+ System.err.println("The path command prints the path to the .apk of a package.");
+ System.err.println("");
+ System.err.println("The install command installs a package to the system. Use");
+ System.err.println("the -l option to install the package with FORWARD_LOCK. Use");
+ System.err.println("the -r option to reinstall an exisiting app, keeping its data.");
+ System.err.println("");
+ System.err.println("The uninstall command removes a package from the system. Use");
+ System.err.println("the -k option to keep the data and cache directories around");
+ System.err.println("after the package removal.");
+ System.err.println("");
+ System.err.println("The enable and disable commands change the enabled state of");
+ System.err.println("a given package or component (written as \"package/class\").");
+ }
+}
diff --git a/cmds/runtime/Android.mk b/cmds/runtime/Android.mk
new file mode 100644
index 0000000..521eb2b
--- /dev/null
+++ b/cmds/runtime/Android.mk
@@ -0,0 +1,29 @@
+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 \
+ 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
diff --git a/cmds/runtime/MODULE_LICENSE_APACHE2 b/cmds/runtime/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cmds/runtime/MODULE_LICENSE_APACHE2
diff --git a/cmds/runtime/NOTICE b/cmds/runtime/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/cmds/runtime/NOTICE
@@ -0,0 +1,190 @@
+
+ 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
+
diff --git a/cmds/runtime/ServiceManager.cpp b/cmds/runtime/ServiceManager.cpp
new file mode 100644
index 0000000..758a95c
--- /dev/null
+++ b/cmds/runtime/ServiceManager.cpp
@@ -0,0 +1,74 @@
+//
+// 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 <utils/Parcel.h>
+#include <utils/String8.h>
+#include <utils/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
diff --git a/cmds/runtime/ServiceManager.h b/cmds/runtime/ServiceManager.h
new file mode 100644
index 0000000..d09cec8
--- /dev/null
+++ b/cmds/runtime/ServiceManager.h
@@ -0,0 +1,38 @@
+//
+// Copyright 2005 The Android Open Source Project
+//
+#ifndef ANDROID_SERVICE_MANAGER_H
+#define ANDROID_SERVICE_MANAGER_H
+
+#include <utils/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
diff --git a/cmds/runtime/SignalHandler.cpp b/cmds/runtime/SignalHandler.cpp
new file mode 100644
index 0000000..cccaabf
--- /dev/null
+++ b/cmds/runtime/SignalHandler.cpp
@@ -0,0 +1,249 @@
+//
+// 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
+
diff --git a/cmds/runtime/SignalHandler.h b/cmds/runtime/SignalHandler.h
new file mode 100644
index 0000000..7f4ef8e
--- /dev/null
+++ b/cmds/runtime/SignalHandler.h
@@ -0,0 +1,137 @@
+//
+// 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
diff --git a/cmds/runtime/main_runtime.cpp b/cmds/runtime/main_runtime.cpp
new file mode 100644
index 0000000..1531a9e
--- /dev/null
+++ b/cmds/runtime/main_runtime.cpp
@@ -0,0 +1,514 @@
+//
+// Copyright 2005 The Android Open Source Project
+//
+// Main entry point for runtime.
+//
+
+#include "ServiceManager.h"
+#include "SignalHandler.h"
+
+#include <utils.h>
+#include <utils/IPCThreadState.h>
+#include <utils/ProcessState.h>
+#include <utils/Log.h>
+#include <cutils/zygote.h>
+
+#include <cutils/properties.h>
+
+#include <private/utils/Static.h>
+
+#include <ui/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
+ */
+ "--capabilities=88161312,88161312",
+ "--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 status_t app_init(const char* className);
+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] [-s]\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"
+ "-s: Force single-process mode\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);
+
+ if (proc->supportsProcesses()) {
+ // 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();
+ } else {
+ // Keep this thread running forever...
+ while (1) {
+ usleep(100000);
+ }
+ }
+ 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)
+{
+ // If we are running multiprocess, we now need to have the
+ // thread pool started here. We don't do this in boot_init()
+ // because when running single process we need to start the
+ // thread pool after the Android runtime has been started (so
+ // the pool uses Dalvik threads).
+ if (proc->supportsProcesses()) {
+ 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);
+
+ if (proc->supportsProcesses()) {
+ LOGI("Binder driver opened. Multiprocess enabled.\n");
+ } else {
+ LOGI("Binder driver not found. Processes not supported.\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[])
+{
+ bool singleProcess = false;
+ 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:ns");
+ 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 's':
+ singleProcess = true;
+ 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 (singleProcess) {
+ ProcessState::setSingleProcess(true);
+ }
+
+ 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();
+
+ /* If we are in multiprocess mode, have zygote spawn the system
+ * server process and call system_init(). If we are running in
+ * single process mode just call system_init() directly.
+ */
+ if (proc->supportsProcesses()) {
+ // 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);
+
+ //start_process("/system/bin/mediaserver");
+
+ } else {
+#ifndef HAVE_ANDROID_OS
+ QuickRuntime* runt = new QuickRuntime();
+ runt->start("com/android/server/SystemServer",
+ false /* spontaneously fork system server from zygote */);
+#endif
+ }
+
+ //printf("+++ post-zygote\n");
+
+ finish_system_init(proc);
+ run(proc);
+
+bail:
+ if (proc != NULL) {
+ proc->setContextObject(NULL);
+ }
+
+ return 0;
+}
diff --git a/cmds/service/Android.mk b/cmds/service/Android.mk
new file mode 100644
index 0000000..8c5005c
--- /dev/null
+++ b/cmds/service/Android.mk
@@ -0,0 +1,17 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ service.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libutils
+
+ifeq ($(TARGET_OS),linux)
+ LOCAL_CFLAGS += -DXP_UNIX
+ #LOCAL_SHARED_LIBRARIES += librt
+endif
+
+LOCAL_MODULE:= service
+
+include $(BUILD_EXECUTABLE)
diff --git a/cmds/service/MODULE_LICENSE_APACHE2 b/cmds/service/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cmds/service/MODULE_LICENSE_APACHE2
diff --git a/cmds/service/NOTICE b/cmds/service/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/cmds/service/NOTICE
@@ -0,0 +1,190 @@
+
+ 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
+
diff --git a/cmds/service/service.cpp b/cmds/service/service.cpp
new file mode 100644
index 0000000..859a9bf
--- /dev/null
+++ b/cmds/service/service.cpp
@@ -0,0 +1,275 @@
+/*
+ * Command line access to services.
+ *
+ */
+
+#include <utils/Parcel.h>
+#include <utils/ProcessState.h>
+#include <utils/IServiceManager.h>
+#include <utils/TextOutput.h>
+
+#include <getopt.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+using namespace android;
+
+void writeString16(Parcel& parcel, const char* string)
+{
+ if (string != NULL)
+ {
+ parcel.writeString16(String16(string));
+ }
+ else
+ {
+ parcel.writeInt32(-1);
+ }
+}
+
+// get the name of the generic interface we hold a reference to
+static String16 get_interface_name(sp<IBinder> service)
+{
+ if (service != NULL) {
+ Parcel data, reply;
+ status_t err = service->transact(IBinder::INTERFACE_TRANSACTION, data, &reply);
+ if (err == NO_ERROR) {
+ return reply.readString16();
+ }
+ }
+ return String16();
+}
+
+static String8 good_old_string(const String16& src)
+{
+ String8 name8;
+ char ch8[2];
+ ch8[1] = 0;
+ for (unsigned j = 0; j < src.size(); j++) {
+ char16_t ch = src[j];
+ if (ch < 128) ch8[0] = (char)ch;
+ name8.append(ch8);
+ }
+ return name8;
+}
+
+int main(int argc, char* const argv[])
+{
+ sp<IServiceManager> sm = defaultServiceManager();
+ fflush(stdout);
+ if (sm == NULL) {
+ aerr << "service: Unable to get default service manager!" << endl;
+ return 20;
+ }
+
+ bool wantsUsage = false;
+ int result = 0;
+
+ while (1) {
+ int ic = getopt(argc, argv, "h?");
+ if (ic < 0)
+ break;
+
+ switch (ic) {
+ case 'h':
+ case '?':
+ wantsUsage = true;
+ break;
+ default:
+ aerr << "service: Unknown option -" << ic << endl;
+ wantsUsage = true;
+ result = 10;
+ break;
+ }
+ }
+
+ if (optind >= argc) {
+ wantsUsage = true;
+ } else if (!wantsUsage) {
+ if (strcmp(argv[optind], "check") == 0) {
+ optind++;
+ if (optind < argc) {
+ sp<IBinder> service = sm->checkService(String16(argv[optind]));
+ aout << "Service " << argv[optind] <<
+ (service == NULL ? ": not found" : ": found") << endl;
+ } else {
+ aerr << "service: No service specified for check" << endl;
+ wantsUsage = true;
+ result = 10;
+ }
+ }
+ else if (strcmp(argv[optind], "list") == 0) {
+ Vector<String16> services = sm->listServices();
+ aout << "Found " << services.size() << " services:" << endl;
+ for (unsigned i = 0; i < services.size(); i++) {
+ String16 name = services[i];
+ sp<IBinder> service = sm->checkService(name);
+ aout << i
+ << "\t" << good_old_string(name)
+ << ": [" << good_old_string(get_interface_name(service)) << "]"
+ << endl;
+ }
+ } else if (strcmp(argv[optind], "call") == 0) {
+ optind++;
+ if (optind+1 < argc) {
+ int serviceArg = optind;
+ sp<IBinder> service = sm->checkService(String16(argv[optind++]));
+ String16 ifName = get_interface_name(service);
+ int32_t code = atoi(argv[optind++]);
+ if (service != NULL && ifName.size() > 0) {
+ Parcel data, reply;
+
+ // the interface name is first
+ data.writeInterfaceToken(ifName);
+
+ // then the rest of the call arguments
+ while (optind < argc) {
+ if (strcmp(argv[optind], "i32") == 0) {
+ optind++;
+ if (optind >= argc) {
+ aerr << "service: no integer supplied for 'i32'" << endl;
+ wantsUsage = true;
+ result = 10;
+ break;
+ }
+ data.writeInt32(atoi(argv[optind++]));
+ } else if (strcmp(argv[optind], "s16") == 0) {
+ optind++;
+ if (optind >= argc) {
+ aerr << "service: no string supplied for 's16'" << endl;
+ wantsUsage = true;
+ result = 10;
+ break;
+ }
+ data.writeString16(String16(argv[optind++]));
+ } else if (strcmp(argv[optind], "null") == 0) {
+ optind++;
+ data.writeStrongBinder(NULL);
+ } else if (strcmp(argv[optind], "intent") == 0) {
+
+ char* action = NULL;
+ char* dataArg = NULL;
+ char* type = NULL;
+ int launchFlags = 0;
+ char* component = NULL;
+ int categoryCount = 0;
+ char* categories[16];
+
+ char* context1 = NULL;
+
+ optind++;
+
+ while (optind < argc)
+ {
+ char* key = strtok_r(argv[optind], "=", &context1);
+ char* value = strtok_r(NULL, "=", &context1);
+
+ // we have reached the end of the XXX=XXX args.
+ if (key == NULL) break;
+
+ if (strcmp(key, "action") == 0)
+ {
+ action = value;
+ }
+ else if (strcmp(key, "data") == 0)
+ {
+ dataArg = value;
+ }
+ else if (strcmp(key, "type") == 0)
+ {
+ type = value;
+ }
+ else if (strcmp(key, "launchFlags") == 0)
+ {
+ launchFlags = atoi(value);
+ }
+ else if (strcmp(key, "component") == 0)
+ {
+ component = value;
+ }
+ else if (strcmp(key, "categories") == 0)
+ {
+ char* context2 = NULL;
+ int categoryCount = 0;
+ categories[categoryCount] = strtok_r(value, ",", &context2);
+
+ while (categories[categoryCount] != NULL)
+ {
+ categoryCount++;
+ categories[categoryCount] = strtok_r(NULL, ",", &context2);
+ }
+ }
+
+ optind++;
+ }
+
+ writeString16(data, action);
+ writeString16(data, dataArg);
+ writeString16(data, type);
+ data.writeInt32(launchFlags);
+ writeString16(data, component);
+
+ if (categoryCount > 0)
+ {
+ data.writeInt32(categoryCount);
+ for (int i = 0 ; i < categoryCount ; i++)
+ {
+ writeString16(data, categories[i]);
+ }
+ }
+ else
+ {
+ data.writeInt32(0);
+ }
+
+ // for now just set the extra field to be null.
+ data.writeInt32(-1);
+ } else {
+ aerr << "service: unknown option " << argv[optind] << endl;
+ wantsUsage = true;
+ result = 10;
+ break;
+ }
+ }
+
+ service->transact(code, data, &reply);
+ aout << "Result: " << reply << endl;
+ } else {
+ aerr << "service: Service " << argv[serviceArg]
+ << " does not exist" << endl;
+ result = 10;
+ }
+ } else {
+ if (optind < argc) {
+ aerr << "service: No service specified for call" << endl;
+ } else {
+ aerr << "service: No code specified for call" << endl;
+ }
+ wantsUsage = true;
+ result = 10;
+ }
+ } else {
+ aerr << "service: Unknown command " << argv[optind] << endl;
+ wantsUsage = true;
+ result = 10;
+ }
+ }
+
+ if (wantsUsage) {
+ aout << "Usage: service [-h|-?]\n"
+ " service list\n"
+ " service check SERVICE\n"
+ " service call SERVICE CODE [i32 INT | s16 STR] ...\n"
+ "Options:\n"
+ " i32: Write the integer INT into the send parcel.\n"
+ " s16: Write the UTF-16 string STR into the send parcel.\n";
+// " intent: Write and Intent int the send parcel. ARGS can be\n"
+// " action=STR data=STR type=STR launchFlags=INT component=STR categories=STR[,STR,...]\n";
+ return result;
+ }
+
+ return result;
+}
+
diff --git a/cmds/servicemanager/Android.mk b/cmds/servicemanager/Android.mk
new file mode 100644
index 0000000..25266a2
--- /dev/null
+++ b/cmds/servicemanager/Android.mk
@@ -0,0 +1,14 @@
+ifneq ($(TARGET_SIMULATOR),true)
+LOCAL_PATH:= $(call my-dir)
+
+#include $(CLEAR_VARS)
+#LOCAL_SRC_FILES := bctest.c binder.c
+#LOCAL_MODULE := bctest
+#include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_SRC_FILES := service_manager.c binder.c
+LOCAL_MODULE := servicemanager
+include $(BUILD_EXECUTABLE)
+endif
diff --git a/cmds/servicemanager/bctest.c b/cmds/servicemanager/bctest.c
new file mode 100644
index 0000000..6dee816
--- /dev/null
+++ b/cmds/servicemanager/bctest.c
@@ -0,0 +1,102 @@
+/* Copyright 2008 The Android Open Source Project
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "binder.h"
+
+void *svcmgr_lookup(struct binder_state *bs, void *target, const char *name)
+{
+ void *ptr;
+ unsigned iodata[512/4];
+ struct binder_io msg, reply;
+
+ bio_init(&msg, iodata, sizeof(iodata), 4);
+ bio_put_string16_x(&msg, SVC_MGR_NAME);
+ bio_put_string16_x(&msg, name);
+
+ if (binder_call(bs, &msg, &reply, target, SVC_MGR_CHECK_SERVICE))
+ return 0;
+
+ ptr = bio_get_ref(&reply);
+
+ if (ptr)
+ binder_acquire(bs, ptr);
+
+ binder_done(bs, &msg, &reply);
+
+ return ptr;
+}
+
+int svcmgr_publish(struct binder_state *bs, void *target, const char *name, void *ptr)
+{
+ unsigned status;
+ unsigned iodata[512/4];
+ struct binder_io msg, reply;
+
+ bio_init(&msg, iodata, sizeof(iodata), 4);
+
+ bio_put_string16_x(&msg, SVC_MGR_NAME);
+ bio_put_string16_x(&msg, name);
+ bio_put_obj(&msg, ptr);
+
+ if (binder_call(bs, &msg, &reply, target, SVC_MGR_ADD_SERVICE))
+ return -1;
+
+ status = bio_get_uint32(&reply);
+
+ binder_done(bs, &msg, &reply);
+
+ return status;
+}
+
+unsigned token;
+
+int main(int argc, char **argv)
+{
+ int fd;
+ struct binder_state *bs;
+ void *svcmgr = BINDER_SERVICE_MANAGER;
+
+ bs = binder_open(128*1024);
+
+ argc--;
+ argv++;
+ while (argc > 0) {
+ if (!strcmp(argv[0],"alt")) {
+ void *ptr = svcmgr_lookup(bs, svcmgr, "alt_svc_mgr");
+ if (!ptr) {
+ fprintf(stderr,"cannot find alt_svc_mgr\n");
+ return -1;
+ }
+ svcmgr = ptr;
+ fprintf(stderr,"svcmgr is via %p\n", ptr);
+ } else if (!strcmp(argv[0],"lookup")) {
+ void *ptr;
+ if (argc < 2) {
+ fprintf(stderr,"argument required\n");
+ return -1;
+ }
+ ptr = svcmgr_lookup(bs, svcmgr, argv[1]);
+ fprintf(stderr,"lookup(%s) = %p\n", argv[1], ptr);
+ argc--;
+ argv++;
+ } else if (!strcmp(argv[0],"publish")) {
+ if (argc < 2) {
+ fprintf(stderr,"argument required\n");
+ return -1;
+ }
+ svcmgr_publish(bs, svcmgr, argv[1], &token);
+ argc--;
+ argv++;
+ } else {
+ fprintf(stderr,"unknown command %s\n", argv[0]);
+ return -1;
+ }
+ argc--;
+ argv++;
+ }
+ return 0;
+}
diff --git a/cmds/servicemanager/binder.c b/cmds/servicemanager/binder.c
new file mode 100644
index 0000000..b03b620
--- /dev/null
+++ b/cmds/servicemanager/binder.c
@@ -0,0 +1,616 @@
+/* Copyright 2008 The Android Open Source Project
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#include "binder.h"
+
+#define MAX_BIO_SIZE (1 << 30)
+
+#define TRACE 0
+
+#define LOG_TAG "Binder"
+#include <cutils/log.h>
+
+void bio_init_from_txn(struct binder_io *io, struct binder_txn *txn);
+
+#if TRACE
+void hexdump(void *_data, unsigned len)
+{
+ unsigned char *data = _data;
+ unsigned count;
+
+ for (count = 0; count < len; count++) {
+ if ((count & 15) == 0)
+ fprintf(stderr,"%04x:", count);
+ fprintf(stderr," %02x %c", *data,
+ (*data < 32) || (*data > 126) ? '.' : *data);
+ data++;
+ if ((count & 15) == 15)
+ fprintf(stderr,"\n");
+ }
+ if ((count & 15) != 0)
+ fprintf(stderr,"\n");
+}
+
+void binder_dump_txn(struct binder_txn *txn)
+{
+ struct binder_object *obj;
+ unsigned *offs = txn->offs;
+ unsigned count = txn->offs_size / 4;
+
+ fprintf(stderr," target %p cookie %p code %08x flags %08x\n",
+ txn->target, txn->cookie, txn->code, txn->flags);
+ fprintf(stderr," pid %8d uid %8d data %8d offs %8d\n",
+ txn->sender_pid, txn->sender_euid, txn->data_size, txn->offs_size);
+ hexdump(txn->data, txn->data_size);
+ while (count--) {
+ obj = (void*) (((char*) txn->data) + *offs++);
+ fprintf(stderr," - type %08x flags %08x ptr %p cookie %p\n",
+ obj->type, obj->flags, obj->pointer, obj->cookie);
+ }
+}
+
+#define NAME(n) case n: return #n
+const char *cmd_name(uint32_t cmd)
+{
+ switch(cmd) {
+ NAME(BR_NOOP);
+ NAME(BR_TRANSACTION_COMPLETE);
+ NAME(BR_INCREFS);
+ NAME(BR_ACQUIRE);
+ NAME(BR_RELEASE);
+ NAME(BR_DECREFS);
+ NAME(BR_TRANSACTION);
+ NAME(BR_REPLY);
+ NAME(BR_FAILED_REPLY);
+ NAME(BR_DEAD_REPLY);
+ NAME(BR_DEAD_BINDER);
+ default: return "???";
+ }
+}
+#else
+#define hexdump(a,b) do{} while (0)
+#define binder_dump_txn(txn) do{} while (0)
+#endif
+
+#define BIO_F_SHARED 0x01 /* needs to be buffer freed */
+#define BIO_F_OVERFLOW 0x02 /* ran out of space */
+#define BIO_F_IOERROR 0x04
+#define BIO_F_MALLOCED 0x08 /* needs to be free()'d */
+
+struct binder_state
+{
+ int fd;
+ void *mapped;
+ unsigned mapsize;
+};
+
+struct binder_state *binder_open(unsigned mapsize)
+{
+ struct binder_state *bs;
+
+ bs = malloc(sizeof(*bs));
+ if (!bs) {
+ errno = ENOMEM;
+ return 0;
+ }
+
+ bs->fd = open("/dev/binder", O_RDWR);
+ if (bs->fd < 0) {
+ fprintf(stderr,"binder: cannot open device (%s)\n",
+ strerror(errno));
+ goto fail_open;
+ }
+
+ bs->mapsize = mapsize;
+ bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
+ if (bs->mapped == MAP_FAILED) {
+ fprintf(stderr,"binder: cannot map device (%s)\n",
+ strerror(errno));
+ goto fail_map;
+ }
+
+ /* TODO: check version */
+
+ return bs;
+
+fail_map:
+ close(bs->fd);
+fail_open:
+ free(bs);
+ return 0;
+}
+
+void binder_close(struct binder_state *bs)
+{
+ munmap(bs->mapped, bs->mapsize);
+ close(bs->fd);
+ free(bs);
+}
+
+int binder_become_context_manager(struct binder_state *bs)
+{
+ return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
+}
+
+int binder_write(struct binder_state *bs, void *data, unsigned len)
+{
+ struct binder_write_read bwr;
+ int res;
+ bwr.write_size = len;
+ bwr.write_consumed = 0;
+ bwr.write_buffer = (unsigned) data;
+ bwr.read_size = 0;
+ bwr.read_consumed = 0;
+ bwr.read_buffer = 0;
+ res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
+ if (res < 0) {
+ fprintf(stderr,"binder_write: ioctl failed (%s)\n",
+ strerror(errno));
+ }
+ return res;
+}
+
+void binder_send_reply(struct binder_state *bs,
+ struct binder_io *reply,
+ void *buffer_to_free,
+ int status)
+{
+ struct {
+ uint32_t cmd_free;
+ void *buffer;
+ uint32_t cmd_reply;
+ struct binder_txn txn;
+ } __attribute__((packed)) data;
+
+ data.cmd_free = BC_FREE_BUFFER;
+ data.buffer = buffer_to_free;
+ data.cmd_reply = BC_REPLY;
+ data.txn.target = 0;
+ data.txn.cookie = 0;
+ data.txn.code = 0;
+ if (status) {
+ data.txn.flags = TF_STATUS_CODE;
+ data.txn.data_size = sizeof(int);
+ data.txn.offs_size = 0;
+ data.txn.data = &status;
+ data.txn.offs = 0;
+ } else {
+ data.txn.flags = 0;
+ data.txn.data_size = reply->data - reply->data0;
+ data.txn.offs_size = ((char*) reply->offs) - ((char*) reply->offs0);
+ data.txn.data = reply->data0;
+ data.txn.offs = reply->offs0;
+ }
+ binder_write(bs, &data, sizeof(data));
+}
+
+int binder_parse(struct binder_state *bs, struct binder_io *bio,
+ uint32_t *ptr, uint32_t size, binder_handler func)
+{
+ int r = 1;
+ uint32_t *end = ptr + (size / 4);
+
+ while (ptr < end) {
+ uint32_t cmd = *ptr++;
+#if TRACE
+ fprintf(stderr,"%s:\n", cmd_name(cmd));
+#endif
+ switch(cmd) {
+ case BR_NOOP:
+ break;
+ case BR_TRANSACTION_COMPLETE:
+ break;
+ case BR_INCREFS:
+ case BR_ACQUIRE:
+ case BR_RELEASE:
+ case BR_DECREFS:
+#if TRACE
+ fprintf(stderr," %08x %08x\n", ptr[0], ptr[1]);
+#endif
+ ptr += 2;
+ break;
+ case BR_TRANSACTION: {
+ struct binder_txn *txn = (void *) ptr;
+ if ((end - ptr) * sizeof(uint32_t) < sizeof(struct binder_txn)) {
+ LOGE("parse: txn too small!\n");
+ return -1;
+ }
+ binder_dump_txn(txn);
+ if (func) {
+ unsigned rdata[256/4];
+ struct binder_io msg;
+ struct binder_io reply;
+ int res;
+
+ bio_init(&reply, rdata, sizeof(rdata), 4);
+ bio_init_from_txn(&msg, txn);
+ res = func(bs, txn, &msg, &reply);
+ binder_send_reply(bs, &reply, txn->data, res);
+ }
+ ptr += sizeof(*txn) / sizeof(uint32_t);
+ break;
+ }
+ case BR_REPLY: {
+ struct binder_txn *txn = (void*) ptr;
+ if ((end - ptr) * sizeof(uint32_t) < sizeof(struct binder_txn)) {
+ LOGE("parse: reply too small!\n");
+ return -1;
+ }
+ binder_dump_txn(txn);
+ if (bio) {
+ bio_init_from_txn(bio, txn);
+ bio = 0;
+ } else {
+ /* todo FREE BUFFER */
+ }
+ ptr += (sizeof(*txn) / sizeof(uint32_t));
+ r = 0;
+ break;
+ }
+ case BR_DEAD_BINDER: {
+ struct binder_death *death = (void*) *ptr++;
+ death->func(bs, death->ptr);
+ break;
+ }
+ case BR_FAILED_REPLY:
+ r = -1;
+ break;
+ case BR_DEAD_REPLY:
+ r = -1;
+ break;
+ default:
+ LOGE("parse: OOPS %d\n", cmd);
+ return -1;
+ }
+ }
+
+ return r;
+}
+
+void binder_acquire(struct binder_state *bs, void *ptr)
+{
+ uint32_t cmd[2];
+ cmd[0] = BC_ACQUIRE;
+ cmd[1] = (uint32_t) ptr;
+ binder_write(bs, cmd, sizeof(cmd));
+}
+
+void binder_release(struct binder_state *bs, void *ptr)
+{
+ uint32_t cmd[2];
+ cmd[0] = BC_RELEASE;
+ cmd[1] = (uint32_t) ptr;
+ binder_write(bs, cmd, sizeof(cmd));
+}
+
+void binder_link_to_death(struct binder_state *bs, void *ptr, struct binder_death *death)
+{
+ uint32_t cmd[3];
+ cmd[0] = BC_REQUEST_DEATH_NOTIFICATION;
+ cmd[1] = (uint32_t) ptr;
+ cmd[2] = (uint32_t) death;
+ binder_write(bs, cmd, sizeof(cmd));
+}
+
+
+int binder_call(struct binder_state *bs,
+ struct binder_io *msg, struct binder_io *reply,
+ void *target, uint32_t code)
+{
+ int res;
+ struct binder_write_read bwr;
+ struct {
+ uint32_t cmd;
+ struct binder_txn txn;
+ } writebuf;
+ unsigned readbuf[32];
+
+ if (msg->flags & BIO_F_OVERFLOW) {
+ fprintf(stderr,"binder: txn buffer overflow\n");
+ goto fail;
+ }
+
+ writebuf.cmd = BC_TRANSACTION;
+ writebuf.txn.target = target;
+ writebuf.txn.code = code;
+ writebuf.txn.flags = 0;
+ writebuf.txn.data_size = msg->data - msg->data0;
+ writebuf.txn.offs_size = ((char*) msg->offs) - ((char*) msg->offs0);
+ writebuf.txn.data = msg->data0;
+ writebuf.txn.offs = msg->offs0;
+
+ bwr.write_size = sizeof(writebuf);
+ bwr.write_consumed = 0;
+ bwr.write_buffer = (unsigned) &writebuf;
+
+ hexdump(msg->data0, msg->data - msg->data0);
+ for (;;) {
+ bwr.read_size = sizeof(readbuf);
+ bwr.read_consumed = 0;
+ bwr.read_buffer = (unsigned) readbuf;
+
+ res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
+
+ if (res < 0) {
+ fprintf(stderr,"binder: ioctl failed (%s)\n", strerror(errno));
+ goto fail;
+ }
+
+ res = binder_parse(bs, reply, readbuf, bwr.read_consumed, 0);
+ if (res == 0) return 0;
+ if (res < 0) goto fail;
+ }
+
+fail:
+ memset(reply, 0, sizeof(*reply));
+ reply->flags |= BIO_F_IOERROR;
+ return -1;
+}
+
+void binder_loop(struct binder_state *bs, binder_handler func)
+{
+ int res;
+ struct binder_write_read bwr;
+ unsigned readbuf[32];
+
+ bwr.write_size = 0;
+ bwr.write_consumed = 0;
+ bwr.write_buffer = 0;
+
+ readbuf[0] = BC_ENTER_LOOPER;
+ binder_write(bs, readbuf, sizeof(unsigned));
+
+ for (;;) {
+ bwr.read_size = sizeof(readbuf);
+ bwr.read_consumed = 0;
+ bwr.read_buffer = (unsigned) readbuf;
+
+ res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
+
+ if (res < 0) {
+ LOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
+ break;
+ }
+
+ res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func);
+ if (res == 0) {
+ LOGE("binder_loop: unexpected reply?!\n");
+ break;
+ }
+ if (res < 0) {
+ LOGE("binder_loop: io error %d %s\n", res, strerror(errno));
+ break;
+ }
+ }
+}
+
+void bio_init_from_txn(struct binder_io *bio, struct binder_txn *txn)
+{
+ bio->data = bio->data0 = txn->data;
+ bio->offs = bio->offs0 = txn->offs;
+ bio->data_avail = txn->data_size;
+ bio->offs_avail = txn->offs_size / 4;
+ bio->flags = BIO_F_SHARED;
+}
+
+void bio_init(struct binder_io *bio, void *data,
+ uint32_t maxdata, uint32_t maxoffs)
+{
+ uint32_t n = maxoffs * sizeof(uint32_t);
+
+ if (n > maxdata) {
+ bio->flags = BIO_F_OVERFLOW;
+ bio->data_avail = 0;
+ bio->offs_avail = 0;
+ return;
+ }
+
+ bio->data = bio->data0 = data + n;
+ bio->offs = bio->offs0 = data;
+ bio->data_avail = maxdata - n;
+ bio->offs_avail = maxoffs;
+ bio->flags = 0;
+}
+
+static void *bio_alloc(struct binder_io *bio, uint32_t size)
+{
+ size = (size + 3) & (~3);
+ if (size > bio->data_avail) {
+ bio->flags |= BIO_F_OVERFLOW;
+ return 0;
+ } else {
+ void *ptr = bio->data;
+ bio->data += size;
+ bio->data_avail -= size;
+ return ptr;
+ }
+}
+
+void binder_done(struct binder_state *bs,
+ struct binder_io *msg,
+ struct binder_io *reply)
+{
+ if (reply->flags & BIO_F_SHARED) {
+ uint32_t cmd[2];
+ cmd[0] = BC_FREE_BUFFER;
+ cmd[1] = (uint32_t) reply->data0;
+ binder_write(bs, cmd, sizeof(cmd));
+ reply->flags = 0;
+ }
+}
+
+static struct binder_object *bio_alloc_obj(struct binder_io *bio)
+{
+ struct binder_object *obj;
+
+ obj = bio_alloc(bio, sizeof(*obj));
+
+ if (obj && bio->offs_avail) {
+ bio->offs_avail--;
+ *bio->offs++ = ((char*) obj) - ((char*) bio->data0);
+ return obj;
+ }
+
+ bio->flags |= BIO_F_OVERFLOW;
+ return 0;
+}
+
+void bio_put_uint32(struct binder_io *bio, uint32_t n)
+{
+ uint32_t *ptr = bio_alloc(bio, sizeof(n));
+ if (ptr)
+ *ptr = n;
+}
+
+void bio_put_obj(struct binder_io *bio, void *ptr)
+{
+ struct binder_object *obj;
+
+ obj = bio_alloc_obj(bio);
+ if (!obj)
+ return;
+
+ obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
+ obj->type = BINDER_TYPE_BINDER;
+ obj->pointer = ptr;
+ obj->cookie = 0;
+}
+
+void bio_put_ref(struct binder_io *bio, void *ptr)
+{
+ struct binder_object *obj;
+
+ if (ptr)
+ obj = bio_alloc_obj(bio);
+ else
+ obj = bio_alloc(bio, sizeof(*obj));
+
+ if (!obj)
+ return;
+
+ obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
+ obj->type = BINDER_TYPE_HANDLE;
+ obj->pointer = ptr;
+ obj->cookie = 0;
+}
+
+void bio_put_string16(struct binder_io *bio, const uint16_t *str)
+{
+ uint32_t len;
+ uint16_t *ptr;
+
+ if (!str) {
+ bio_put_uint32(bio, 0xffffffff);
+ return;
+ }
+
+ len = 0;
+ while (str[len]) len++;
+
+ if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) {
+ bio_put_uint32(bio, 0xffffffff);
+ return;
+ }
+
+ bio_put_uint32(bio, len);
+ len = (len + 1) * sizeof(uint16_t);
+ ptr = bio_alloc(bio, len);
+ if (ptr)
+ memcpy(ptr, str, len);
+}
+
+void bio_put_string16_x(struct binder_io *bio, const char *_str)
+{
+ unsigned char *str = (unsigned char*) _str;
+ uint32_t len;
+ uint16_t *ptr;
+
+ if (!str) {
+ bio_put_uint32(bio, 0xffffffff);
+ return;
+ }
+
+ len = strlen(_str);
+
+ if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) {
+ bio_put_uint32(bio, 0xffffffff);
+ return;
+ }
+
+ bio_put_uint32(bio, len);
+ ptr = bio_alloc(bio, (len + 1) * sizeof(uint16_t));
+ if (!ptr)
+ return;
+
+ while (*str)
+ *ptr++ = *str++;
+ *ptr++ = 0;
+}
+
+static void *bio_get(struct binder_io *bio, uint32_t size)
+{
+ size = (size + 3) & (~3);
+
+ if (bio->data_avail < size){
+ bio->data_avail = 0;
+ bio->flags |= BIO_F_OVERFLOW;
+ return 0;
+ } else {
+ void *ptr = bio->data;
+ bio->data += size;
+ bio->data_avail -= size;
+ return ptr;
+ }
+}
+
+uint32_t bio_get_uint32(struct binder_io *bio)
+{
+ uint32_t *ptr = bio_get(bio, sizeof(*ptr));
+ return ptr ? *ptr : 0;
+}
+
+uint16_t *bio_get_string16(struct binder_io *bio, unsigned *sz)
+{
+ unsigned len;
+ len = bio_get_uint32(bio);
+ if (sz)
+ *sz = len;
+ return bio_get(bio, (len + 1) * sizeof(uint16_t));
+}
+
+static struct binder_object *_bio_get_obj(struct binder_io *bio)
+{
+ unsigned n;
+ unsigned off = bio->data - bio->data0;
+
+ /* TODO: be smarter about this? */
+ for (n = 0; n < bio->offs_avail; n++) {
+ if (bio->offs[n] == off)
+ return bio_get(bio, sizeof(struct binder_object));
+ }
+
+ bio->data_avail = 0;
+ bio->flags |= BIO_F_OVERFLOW;
+ return 0;
+}
+
+void *bio_get_ref(struct binder_io *bio)
+{
+ struct binder_object *obj;
+
+ obj = _bio_get_obj(bio);
+ if (!obj)
+ return 0;
+
+ if (obj->type == BINDER_TYPE_HANDLE)
+ return obj->pointer;
+
+ return 0;
+}
diff --git a/cmds/servicemanager/binder.h b/cmds/servicemanager/binder.h
new file mode 100644
index 0000000..d8c51ef
--- /dev/null
+++ b/cmds/servicemanager/binder.h
@@ -0,0 +1,119 @@
+/* Copyright 2008 The Android Open Source Project
+ */
+
+#ifndef _BINDER_H_
+#define _BINDER_H_
+
+#include <sys/ioctl.h>
+#include <linux/binder.h>
+
+struct binder_state;
+
+struct binder_object
+{
+ uint32_t type;
+ uint32_t flags;
+ void *pointer;
+ void *cookie;
+};
+
+struct binder_txn
+{
+ void *target;
+ void *cookie;
+ uint32_t code;
+ uint32_t flags;
+
+ uint32_t sender_pid;
+ uint32_t sender_euid;
+
+ uint32_t data_size;
+ uint32_t offs_size;
+ void *data;
+ void *offs;
+};
+
+struct binder_io
+{
+ char *data; /* pointer to read/write from */
+ uint32_t *offs; /* array of offsets */
+ uint32_t data_avail; /* bytes available in data buffer */
+ uint32_t offs_avail; /* entries available in offsets array */
+
+ char *data0; /* start of data buffer */
+ uint32_t *offs0; /* start of offsets buffer */
+ uint32_t flags;
+ uint32_t unused;
+};
+
+struct binder_death {
+ void (*func)(struct binder_state *bs, void *ptr);
+ void *ptr;
+};
+
+/* the one magic object */
+#define BINDER_SERVICE_MANAGER ((void*) 0)
+
+#define SVC_MGR_NAME "android.os.IServiceManager"
+
+enum {
+ SVC_MGR_GET_SERVICE = 1,
+ SVC_MGR_CHECK_SERVICE,
+ SVC_MGR_ADD_SERVICE,
+ SVC_MGR_LIST_SERVICES,
+};
+
+typedef int (*binder_handler)(struct binder_state *bs,
+ struct binder_txn *txn,
+ struct binder_io *msg,
+ struct binder_io *reply);
+
+struct binder_state *binder_open(unsigned mapsize);
+void binder_close(struct binder_state *bs);
+
+/* initiate a blocking binder call
+ * - returns zero on success
+ */
+int binder_call(struct binder_state *bs,
+ struct binder_io *msg, struct binder_io *reply,
+ void *target, uint32_t code);
+
+/* release any state associate with the binder_io
+ * - call once any necessary data has been extracted from the
+ * binder_io after binder_call() returns
+ * - can safely be called even if binder_call() fails
+ */
+void binder_done(struct binder_state *bs,
+ struct binder_io *msg, struct binder_io *reply);
+
+/* manipulate strong references */
+void binder_acquire(struct binder_state *bs, void *ptr);
+void binder_release(struct binder_state *bs, void *ptr);
+
+void binder_link_to_death(struct binder_state *bs, void *ptr, struct binder_death *death);
+
+void binder_loop(struct binder_state *bs, binder_handler func);
+
+int binder_become_context_manager(struct binder_state *bs);
+
+/* allocate a binder_io, providing a stack-allocated working
+ * buffer, size of the working buffer, and how many object
+ * offset entries to reserve from the buffer
+ */
+void bio_init(struct binder_io *bio, void *data,
+ uint32_t maxdata, uint32_t maxobjects);
+
+void bio_destroy(struct binder_io *bio);
+
+void bio_put_obj(struct binder_io *bio, void *ptr);
+void bio_put_ref(struct binder_io *bio, void *ptr);
+void bio_put_uint32(struct binder_io *bio, uint32_t n);
+void bio_put_string16(struct binder_io *bio, const uint16_t *str);
+void bio_put_string16_x(struct binder_io *bio, const char *_str);
+
+uint32_t bio_get_uint32(struct binder_io *bio);
+uint16_t *bio_get_string16(struct binder_io *bio, uint32_t *sz);
+void *bio_get_obj(struct binder_io *bio);
+void *bio_get_ref(struct binder_io *bio);
+
+#endif
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
new file mode 100644
index 0000000..e4aa8b5
--- /dev/null
+++ b/cmds/servicemanager/service_manager.c
@@ -0,0 +1,260 @@
+/* Copyright 2008 The Android Open Source Project
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <private/android_filesystem_config.h>
+
+#include "binder.h"
+
+#if 0
+#define LOGI(x...) fprintf(stderr, "svcmgr: " x)
+#define LOGE(x...) fprintf(stderr, "svcmgr: " x)
+#else
+#define LOG_TAG "ServiceManager"
+#include <cutils/log.h>
+#endif
+
+/* TODO:
+ * These should come from a config file or perhaps be
+ * based on some namespace rules of some sort (media
+ * uid can register media.*, etc)
+ */
+static struct {
+ unsigned uid;
+ const char *name;
+} allowed[] = {
+ { AID_MEDIA, "media.audio_flinger" },
+ { AID_MEDIA, "media.player" },
+ { AID_MEDIA, "media.camera" },
+ { AID_RADIO, "radio.phone" },
+ { AID_RADIO, "radio.sms" },
+ { AID_RADIO, "radio.phonesubinfo" },
+ { AID_RADIO, "radio.simphonebook" },
+/* TODO: remove after phone services are updated: */
+ { AID_RADIO, "phone" },
+ { AID_RADIO, "isms" },
+ { AID_RADIO, "iphonesubinfo" },
+ { AID_RADIO, "simphonebook" },
+};
+
+void *svcmgr_handle;
+
+const char *str8(uint16_t *x)
+{
+ static char buf[128];
+ unsigned max = 127;
+ char *p = buf;
+
+ if (x) {
+ while (*x && max--) {
+ *p++ = *x++;
+ }
+ }
+ *p++ = 0;
+ return buf;
+}
+
+int str16eq(uint16_t *a, const char *b)
+{
+ while (*a && *b)
+ if (*a++ != *b++) return 0;
+ if (*a || *b)
+ return 0;
+ return 1;
+}
+
+int svc_can_register(unsigned uid, uint16_t *name)
+{
+ unsigned n;
+
+ if ((uid == 0) || (uid == AID_SYSTEM))
+ return 1;
+
+ for (n = 0; n < sizeof(allowed) / sizeof(allowed[0]); n++)
+ if ((uid == allowed[n].uid) && str16eq(name, allowed[n].name))
+ return 1;
+
+ return 0;
+}
+
+struct svcinfo
+{
+ struct svcinfo *next;
+ void *ptr;
+ struct binder_death death;
+ unsigned len;
+ uint16_t name[0];
+};
+
+struct svcinfo *svclist = 0;
+
+struct svcinfo *find_svc(uint16_t *s16, unsigned len)
+{
+ struct svcinfo *si;
+
+ for (si = svclist; si; si = si->next) {
+ if ((len == si->len) &&
+ !memcmp(s16, si->name, len * sizeof(uint16_t))) {
+ return si;
+ }
+ }
+ return 0;
+}
+
+void svcinfo_death(struct binder_state *bs, void *ptr)
+{
+ struct svcinfo *si = ptr;
+ LOGI("service '%s' died\n", str8(si->name));
+ if (si->ptr) {
+ binder_release(bs, si->ptr);
+ si->ptr = 0;
+ }
+}
+
+uint16_t svcmgr_id[] = {
+ 'a','n','d','r','o','i','d','.','o','s','.',
+ 'I','S','e','r','v','i','c','e','M','a','n','a','g','e','r'
+};
+
+
+void *do_find_service(struct binder_state *bs, uint16_t *s, unsigned len)
+{
+ struct svcinfo *si;
+ si = find_svc(s, len);
+
+// LOGI("check_service('%s') ptr = %p\n", str8(s), si ? si->ptr : 0);
+ if (si && si->ptr) {
+ return si->ptr;
+ } else {
+ return 0;
+ }
+}
+
+int do_add_service(struct binder_state *bs,
+ uint16_t *s, unsigned len,
+ void *ptr, unsigned uid)
+{
+ struct svcinfo *si;
+// LOGI("add_service('%s',%p) uid=%d\n", str8(s), ptr, uid);
+
+ if (!ptr || (len == 0) || (len > 127))
+ return -1;
+
+ if (!svc_can_register(uid, s)) {
+ LOGE("add_service('%s',%p) uid=%d - PERMISSION DENIED\n",
+ str8(s), ptr, uid);
+ return -1;
+ }
+
+ si = find_svc(s, len);
+ if (si) {
+ if (si->ptr) {
+ LOGE("add_service('%s',%p) uid=%d - ALREADY REGISTERED\n",
+ str8(s), ptr, uid);
+ return -1;
+ }
+ si->ptr = ptr;
+ } else {
+ si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
+ if (!si) {
+ LOGE("add_service('%s',%p) uid=%d - OUT OF MEMORY\n",
+ str8(s), ptr, uid);
+ return -1;
+ }
+ si->ptr = ptr;
+ si->len = len;
+ memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
+ si->name[len] = '\0';
+ si->death.func = svcinfo_death;
+ si->death.ptr = si;
+ si->next = svclist;
+ svclist = si;
+ }
+
+ binder_acquire(bs, ptr);
+ binder_link_to_death(bs, ptr, &si->death);
+ return 0;
+}
+
+int svcmgr_handler(struct binder_state *bs,
+ struct binder_txn *txn,
+ struct binder_io *msg,
+ struct binder_io *reply)
+{
+ struct svcinfo *si;
+ uint16_t *s;
+ unsigned len;
+ void *ptr;
+
+// LOGI("target=%p code=%d pid=%d uid=%d\n",
+// txn->target, txn->code, txn->sender_pid, txn->sender_euid);
+
+ if (txn->target != svcmgr_handle)
+ return -1;
+
+ s = bio_get_string16(msg, &len);
+
+ if ((len != (sizeof(svcmgr_id) / 2)) ||
+ memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
+ fprintf(stderr,"invalid id %s\n", str8(s));
+ return -1;
+ }
+
+ switch(txn->code) {
+ case SVC_MGR_GET_SERVICE:
+ case SVC_MGR_CHECK_SERVICE:
+ s = bio_get_string16(msg, &len);
+ ptr = do_find_service(bs, s, len);
+ if (!ptr)
+ break;
+ bio_put_ref(reply, ptr);
+ return 0;
+
+ case SVC_MGR_ADD_SERVICE:
+ s = bio_get_string16(msg, &len);
+ ptr = bio_get_ref(msg);
+ if (do_add_service(bs, s, len, ptr, txn->sender_euid))
+ return -1;
+ break;
+
+ case SVC_MGR_LIST_SERVICES: {
+ unsigned n = bio_get_uint32(msg);
+
+ si = svclist;
+ while ((n-- > 0) && si)
+ si = si->next;
+ if (si) {
+ bio_put_string16(reply, si->name);
+ return 0;
+ }
+ return -1;
+ }
+ default:
+ LOGE("unknown code %d\n", txn->code);
+ return -1;
+ }
+
+ bio_put_uint32(reply, 0);
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ struct binder_state *bs;
+ void *svcmgr = BINDER_SERVICE_MANAGER;
+
+ bs = binder_open(128*1024);
+
+ if (binder_become_context_manager(bs)) {
+ LOGE("cannot become context manager (%s)\n", strerror(errno));
+ return -1;
+ }
+
+ svcmgr_handle = svcmgr;
+ binder_loop(bs, svcmgr_handler);
+ return 0;
+}
diff --git a/cmds/surfaceflinger/Android.mk b/cmds/surfaceflinger/Android.mk
new file mode 100644
index 0000000..37c3d94
--- /dev/null
+++ b/cmds/surfaceflinger/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ main_surfaceflinger.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libsurfaceflinger \
+ libutils
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/../../libs/surfaceflinger
+
+LOCAL_MODULE:= surfaceflinger
+
+include $(BUILD_EXECUTABLE)
diff --git a/cmds/surfaceflinger/main_surfaceflinger.cpp b/cmds/surfaceflinger/main_surfaceflinger.cpp
new file mode 100644
index 0000000..7c89578
--- /dev/null
+++ b/cmds/surfaceflinger/main_surfaceflinger.cpp
@@ -0,0 +1,18 @@
+#include <utils/IPCThreadState.h>
+#include <utils/ProcessState.h>
+#include <utils/IServiceManager.h>
+#include <utils/Log.h>
+
+#include <SurfaceFlinger.h>
+
+using namespace android;
+
+int main(int argc, char** argv)
+{
+ sp<ProcessState> proc(ProcessState::self());
+ sp<IServiceManager> sm = defaultServiceManager();
+ LOGI("ServiceManager: %p", sm.get());
+ SurfaceFlinger::instantiate();
+ ProcessState::self()->startThreadPool();
+ IPCThreadState::self()->joinThreadPool();
+}
diff --git a/cmds/svc/Android.mk b/cmds/svc/Android.mk
new file mode 100644
index 0000000..198efb2
--- /dev/null
+++ b/cmds/svc/Android.mk
@@ -0,0 +1,15 @@
+# Copyright 2007 The Android Open Source Project
+#
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_MODULE := svc
+include $(BUILD_JAVA_LIBRARY)
+
+
+include $(CLEAR_VARS)
+ALL_PREBUILT += $(TARGET_OUT)/bin/svc
+$(TARGET_OUT)/bin/svc : $(LOCAL_PATH)/svc | $(ACP)
+ $(transform-prebuilt-to-target)
+
diff --git a/cmds/svc/MODULE_LICENSE_APACHE2 b/cmds/svc/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cmds/svc/MODULE_LICENSE_APACHE2
diff --git a/cmds/svc/NOTICE b/cmds/svc/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/cmds/svc/NOTICE
@@ -0,0 +1,190 @@
+
+ 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
+
diff --git a/cmds/svc/src/com/android/commands/svc/DataCommand.java b/cmds/svc/src/com/android/commands/svc/DataCommand.java
new file mode 100644
index 0000000..72cb86d
--- /dev/null
+++ b/cmds/svc/src/com/android/commands/svc/DataCommand.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.commands.svc;
+
+import android.os.ServiceManager;
+import android.os.RemoteException;
+import android.net.IConnectivityManager;
+import android.net.ConnectivityManager;
+import android.content.Context;
+import com.android.internal.telephony.ITelephony;
+
+public class DataCommand extends Svc.Command {
+ public DataCommand() {
+ super("data");
+ }
+
+ public String shortHelp() {
+ return "Control mobile data connectivity";
+ }
+
+ public String longHelp() {
+ return shortHelp() + "\n"
+ + "\n"
+ + "usage: svc data [enable|disable]\n"
+ + " Turn mobile data on or off.\n\n"
+ + " svc data prefer\n"
+ + " Set mobile as the preferred data network\n";
+ }
+
+ public void run(String[] args) {
+ boolean validCommand = false;
+ if (args.length >= 2) {
+ boolean flag = false;
+ if ("enable".equals(args[1])) {
+ flag = true;
+ validCommand = true;
+ } else if ("disable".equals(args[1])) {
+ flag = false;
+ validCommand = true;
+ } else if ("prefer".equals(args[1])) {
+ IConnectivityManager connMgr =
+ IConnectivityManager.Stub.asInterface(ServiceManager.getService(Context.CONNECTIVITY_SERVICE));
+ try {
+ connMgr.setNetworkPreference(ConnectivityManager.TYPE_MOBILE);
+ } catch (RemoteException e) {
+ System.err.println("Failed to set preferred network: " + e);
+ }
+ return;
+ }
+ if (validCommand) {
+ ITelephony phoneMgr
+ = ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
+ try {
+ if (flag) {
+ phoneMgr.enableDataConnectivity();
+ } else
+ phoneMgr.disableDataConnectivity();
+ }
+ catch (RemoteException e) {
+ System.err.println("Mobile data operation failed: " + e);
+ }
+ return;
+ }
+ }
+ System.err.println(longHelp());
+ }
+} \ No newline at end of file
diff --git a/cmds/svc/src/com/android/commands/svc/PowerCommand.java b/cmds/svc/src/com/android/commands/svc/PowerCommand.java
new file mode 100644
index 0000000..2b54f54
--- /dev/null
+++ b/cmds/svc/src/com/android/commands/svc/PowerCommand.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.commands.svc;
+
+import android.os.IPowerManager;
+import android.os.ServiceManager;
+import android.os.RemoteException;
+import android.os.BatteryManager;
+import android.content.Context;
+
+public class PowerCommand extends Svc.Command {
+ public PowerCommand() {
+ super("power");
+ }
+
+ public String shortHelp() {
+ return "Control the power manager";
+ }
+
+ public String longHelp() {
+ return shortHelp() + "\n"
+ + "\n"
+ + "usage: svc power stayon [true|false|usb|ac]\n"
+ + " Set the 'keep awake while plugged in' setting.\n";
+ }
+
+ public void run(String[] args) {
+ fail: {
+ if (args.length >= 2) {
+ if ("stayon".equals(args[1]) && args.length == 3) {
+ int val;
+ if ("true".equals(args[2])) {
+ val = BatteryManager.BATTERY_PLUGGED_AC |
+ BatteryManager.BATTERY_PLUGGED_USB;
+ }
+ else if ("false".equals(args[2])) {
+ val = 0;
+ } else if ("usb".equals(args[2])) {
+ val = BatteryManager.BATTERY_PLUGGED_USB;
+ } else if ("ac".equals(args[2])) {
+ val = BatteryManager.BATTERY_PLUGGED_AC;
+ }
+ else {
+ break fail;
+ }
+ IPowerManager pm
+ = IPowerManager.Stub.asInterface(ServiceManager.getService(Context.POWER_SERVICE));
+ try {
+ pm.setStayOnSetting(val);
+ }
+ catch (RemoteException e) {
+ System.err.println("Faild to set setting: " + e);
+ }
+ return;
+ }
+ }
+ }
+ System.err.println(longHelp());
+ }
+}
diff --git a/cmds/svc/src/com/android/commands/svc/Svc.java b/cmds/svc/src/com/android/commands/svc/Svc.java
new file mode 100644
index 0000000..1cd4c0d
--- /dev/null
+++ b/cmds/svc/src/com/android/commands/svc/Svc.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.commands.svc;
+
+public class Svc {
+
+ public static abstract class Command {
+ private String mName;
+
+ public Command(String name) {
+ mName = name;
+ }
+
+ public String name() {
+ return mName;
+ }
+
+ public abstract String shortHelp(); // should fit on one short line
+ public abstract String longHelp(); // take as much space as you need, 75 col max
+ public abstract void run(String[] args); // run the command
+ }
+
+ public static void main(String[] args) {
+ if (args.length >= 1) {
+ Command c = lookupCommand(args[0]);
+ if (c != null) {
+ c.run(args);
+ return;
+ }
+ }
+ COMMAND_HELP.run(args);
+ }
+
+ private static Command lookupCommand(String name) {
+ final int N = COMMANDS.length;
+ for (int i=0; i<N; i++) {
+ Command c = COMMANDS[i];
+ if (c.name().equals(name)) {
+ return c;
+ }
+ }
+ return null;
+ }
+
+ public static final Command COMMAND_HELP = new Command("help") {
+ public String shortHelp() {
+ return "Show information about the subcommands";
+ }
+ public String longHelp() {
+ return shortHelp();
+ }
+ public void run(String[] args) {
+ if (args.length == 2) {
+ Command c = lookupCommand(args[1]);
+ if (c != null) {
+ System.err.println(c.longHelp());
+ return;
+ }
+ }
+
+ System.err.println("Available commands:");
+ final int N = COMMANDS.length;
+ int maxlen = 0;
+ for (int i=0; i<N; i++) {
+ Command c = COMMANDS[i];
+ int len = c.name().length();
+ if (maxlen < len) {
+ maxlen = len;
+ }
+ }
+ String format = " %-" + maxlen + "s %s";
+ for (int i=0; i<N; i++) {
+ Command c = COMMANDS[i];
+ System.err.println(String.format(format, c.name(), c.shortHelp()));
+ }
+ }
+ };
+
+ public static final Command[] COMMANDS = new Command[] {
+ COMMAND_HELP,
+ new PowerCommand(),
+ new DataCommand(),
+ new WifiCommand()
+ };
+}
diff --git a/cmds/svc/src/com/android/commands/svc/WifiCommand.java b/cmds/svc/src/com/android/commands/svc/WifiCommand.java
new file mode 100644
index 0000000..d29e8b2
--- /dev/null
+++ b/cmds/svc/src/com/android/commands/svc/WifiCommand.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.commands.svc;
+
+import android.os.ServiceManager;
+import android.os.RemoteException;
+import android.net.wifi.IWifiManager;
+import android.net.IConnectivityManager;
+import android.net.ConnectivityManager;
+import android.content.Context;
+
+public class WifiCommand extends Svc.Command {
+ public WifiCommand() {
+ super("wifi");
+ }
+
+ public String shortHelp() {
+ return "Control the Wi-Fi manager";
+ }
+
+ public String longHelp() {
+ return shortHelp() + "\n"
+ + "\n"
+ + "usage: svc wifi [enable|disable]\n"
+ + " Turn Wi-Fi on or off.\n\n"
+ + " svc wifi prefer\n"
+ + " Set Wi-Fi as the preferred data network\n";
+ }
+
+ public void run(String[] args) {
+ boolean validCommand = false;
+ if (args.length >= 2) {
+ boolean flag = false;
+ if ("enable".equals(args[1])) {
+ flag = true;
+ validCommand = true;
+ } else if ("disable".equals(args[1])) {
+ flag = false;
+ validCommand = true;
+ } else if ("prefer".equals(args[1])) {
+ IConnectivityManager connMgr =
+ IConnectivityManager.Stub.asInterface(ServiceManager.getService(Context.CONNECTIVITY_SERVICE));
+ try {
+ connMgr.setNetworkPreference(ConnectivityManager.TYPE_WIFI);
+ } catch (RemoteException e) {
+ System.err.println("Failed to set preferred network: " + e);
+ }
+ return;
+ }
+ if (validCommand) {
+ IWifiManager wifiMgr
+ = IWifiManager.Stub.asInterface(ServiceManager.getService(Context.WIFI_SERVICE));
+ try {
+ wifiMgr.setWifiEnabled(flag);
+ }
+ catch (RemoteException e) {
+ System.err.println("Wi-Fi operation failed: " + e);
+ }
+ return;
+ }
+ }
+ System.err.println(longHelp());
+ }
+} \ No newline at end of file
diff --git a/cmds/svc/svc b/cmds/svc/svc
new file mode 100755
index 0000000..27111cd
--- /dev/null
+++ b/cmds/svc/svc
@@ -0,0 +1,7 @@
+# Script to start "am" on the device, which has a very rudimentary
+# shell.
+#
+base=/system
+export CLASSPATH=$base/framework/svc.jar
+exec app_process $base/bin com.android.commands.svc.Svc $*
+
diff --git a/cmds/system_server/Android.mk b/cmds/system_server/Android.mk
new file mode 100644
index 0000000..0a684e8
--- /dev/null
+++ b/cmds/system_server/Android.mk
@@ -0,0 +1,19 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ system_main.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libutils \
+ libsystem_server
+
+LOCAL_C_INCLUDES := \
+ $(JNI_H_INCLUDE)
+
+LOCAL_MODULE:= system_server
+
+include $(BUILD_EXECUTABLE)
+
+include $(LOCAL_PATH)/library/Android.mk
+
diff --git a/cmds/system_server/MODULE_LICENSE_APACHE2 b/cmds/system_server/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cmds/system_server/MODULE_LICENSE_APACHE2
diff --git a/cmds/system_server/NOTICE b/cmds/system_server/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/cmds/system_server/NOTICE
@@ -0,0 +1,190 @@
+
+ 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
+
diff --git a/cmds/system_server/library/Android.mk b/cmds/system_server/library/Android.mk
new file mode 100644
index 0000000..580331a
--- /dev/null
+++ b/cmds/system_server/library/Android.mk
@@ -0,0 +1,27 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ system_init.cpp
+
+base = $(LOCAL_PATH)/../../..
+
+LOCAL_C_INCLUDES := \
+ $(base)/camera/libcameraservice \
+ $(base)/libs/audioflinger \
+ $(base)/libs/surfaceflinger \
+ $(base)/media/libmediaplayerservice \
+ $(JNI_H_INCLUDE)
+
+LOCAL_SHARED_LIBRARIES := \
+ libandroid_runtime \
+ libsurfaceflinger \
+ libaudioflinger \
+ libcameraservice \
+ libmediaplayerservice \
+ libutils \
+ libcutils
+
+LOCAL_MODULE:= libsystem_server
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/cmds/system_server/library/system_init.cpp b/cmds/system_server/library/system_init.cpp
new file mode 100644
index 0000000..73b23e2
--- /dev/null
+++ b/cmds/system_server/library/system_init.cpp
@@ -0,0 +1,109 @@
+/*
+ * System server main initialization.
+ *
+ * The system server is responsible for becoming the Binder
+ * context manager, supplying the root ServiceManager object
+ * through which other services can be found.
+ */
+
+#define LOG_TAG "sysproc"
+
+#include <utils/IPCThreadState.h>
+#include <utils/ProcessState.h>
+#include <utils/IServiceManager.h>
+#include <utils/TextOutput.h>
+#include <utils/Log.h>
+
+#include <SurfaceFlinger.h>
+#include <AudioFlinger.h>
+#include <CameraService.h>
+#include <MediaPlayerService.h>
+
+#include <android_runtime/AndroidRuntime.h>
+
+#include <signal.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <cutils/properties.h>
+
+using namespace android;
+
+namespace android {
+/**
+ * This class is used to kill this process when the runtime dies.
+ */
+class GrimReaper : public IBinder::DeathRecipient {
+public:
+ GrimReaper() { }
+
+ virtual void binderDied(const wp<IBinder>& who)
+ {
+ LOGI("Grim Reaper killing system_server...");
+ kill(getpid(), SIGKILL);
+ }
+};
+
+} // namespace android
+
+
+
+extern "C" status_t system_init()
+{
+ LOGI("Entered system_init()");
+
+ sp<ProcessState> proc(ProcessState::self());
+
+ sp<IServiceManager> sm = defaultServiceManager();
+ LOGI("ServiceManager: %p\n", sm.get());
+
+ sp<GrimReaper> grim = new GrimReaper();
+ sm->asBinder()->linkToDeath(grim, grim.get(), 0);
+
+ char propBuf[PROPERTY_VALUE_MAX];
+ property_get("system_init.startsurfaceflinger", propBuf, "1");
+ if (strcmp(propBuf, "1") == 0) {
+ // Start the SurfaceFlinger
+ SurfaceFlinger::instantiate();
+ }
+
+ // On the simulator, audioflinger et al don't get started the
+ // same way as on the device, and we need to start them here
+ if (!proc->supportsProcesses()) {
+
+ // Start the AudioFlinger
+ AudioFlinger::instantiate();
+
+ // Start the media playback service
+ MediaPlayerService::instantiate();
+
+ // Start the camera service
+ CameraService::instantiate();
+ }
+
+ // And now start the Android runtime. We have to do this bit
+ // of nastiness because the Android runtime initialization requires
+ // some of the core system services to already be started.
+ // All other servers should just start the Android runtime at
+ // the beginning of their processes's main(), before calling
+ // the init function.
+ LOGI("System server: starting Android runtime.\n");
+
+ AndroidRuntime* runtime = AndroidRuntime::getRuntime();
+
+ LOGI("System server: starting Android services.\n");
+ runtime->callStatic("com/android/server/SystemServer", "init2");
+
+ // If running in our own process, just go into the thread
+ // pool. Otherwise, call the initialization finished
+ // func to let this process continue its initilization.
+ if (proc->supportsProcesses()) {
+ LOGI("System server: entering thread pool.\n");
+ ProcessState::self()->startThreadPool();
+ IPCThreadState::self()->joinThreadPool();
+ LOGI("System server: exiting thread pool.\n");
+ }
+ return NO_ERROR;
+}
+
diff --git a/cmds/system_server/system_main.cpp b/cmds/system_server/system_main.cpp
new file mode 100644
index 0000000..ca16e57
--- /dev/null
+++ b/cmds/system_server/system_main.cpp
@@ -0,0 +1,61 @@
+/*
+ * Main entry of system server process.
+ *
+ * Calls the standard system initialization function, and then
+ * puts the main thread into the thread pool so it can handle
+ * incoming transactions.
+ *
+ */
+
+#define LOG_TAG "sysproc"
+
+#include <utils/IPCThreadState.h>
+#include <utils/Log.h>
+
+#include <private/android_filesystem_config.h>
+
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+
+using namespace android;
+
+extern "C" status_t system_init();
+
+bool finish_system_init()
+{
+ return true;
+}
+
+static void blockSignals()
+{
+ sigset_t mask;
+ int cc;
+
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGQUIT);
+ sigaddset(&mask, SIGUSR1);
+ cc = sigprocmask(SIG_BLOCK, &mask, NULL);
+ assert(cc == 0);
+}
+
+int main(int argc, const char* const argv[])
+{
+ LOGI("System server is starting with pid=%d.\n", getpid());
+
+ blockSignals();
+
+ // You can trust me, honestly!
+ LOGW("*** Current priority: %d\n", getpriority(PRIO_PROCESS, 0));
+ setpriority(PRIO_PROCESS, 0, -1);
+
+ #if HAVE_ANDROID_OS
+ //setgid(GID_SYSTEM);
+ //setuid(UID_SYSTEM);
+ #endif
+
+ system_init();
+}