summaryrefslogtreecommitdiff
path: root/cmds
diff options
context:
space:
mode:
Diffstat (limited to 'cmds')
-rw-r--r--cmds/am/src/com/android/commands/am/Am.java567
-rw-r--r--cmds/app_process/app_main.cpp4
-rw-r--r--cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java41
-rw-r--r--cmds/bootanimation/Android.mk5
-rw-r--r--cmds/bootanimation/BootAnimation.cpp310
-rw-r--r--cmds/bootanimation/BootAnimation.h33
-rw-r--r--cmds/bootanimation/bootanimation_main.cpp7
-rw-r--r--cmds/bugreport/Android.mk14
-rw-r--r--cmds/bugreport/bugreport.c56
-rw-r--r--cmds/dumpstate/Android.mk2
-rw-r--r--cmds/dumpstate/dumpstate.c127
-rw-r--r--cmds/dumpstate/dumpstate.h18
-rw-r--r--cmds/dumpsys/Android.mk4
-rw-r--r--cmds/dumpsys/dumpsys.cpp6
-rw-r--r--cmds/keystore/Android.mk42
-rw-r--r--cmds/keystore/certtool.h91
-rw-r--r--cmds/keystore/common.h60
-rw-r--r--cmds/keystore/keymgmt.c426
-rw-r--r--cmds/keystore/keymgmt.h82
-rw-r--r--cmds/keystore/keystore.c542
-rw-r--r--cmds/keystore/keystore.h33
-rw-r--r--cmds/keystore/keystore_cli.c97
-rw-r--r--cmds/keystore/keystore_get.h88
-rw-r--r--cmds/keystore/netkeystore.c411
-rw-r--r--cmds/keystore/netkeystore.h96
-rw-r--r--cmds/keystore/tests/Android.mk28
-rw-r--r--cmds/keystore/tests/netkeystore_test.c249
-rw-r--r--cmds/pm/src/com/android/commands/pm/Pm.java243
-rw-r--r--cmds/runtime/Android.mk1
-rw-r--r--cmds/runtime/ServiceManager.cpp4
-rw-r--r--cmds/runtime/ServiceManager.h2
-rw-r--r--cmds/runtime/main_runtime.cpp8
-rw-r--r--cmds/service/Android.mk3
-rw-r--r--cmds/service/service.cpp6
-rw-r--r--cmds/servicemanager/service_manager.c1
-rw-r--r--cmds/stagefright/Android.mk46
-rw-r--r--cmds/stagefright/SineSource.cpp101
-rw-r--r--cmds/stagefright/SineSource.h39
-rw-r--r--cmds/stagefright/WaveWriter.h71
-rw-r--r--cmds/stagefright/record.cpp265
-rw-r--r--cmds/stagefright/stagefright.cpp402
-rw-r--r--cmds/surfaceflinger/Android.mk1
-rw-r--r--cmds/surfaceflinger/main_surfaceflinger.cpp6
-rw-r--r--cmds/svc/src/com/android/commands/svc/PowerCommand.java6
-rw-r--r--cmds/system_server/Android.mk1
-rw-r--r--cmds/system_server/library/Android.mk1
-rw-r--r--cmds/system_server/library/system_init.cpp10
-rw-r--r--cmds/system_server/system_main.cpp2
48 files changed, 2627 insertions, 2031 deletions
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 3782136f5c73..eca5af976d42 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -23,16 +23,19 @@ import android.app.IActivityManager;
import android.app.IInstrumentationWatcher;
import android.app.Instrumentation;
import android.content.ComponentName;
+import android.content.IIntentReceiver;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.util.AndroidException;
import android.view.IWindowManager;
import java.io.File;
import java.io.FileNotFoundException;
+import java.net.URISyntaxException;
import java.util.Iterator;
import java.util.Set;
@@ -45,16 +48,29 @@ public class Am {
private boolean mDebugOption = false;
+ // These are magic strings understood by the Eclipse plugin.
+ private static final String FATAL_ERROR_CODE = "Error type 1";
+ private static final String NO_SYSTEM_ERROR_CODE = "Error type 2";
+ private static final String NO_CLASS_ERROR_CODE = "Error type 3";
+
/**
* Command-line entry point.
*
* @param args The command-line arguments
*/
public static void main(String[] args) {
- (new Am()).run(args);
+ try {
+ (new Am()).run(args);
+ } catch (IllegalArgumentException e) {
+ showUsage();
+ System.err.println("Error: " + e.getMessage());
+ } catch (Exception e) {
+ System.err.println(e.toString());
+ System.exit(1);
+ }
}
- private void run(String[] args) {
+ private void run(String[] args) throws Exception {
if (args.length < 1) {
showUsage();
return;
@@ -62,16 +78,14 @@ public class Am {
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;
+ System.err.println(NO_SYSTEM_ERROR_CODE);
+ throw new AndroidException("Can't connect to activity manager; is the system running?");
}
mArgs = args;
-
String op = args[0];
mNextArg = 1;
+
if (op.equals("start")) {
runStart();
} else if (op.equals("instrument")) {
@@ -81,13 +95,11 @@ public class Am {
} else if (op.equals("profile")) {
runProfile();
} else {
- System.err.println("Error: Unknown command: " + op);
- showUsage();
- return;
+ throw new IllegalArgumentException("Unknown command: " + op);
}
}
- private Intent makeIntent() {
+ private Intent makeIntent() throws URISyntaxException {
Intent intent = new Intent();
boolean hasIntentInfo = false;
@@ -95,186 +107,146 @@ public class Am {
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;
- }
+ String opt;
+ while ((opt=nextOption()) != null) {
+ if (opt.equals("-a")) {
+ intent.setAction(nextArgRequired());
+ hasIntentInfo = true;
+ } else if (opt.equals("-d")) {
+ data = Uri.parse(nextArgRequired());
+ hasIntentInfo = true;
+ } else if (opt.equals("-t")) {
+ type = nextArgRequired();
+ hasIntentInfo = true;
+ } else if (opt.equals("-c")) {
+ intent.addCategory(nextArgRequired());
+ hasIntentInfo = true;
+ } else if (opt.equals("-e") || opt.equals("--es")) {
+ String key = nextArgRequired();
+ String value = nextArgRequired();
+ intent.putExtra(key, value);
+ hasIntentInfo = true;
+ } else if (opt.equals("--ei")) {
+ String key = nextArgRequired();
+ String value = nextArgRequired();
+ intent.putExtra(key, Integer.valueOf(value));
+ hasIntentInfo = true;
+ } else if (opt.equals("--ez")) {
+ String key = nextArgRequired();
+ String value = nextArgRequired();
+ intent.putExtra(key, Boolean.valueOf(value));
+ hasIntentInfo = true;
+ } else if (opt.equals("-n")) {
+ String str = nextArgRequired();
+ ComponentName cn = ComponentName.unflattenFromString(str);
+ if (cn == null) throw new IllegalArgumentException("Bad component name: " + str);
+ intent.setComponent(cn);
+ hasIntentInfo = true;
+ } else if (opt.equals("-f")) {
+ String str = nextArgRequired();
+ 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());
- }
+ Intent oldIntent = intent;
+ intent = Intent.getIntent(uri);
+ 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;
+ hasIntentInfo = true;
}
+ if (!hasIntentInfo) throw new IllegalArgumentException("No intent supplied");
return intent;
}
- private void runStart() {
+ private void runStart() throws Exception {
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_SWITCHES_CANCELED:
- System.err.println(
- "Warning: Activity not started because the "
- + " current activity is being kept for the user.");
- 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_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;
- case IActivityManager.START_INTENT_NOT_RESOLVED:
- System.err.println(
- "Error: Activity not started, unable to "
- + "resolve " + intent.toString());
- 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_FORWARD_AND_REQUEST_CONFLICT:
- System.err.println(
- "Error: Activity not started, you requested to "
- + "both forward and receive its result");
- break;
- case IActivityManager.START_PERMISSION_DENIED:
- System.err.println(
- "Error: Activity not started, you do not "
- + "have permission to access it.");
- break;
- default:
- System.err.println(
- "Error: Activity not started, unknown error "
- + "code " + res);
- break;
- }
- } catch (RemoteException e) {
- System.err.println("Error type 1");
+ System.out.println("Starting: " + intent);
+ 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_SWITCHES_CANCELED:
+ System.err.println(
+ "Warning: Activity not started because the "
+ + " current activity is being kept for the user.");
+ 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_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;
+ case IActivityManager.START_INTENT_NOT_RESOLVED:
System.err.println(
"Error: Activity not started, unable to "
- + "call on to activity manager service");
- }
+ + "resolve " + intent.toString());
+ break;
+ case IActivityManager.START_CLASS_NOT_FOUND:
+ System.err.println(NO_CLASS_ERROR_CODE);
+ System.err.println("Error: Activity class " +
+ intent.getComponent().toShortString()
+ + " does not exist.");
+ 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_PERMISSION_DENIED:
+ System.err.println(
+ "Error: Activity not started, you do not "
+ + "have permission to access it.");
+ break;
+ default:
+ System.err.println(
+ "Error: Activity not started, unknown error code " + res);
+ break;
}
}
- private void sendBroadcast() {
+ private void sendBroadcast() throws Exception {
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) {
- }
- }
+ IntentReceiver receiver = new IntentReceiver();
+ System.out.println("Broadcasting: " + intent);
+ mAm.broadcastIntent(null, intent, null, receiver, 0, null, null, null, true, false);
+ receiver.waitForFinish();
}
- private void runInstrument() {
+ private void runInstrument() throws Exception {
String profileFile = null;
boolean wait = false;
boolean rawMode = false;
@@ -283,46 +255,30 @@ public class Am {
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;
- }
+ String opt;
+ while ((opt=nextOption()) != null) {
+ if (opt.equals("-p")) {
+ profileFile = nextArgRequired();
+ } else if (opt.equals("-w")) {
+ wait = true;
+ } else if (opt.equals("-r")) {
+ rawMode = true;
+ } else if (opt.equals("-e")) {
+ argKey = nextArgRequired();
+ argValue = nextArgRequired();
+ 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;
- }
-
+ String cnArg = nextArgRequired();
ComponentName cn = ComponentName.unflattenFromString(cnArg);
- if (cn == null) {
- System.err.println("Error: Bad component name: " + cnArg);
- showUsage();
- return;
- }
+ if (cn == null) throw new IllegalArgumentException("Bad component name: " + cnArg);
InstrumentationWatcher watcher = null;
if (wait) {
@@ -331,22 +287,13 @@ public class Am {
}
float[] oldAnims = null;
if (no_window_animation) {
- try {
- oldAnims = wm.getAnimationScales();
- wm.setAnimationScale(0, 0.0f);
- wm.setAnimationScale(1, 0.0f);
- } catch (RemoteException e) {
- }
+ oldAnims = wm.getAnimationScales();
+ wm.setAnimationScale(0, 0.0f);
+ wm.setAnimationScale(1, 0.0f);
}
- try {
- if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher)) {
- System.out.println("INSTRUMENTATION_FAILED: " +
- cn.flattenToString());
- showUsage();
- return;
- }
- } catch (RemoteException e) {
+ if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher)) {
+ throw new AndroidException("INSTRUMENTATION_FAILED: " + cn.flattenToString());
}
if (watcher != null) {
@@ -356,9 +303,58 @@ public class Am {
}
if (oldAnims != null) {
+ wm.setAnimationScales(oldAnims);
+ }
+ }
+
+ private void runProfile() throws Exception {
+ String profileFile = null;
+ boolean start = false;
+ String process = nextArgRequired();
+ ParcelFileDescriptor fd = null;
+
+ String cmd = nextArgRequired();
+ if ("start".equals(cmd)) {
+ start = true;
+ profileFile = nextArgRequired();
+ try {
+ fd = ParcelFileDescriptor.open(
+ new File(profileFile),
+ ParcelFileDescriptor.MODE_CREATE |
+ ParcelFileDescriptor.MODE_TRUNCATE |
+ ParcelFileDescriptor.MODE_READ_WRITE);
+ } catch (FileNotFoundException e) {
+ System.err.println("Error: Unable to open file: " + profileFile);
+ return;
+ }
+ } else if (!"stop".equals(cmd)) {
+ throw new IllegalArgumentException("Profile command " + cmd + " not valid");
+ }
+
+ if (!mAm.profileControl(process, start, profileFile, fd)) {
+ throw new AndroidException("PROFILE FAILED on process " + process);
+ }
+ }
+
+ private class IntentReceiver extends IIntentReceiver.Stub {
+ private boolean mFinished = false;
+
+ public synchronized void performReceive(
+ Intent intent, int rc, String data, Bundle ext, boolean ord,
+ boolean sticky) {
+ String line = "Broadcast completed: result=" + rc;
+ if (data != null) line = line + ", data=\"" + data + "\"";
+ if (ext != null) line = line + ", extras: " + ext;
+ System.out.println(line);
+ mFinished = true;
+ notifyAll();
+ }
+
+ public synchronized void waitForFinish() {
try {
- wm.setAnimationScales(oldAnims);
- } catch (RemoteException e) {
+ while (!mFinished) wait();
+ } catch (InterruptedException e) {
+ throw new IllegalStateException(e);
}
}
}
@@ -366,7 +362,7 @@ public class Am {
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.
@@ -375,7 +371,7 @@ public class Am {
public void setRawOutput(boolean rawMode) {
mRawMode = rawMode;
}
-
+
public void instrumentationStatus(ComponentName name, int resultCode, Bundle results) {
synchronized (this) {
// pretty printer mode?
@@ -431,6 +427,7 @@ public class Am {
}
wait(1000);
} catch (InterruptedException e) {
+ throw new IllegalStateException(e);
}
}
}
@@ -438,62 +435,11 @@ public class Am {
}
}
- private void runProfile() {
- String profileFile = null;
- boolean start = false;
-
- String process = nextArg();
- if (process == null) {
- System.err.println("Error: No profile process supplied");
- showUsage();
- return;
- }
-
- ParcelFileDescriptor fd = null;
-
- String cmd = nextArg();
- if ("start".equals(cmd)) {
- start = true;
- profileFile = nextArg();
- if (profileFile == null) {
- System.err.println("Error: No profile file path supplied");
- showUsage();
- return;
- }
- try {
- fd = ParcelFileDescriptor.open(
- new File(profileFile),
- ParcelFileDescriptor.MODE_CREATE |
- ParcelFileDescriptor.MODE_TRUNCATE |
- ParcelFileDescriptor.MODE_READ_WRITE);
- } catch (FileNotFoundException e) {
- System.err.println("Error: Unable to open file: " + profileFile);
- return;
- }
- } else if (!"stop".equals(cmd)) {
- System.err.println("Error: Profile command " + cmd + " not valid");
- showUsage();
- return;
- }
-
- try {
- if (!mAm.profileControl(process, start, profileFile, fd)) {
- System.err.println("PROFILE FAILED on process " + process);
- return;
- }
- } catch (IllegalArgumentException e) {
- System.out.println("PROFILE FAILED: " + e.getMessage());
- return;
- } catch (IllegalStateException e) {
- System.out.println("PROFILE FAILED: " + e.getMessage());
- return;
- } catch (RemoteException e) {
- System.out.println("PROFILE FAILED: activity manager gone");
- return;
- }
- }
-
private String nextOption() {
+ if (mCurArgData != null) {
+ String prev = mArgs[mNextArg - 1];
+ throw new IllegalArgumentException("No argument expected after \"" + prev + "\"");
+ }
if (mNextArg >= mArgs.length) {
return null;
}
@@ -518,41 +464,52 @@ public class Am {
return arg;
}
- private String nextOptionData() {
+ private String nextArg() {
if (mCurArgData != null) {
- return mCurArgData;
- }
- if (mNextArg >= mArgs.length) {
+ String arg = mCurArgData;
+ mCurArgData = null;
+ return arg;
+ } else if (mNextArg < mArgs.length) {
+ return mArgs[mNextArg++];
+ } else {
return null;
}
- String data = mArgs[mNextArg];
- mNextArg++;
- return data;
}
- private String nextArg() {
- if (mNextArg >= mArgs.length) {
- return null;
+ private String nextArgRequired() {
+ String arg = nextArg();
+ if (arg == null) {
+ String prev = mArgs[mNextArg - 1];
+ throw new IllegalArgumentException("Argument expected after \"" + prev + "\"");
}
- String arg = mArgs[mNextArg];
- mNextArg++;
return arg;
}
- private void showUsage() {
- System.err.println("usage: am [start|broadcast|instrument|profile]");
- 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(" am profile <PROCESS> [start <PROF_FILE>|stop]");
- 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>]");
+ private static void showUsage() {
+ System.err.println(
+ "usage: am [subcommand] [options]\n" +
+ "\n" +
+ " start an Activity: am start [-D] <INTENT>\n" +
+ " -D: enable debugging\n" +
+ "\n" +
+ " send a broadcast Intent: am broadcast <INTENT>\n" +
+ "\n" +
+ " start an Instrumentation: am instrument [flags] <COMPONENT>\n" +
+ " -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT)\n" +
+ " -e <NAME> <VALUE>: set argument <NAME> to <VALUE>\n" +
+ " -p <FILE>: write profiling data to <FILE>\n" +
+ " -w: wait for instrumentation to finish before returning\n" +
+ "\n" +
+ " start profiling: am profile <PROCESS> start <FILE>\n" +
+ " stop profiling: am profile <PROCESS> stop\n" +
+ "\n" +
+ " <INTENT> specifications include these flags:\n" +
+ " [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" +
+ " [-c <CATEGORY> [-c <CATEGORY>] ...]\n" +
+ " [-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]\n" +
+ " [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]\n" +
+ " [-e|--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]\n" +
+ " [-n <COMPONENT>] [-f <FLAGS>] [<URI>]\n"
+ );
}
}
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
index d825d5a3a4dc..7decf9ae737d 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -7,8 +7,8 @@
#define LOG_TAG "appproc"
-#include <utils/IPCThreadState.h>
-#include <utils/ProcessState.h>
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
#include <utils/Log.h>
#include <cutils/process_name.h>
#include <cutils/memory.h>
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
index ee3ec1aa18fb..8c15d0b4ea13 100644
--- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
+++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
@@ -268,7 +268,7 @@ public final class Bmgr {
private void printRestoreSets(RestoreSet[] sets) {
for (RestoreSet s : sets) {
- System.out.println(" " + s.token + " : " + s.name);
+ System.out.println(" " + Long.toHexString(s.token) + " : " + s.name);
}
}
@@ -294,7 +294,7 @@ public final class Bmgr {
private void doRestore() {
long token;
try {
- token = Long.parseLong(nextArg());
+ token = Long.parseLong(nextArg(), 16);
} catch (NumberFormatException e) {
showUsage();
return;
@@ -311,12 +311,13 @@ public final class Bmgr {
return;
}
RestoreSet[] sets = mRestore.getAvailableRestoreSets();
- for (RestoreSet s : sets) {
- if (s.token == token) {
- System.out.println("Scheduling restore: " + s.name);
- mRestore.performRestore(token, observer);
- didRestore = true;
- break;
+ if (sets != null) {
+ for (RestoreSet s : sets) {
+ if (s.token == token) {
+ System.out.println("Scheduling restore: " + s.name);
+ didRestore = (mRestore.performRestore(token, observer) == 0);
+ break;
+ }
}
}
if (!didRestore) {
@@ -327,21 +328,27 @@ public final class Bmgr {
printRestoreSets(sets);
}
}
+
+ // if we kicked off a restore successfully, we have to wait for it
+ // to complete before we can shut down the restore session safely
+ if (didRestore) {
+ synchronized (observer) {
+ while (!observer.done) {
+ try {
+ observer.wait();
+ } catch (InterruptedException ex) {
+ }
+ }
+ }
+ }
+
+ // once the restore has finished, close down the session and we're done
mRestore.endRestoreSession();
} catch (RemoteException e) {
System.err.println(e.toString());
System.err.println(BMGR_NOT_RUNNING_ERR);
}
- // now wait for it to be done
- synchronized (observer) {
- while (!observer.done) {
- try {
- observer.wait();
- } catch (InterruptedException ex) {
- }
- }
- }
System.out.println("done");
}
diff --git a/cmds/bootanimation/Android.mk b/cmds/bootanimation/Android.mk
index 9c94c2ef3cf9..3449de1fe737 100644
--- a/cmds/bootanimation/Android.mk
+++ b/cmds/bootanimation/Android.mk
@@ -12,12 +12,13 @@ ifeq ($(TARGET_SIMULATOR),true)
endif
endif
+LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
libui \
- libcorecg \
- libsgl \
+ libskia \
libEGL \
libGLESv1_CM
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 2fb3f7994961..ce36c4b3320a 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -21,8 +21,9 @@
#include <math.h>
#include <fcntl.h>
#include <utils/misc.h>
+#include <signal.h>
-#include <utils/IPCThreadState.h>
+#include <binder/IPCThreadState.h>
#include <utils/threads.h>
#include <utils/Atomic.h>
#include <utils/Errors.h>
@@ -35,7 +36,8 @@
#include <ui/DisplayInfo.h>
#include <ui/ISurfaceComposer.h>
#include <ui/ISurfaceFlingerClient.h>
-#include <ui/EGLNativeWindowSurface.h>
+#include <ui/FramebufferNativeWindow.h>
+#include <ui/EGLUtils.h>
#include <core/SkBitmap.h>
#include <images/SkImageDecoder.h>
@@ -51,7 +53,7 @@ namespace android {
// ---------------------------------------------------------------------------
BootAnimation::BootAnimation() : Thread(false)
-{
+{
mSession = new SurfaceComposerClient();
}
@@ -59,13 +61,29 @@ BootAnimation::~BootAnimation() {
}
void BootAnimation::onFirstRef() {
- run("BootAnimation", PRIORITY_DISPLAY);
+ status_t err = mSession->linkToComposerDeath(this);
+ LOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err));
+ if (err == NO_ERROR) {
+ run("BootAnimation", PRIORITY_DISPLAY);
+ }
}
-const sp<SurfaceComposerClient>& BootAnimation::session() const {
+sp<SurfaceComposerClient> BootAnimation::session() const {
return mSession;
}
+
+void BootAnimation::binderDied(const wp<IBinder>& who)
+{
+ // woah, surfaceflinger died!
+ LOGD("SurfaceFlinger died, exiting...");
+
+ // calling requestExit() is not enough here because the Surface code
+ // might be blocked on a condition variable that will never be updated.
+ kill( getpid(), SIGKILL );
+ requestExit();
+}
+
status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets,
const char* name) {
Asset* asset = assets.open(name, Asset::ACCESS_BUFFER);
@@ -121,6 +139,62 @@ status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets,
return NO_ERROR;
}
+status_t BootAnimation::initTexture(void* buffer, size_t len)
+{
+ //StopWatch watch("blah");
+
+ SkBitmap bitmap;
+ SkImageDecoder::DecodeMemory(buffer, len,
+ &bitmap, SkBitmap::kRGB_565_Config,
+ SkImageDecoder::kDecodePixels_Mode);
+
+ // ensure we can call getPixels(). No need to call unlock, since the
+ // bitmap will go out of scope when we return from this method.
+ bitmap.lockPixels();
+
+ const int w = bitmap.width();
+ const int h = bitmap.height();
+ const void* p = bitmap.getPixels();
+
+ GLint crop[4] = { 0, h, w, -h };
+ int tw = 1 << (31 - __builtin_clz(w));
+ int th = 1 << (31 - __builtin_clz(h));
+ if (tw < w) tw <<= 1;
+ if (th < h) th <<= 1;
+
+ switch (bitmap.getConfig()) {
+ case SkBitmap::kARGB_8888_Config:
+ if (tw != w || th != h) {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, 0);
+ glTexSubImage2D(GL_TEXTURE_2D, 0,
+ 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, p);
+ } else {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, p);
+ }
+ break;
+
+ case SkBitmap::kRGB_565_Config:
+ if (tw != w || th != h) {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0, GL_RGB,
+ GL_UNSIGNED_SHORT_5_6_5, 0);
+ glTexSubImage2D(GL_TEXTURE_2D, 0,
+ 0, 0, w, h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, p);
+ } else {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0, GL_RGB,
+ GL_UNSIGNED_SHORT_5_6_5, p);
+ }
+ break;
+ default:
+ break;
+ }
+
+ glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
+
+ return NO_ERROR;
+}
+
status_t BootAnimation::readyToRun() {
mAssets.addDefaultAssets();
@@ -130,15 +204,19 @@ status_t BootAnimation::readyToRun() {
return -1;
// create the native surface
- sp<Surface> s = session()->createSurface(getpid(), 0, dinfo.w, dinfo.h,
- PIXEL_FORMAT_RGB_565, ISurfaceComposer::eGPU);
+ sp<SurfaceControl> control = session()->createSurface(
+ getpid(), 0, dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);
session()->openTransaction();
- s->setLayer(0x40000000);
+ control->setLayer(0x40000000);
session()->closeTransaction();
+ sp<Surface> s = control->getSurface();
+
// initialize opengl and egl
- const EGLint attribs[] = { EGL_RED_SIZE, 5, EGL_GREEN_SIZE, 6,
- EGL_BLUE_SIZE, 5, EGL_DEPTH_SIZE, 0, EGL_NONE };
+ const EGLint attribs[] = {
+ EGL_DEPTH_SIZE, 0,
+ EGL_NONE
+ };
EGLint w, h, dummy;
EGLint numConfigs;
EGLConfig config;
@@ -148,60 +226,75 @@ status_t BootAnimation::readyToRun() {
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, 0, 0);
- eglChooseConfig(display, attribs, &config, 1, &numConfigs);
-
- mNativeWindowSurface = new EGLNativeWindowSurface(s);
- surface = eglCreateWindowSurface(display, config,
- mNativeWindowSurface.get(), NULL);
-
+ EGLUtils::selectConfigForNativeWindow(display, attribs, s.get(), &config);
+ surface = eglCreateWindowSurface(display, config, s.get(), NULL);
context = eglCreateContext(display, config, NULL, NULL);
eglQuerySurface(display, surface, EGL_WIDTH, &w);
eglQuerySurface(display, surface, EGL_HEIGHT, &h);
- eglMakeCurrent(display, surface, surface, context);
+
+ if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)
+ return NO_INIT;
+
mDisplay = display;
mContext = context;
mSurface = surface;
mWidth = w;
mHeight = h;
+ mFlingerSurfaceControl = control;
mFlingerSurface = s;
- // initialize GL
- glShadeModel(GL_FLAT);
- glEnable(GL_TEXTURE_2D);
- glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ mAndroidAnimation = false;
+ status_t err = mZip.open("/data/local/bootanimation.zip");
+ if (err != NO_ERROR) {
+ err = mZip.open("/system/media/bootanimation.zip");
+ if (err != NO_ERROR) {
+ mAndroidAnimation = true;
+ }
+ }
return NO_ERROR;
}
-bool BootAnimation::threadLoop() {
- bool r = android();
+bool BootAnimation::threadLoop()
+{
+ bool r;
+ if (mAndroidAnimation) {
+ r = android();
+ } else {
+ r = movie();
+ }
+
eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroyContext(mDisplay, mContext);
eglDestroySurface(mDisplay, mSurface);
- mNativeWindowSurface.clear();
mFlingerSurface.clear();
+ mFlingerSurfaceControl.clear();
eglTerminate(mDisplay);
IPCThreadState::self()->stopProcess();
return r;
}
-bool BootAnimation::android() {
+bool BootAnimation::android()
+{
initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png");
initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png");
// clear screen
+ glShadeModel(GL_FLAT);
glDisable(GL_DITHER);
glDisable(GL_SCISSOR_TEST);
glClear(GL_COLOR_BUFFER_BIT);
eglSwapBuffers(mDisplay, mSurface);
+ glEnable(GL_TEXTURE_2D);
+ glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
const GLint xc = (mWidth - mAndroid[0].w) / 2;
const GLint yc = (mHeight - mAndroid[0].h) / 2;
const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h);
// draw and update only what we need
- mNativeWindowSurface->setSwapRectangle(updateRect.left,
- updateRect.top, updateRect.width(), updateRect.height());
+ mFlingerSurface->setSwapRectangle(updateRect);
glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(),
updateRect.height());
@@ -238,7 +331,7 @@ bool BootAnimation::android() {
// 12fps: don't animate too fast to preserve CPU
const nsecs_t sleepTime = 83333 - ns2us(systemTime() - now);
if (sleepTime > 0)
- usleep(sleepTime);
+ usleep(sleepTime);
} while (!exitPending());
glDeleteTextures(1, &mAndroid[0].name);
@@ -246,6 +339,167 @@ bool BootAnimation::android() {
return false;
}
+
+bool BootAnimation::movie()
+{
+ ZipFileRO& zip(mZip);
+
+ size_t numEntries = zip.getNumEntries();
+ ZipEntryRO desc = zip.findEntryByName("desc.txt");
+ FileMap* descMap = zip.createEntryFileMap(desc);
+ LOGE_IF(!descMap, "descMap is null");
+ if (!descMap) {
+ return false;
+ }
+
+ String8 desString((char const*)descMap->getDataPtr(),
+ descMap->getDataLength());
+ char const* s = desString.string();
+
+ Animation animation;
+
+ // Parse the description file
+ for (;;) {
+ const char* endl = strstr(s, "\n");
+ if (!endl) break;
+ String8 line(s, endl - s);
+ const char* l = line.string();
+ int fps, width, height, count, pause;
+ char path[256];
+ if (sscanf(l, "%d %d %d", &width, &height, &fps) == 3) {
+ //LOGD("> w=%d, h=%d, fps=%d", fps, width, height);
+ animation.width = width;
+ animation.height = height;
+ animation.fps = fps;
+ }
+ if (sscanf(l, "p %d %d %s", &count, &pause, path) == 3) {
+ //LOGD("> count=%d, pause=%d, path=%s", count, pause, path);
+ Animation::Part part;
+ part.count = count;
+ part.pause = pause;
+ part.path = path;
+ animation.parts.add(part);
+ }
+ s = ++endl;
+ }
+
+ // read all the data structures
+ const size_t pcount = animation.parts.size();
+ for (size_t i=0 ; i<numEntries ; i++) {
+ char name[256];
+ ZipEntryRO entry = zip.findEntryByIndex(i);
+ if (zip.getEntryFileName(entry, name, 256) == 0) {
+ const String8 entryName(name);
+ const String8 path(entryName.getPathDir());
+ const String8 leaf(entryName.getPathLeaf());
+ if (leaf.size() > 0) {
+ for (int j=0 ; j<pcount ; j++) {
+ if (path == animation.parts[j].path) {
+ int method;
+ // supports only stored png files
+ if (zip.getEntryInfo(entry, &method, 0, 0, 0, 0, 0)) {
+ if (method == ZipFileRO::kCompressStored) {
+ FileMap* map = zip.createEntryFileMap(entry);
+ if (map) {
+ Animation::Frame frame;
+ frame.name = leaf;
+ frame.map = map;
+ Animation::Part& part(animation.parts.editItemAt(j));
+ part.frames.add(frame);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // clear screen
+ glShadeModel(GL_FLAT);
+ glDisable(GL_DITHER);
+ glDisable(GL_SCISSOR_TEST);
+ glDisable(GL_BLEND);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ eglSwapBuffers(mDisplay, mSurface);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glEnable(GL_TEXTURE_2D);
+ glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ const int xc = (mWidth - animation.width) / 2;
+ const int yc = ((mHeight - animation.height) / 2);
+ nsecs_t lastFrame = systemTime();
+ nsecs_t frameDuration = s2ns(1) / animation.fps;
+
+ Region clearReg(Rect(mWidth, mHeight));
+ clearReg.subtractSelf(Rect(xc, yc, xc+animation.width, yc+animation.height));
+
+ for (int i=0 ; i<pcount && !exitPending() ; i++) {
+ const Animation::Part& part(animation.parts[i]);
+ const size_t fcount = part.frames.size();
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ for (int r=0 ; !part.count || r<part.count ; r++) {
+ for (int j=0 ; j<fcount && !exitPending(); j++) {
+ const Animation::Frame& frame(part.frames[j]);
+
+ if (r > 0) {
+ glBindTexture(GL_TEXTURE_2D, frame.tid);
+ } else {
+ if (part.count != 1) {
+ glGenTextures(1, &frame.tid);
+ glBindTexture(GL_TEXTURE_2D, frame.tid);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ }
+ initTexture(
+ frame.map->getDataPtr(),
+ frame.map->getDataLength());
+ }
+
+ if (!clearReg.isEmpty()) {
+ Region::const_iterator head(clearReg.begin());
+ Region::const_iterator tail(clearReg.end());
+ glEnable(GL_SCISSOR_TEST);
+ while (head != tail) {
+ const Rect& r(*head++);
+ glScissor(r.left, mHeight - r.bottom,
+ r.width(), r.height());
+ glClear(GL_COLOR_BUFFER_BIT);
+ }
+ glDisable(GL_SCISSOR_TEST);
+ }
+ glDrawTexiOES(xc, yc, 0, animation.width, animation.height);
+ eglSwapBuffers(mDisplay, mSurface);
+
+ nsecs_t now = systemTime();
+ nsecs_t delay = frameDuration - (now - lastFrame);
+ lastFrame = now;
+ long wait = ns2us(frameDuration);
+ if (wait > 0)
+ usleep(wait);
+ }
+ usleep(part.pause * ns2us(frameDuration));
+ }
+
+ // free the textures for this part
+ if (part.count != 1) {
+ for (int j=0 ; j<fcount ; j++) {
+ const Animation::Frame& frame(part.frames[j]);
+ glDeleteTextures(1, &frame.tid);
+ }
+ }
+ }
+
+ return false;
+}
+
// ---------------------------------------------------------------------------
}
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index 42e9eed7d3eb..e53ba8b95114 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -34,22 +34,22 @@ class SkBitmap;
namespace android {
class AssetManager;
-class EGLNativeWindowSurface;
// ---------------------------------------------------------------------------
-class BootAnimation : public Thread
+class BootAnimation : public Thread, public IBinder::DeathRecipient
{
public:
BootAnimation();
virtual ~BootAnimation();
- const sp<SurfaceComposerClient>& session() const;
+ sp<SurfaceComposerClient> session() const;
private:
virtual bool threadLoop();
virtual status_t readyToRun();
virtual void onFirstRef();
+ virtual void binderDied(const wp<IBinder>& who);
struct Texture {
GLint w;
@@ -57,8 +57,31 @@ private:
GLuint name;
};
+ struct Animation {
+ struct Frame {
+ String8 name;
+ FileMap* map;
+ mutable GLuint tid;
+ bool operator < (const Frame& rhs) const {
+ return name < rhs.name;
+ }
+ };
+ struct Part {
+ int count;
+ int pause;
+ String8 path;
+ SortedVector<Frame> frames;
+ };
+ int fps;
+ int width;
+ int height;
+ Vector<Part> parts;
+ };
+
status_t initTexture(Texture* texture, AssetManager& asset, const char* name);
+ status_t initTexture(void* buffer, size_t len);
bool android();
+ bool movie();
sp<SurfaceComposerClient> mSession;
AssetManager mAssets;
@@ -68,8 +91,10 @@ private:
EGLDisplay mDisplay;
EGLDisplay mContext;
EGLDisplay mSurface;
+ sp<SurfaceControl> mFlingerSurfaceControl;
sp<Surface> mFlingerSurface;
- sp<EGLNativeWindowSurface> mNativeWindowSurface;
+ bool mAndroidAnimation;
+ ZipFileRO mZip;
};
// ---------------------------------------------------------------------------
diff --git a/cmds/bootanimation/bootanimation_main.cpp b/cmds/bootanimation/bootanimation_main.cpp
index a8359c40d0d2..3c82fe52dba9 100644
--- a/cmds/bootanimation/bootanimation_main.cpp
+++ b/cmds/bootanimation/bootanimation_main.cpp
@@ -18,9 +18,10 @@
#include <cutils/properties.h>
-#include <utils/IPCThreadState.h>
-#include <utils/ProcessState.h>
-#include <utils/IServiceManager.h>
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
+
#include <utils/Log.h>
#include <utils/threads.h>
diff --git a/cmds/bugreport/Android.mk b/cmds/bugreport/Android.mk
new file mode 100644
index 000000000000..631c2193a987
--- /dev/null
+++ b/cmds/bugreport/Android.mk
@@ -0,0 +1,14 @@
+ifneq ($(TARGET_SIMULATOR),true)
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= bugreport.c
+
+LOCAL_MODULE:= bugreport
+
+LOCAL_SHARED_LIBRARIES := libcutils
+
+include $(BUILD_EXECUTABLE)
+
+endif
diff --git a/cmds/bugreport/bugreport.c b/cmds/bugreport/bugreport.c
new file mode 100644
index 000000000000..4a0b51147011
--- /dev/null
+++ b/cmds/bugreport/bugreport.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <cutils/properties.h>
+#include <cutils/sockets.h>
+
+int main(int argc, char *argv[]) {
+ char buffer[65536];
+ int i, s;
+
+ /* start the dumpstate service */
+ property_set("ctl.start", "dumpstate");
+
+ /* socket will not be available until service starts */
+ for (i = 0; i < 10; i++) {
+ s = socket_local_client("dumpstate",
+ ANDROID_SOCKET_NAMESPACE_RESERVED,
+ SOCK_STREAM);
+ if (s >= 0)
+ break;
+ /* try again in 1 second */
+ sleep(1);
+ }
+
+ if (s < 0) {
+ fprintf(stderr, "Failed to connect to dumpstate service\n");
+ exit(1);
+ }
+
+ while (1) {
+ int length = read(s, buffer, sizeof(buffer));
+ if (length <= 0)
+ break;
+ fwrite(buffer, 1, length, stdout);
+ }
+
+ close(s);
+ return 0;
+}
diff --git a/cmds/dumpstate/Android.mk b/cmds/dumpstate/Android.mk
index f61d7ecb3f5a..f8b37a812d08 100644
--- a/cmds/dumpstate/Android.mk
+++ b/cmds/dumpstate/Android.mk
@@ -11,7 +11,7 @@ LOCAL_SHARED_LIBRARIES := libcutils
include $(BUILD_EXECUTABLE)
-COMMANDS = dumpcrash bugreport
+COMMANDS = dumpcrash
SYMLINKS := $(addprefix $(TARGET_OUT_EXECUTABLES)/,$(COMMANDS))
$(SYMLINKS): DUMPSTATE_BINARY := dumpstate
$(SYMLINKS): $(LOCAL_INSTALLED_MODULE) $(LOCAL_PATH)/Android.mk
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index cc951c1bcbd1..642c943ffd36 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -20,12 +20,18 @@
#include <unistd.h>
#include <sys/stat.h>
#include <limits.h>
+#include <errno.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/resource.h>
+#include <cutils/sockets.h>
#include "private/android_filesystem_config.h"
+#define LOG_NDEBUG 0
+#define LOG_TAG "dumpstate"
+#include <utils/Log.h>
+
#include "dumpstate.h"
static char* const gzip_args[] = { "gzip", "-6", 0 };
@@ -34,6 +40,8 @@ static int end_pattern[] = { 75, 50, 75, 50, 75, 0 };
static struct tm now;
+static void dump_kernel_log(const char *path, const char *title) ;
+
/* dumps the current system state to stdout */
static void dumpstate(int full) {
if (full) {
@@ -48,6 +56,8 @@ static void dumpstate(int full) {
EXEC_XBIN("procrank");
PRINT("------ VIRTUAL MEMORY STATS ------");
DUMP("/proc/vmstat");
+ PRINT("------ VMALLOC INFO ------");
+ DUMP("/proc/vmallocinfo");
PRINT("------ SLAB INFO ------");
DUMP("/proc/slabinfo");
PRINT("------ ZONEINFO ------");
@@ -76,9 +86,9 @@ static void dumpstate(int full) {
DUMP("/proc/wakelocks");
PRINT("");
PRINT("------ PROCESSES ------");
- EXEC("ps");
+ EXEC1("ps", "-P");
PRINT("------ PROCESSES AND THREADS ------");
- EXEC2("ps", "-t", "-p");
+ EXEC3("ps", "-t", "-p", "-P");
PRINT("------ LIBRANK ------");
EXEC_XBIN("librank");
PRINT("------ BINDER FAILED TRANSACTION LOG ------");
@@ -101,8 +111,19 @@ static void dumpstate(int full) {
DUMP("/data/system/packages.xml");
PRINT("------ PACKAGE UID ERRORS ------");
DUMP("/data/system/uiderrors.txt");
- PRINT("------ LAST KERNEL LOG ------");
- DUMP("/proc/last_kmsg");
+
+ dump_kernel_log("/data/dontpanic/last_kmsg", "LAST KMSG");
+ dump_kernel_log("/data/dontpanic/apanic_console",
+ "PANIC CONSOLE");
+ dump_kernel_log("/data/dontpanic/apanic_threads",
+ "PANIC THREADS");
+
+ PRINT("------ BACKLIGHTS ------");
+ DUMP_PROMPT("LCD brightness=", "/sys/class/leds/lcd-backlight/brightness");
+ DUMP_PROMPT("Button brightness=", "/sys/class/leds/button-backlight/brightness");
+ DUMP_PROMPT("Keyboard brightness=", "/sys/class/leds/keyboard-backlight/brightness");
+ DUMP_PROMPT("ALS mode=", "/sys/class/leds/lcd-backlight/als");
+ DUMP_PROMPT("LCD driver registers:\n", "/sys/class/leds/lcd-backlight/registers");
}
PRINT("========================================================");
PRINT("== build.prop");
@@ -157,47 +178,50 @@ static int check_command_name(const char* name, const char* test) {
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 socket = 0;
int c, fd, vibrate_fd, fds[2];
char path[PATH_MAX];
pid_t pid;
gid_t groups[] = { AID_LOG, AID_SDCARD_RW };
+ LOGI("begin\n");
+
/* 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)
+ do {
+ c = getopt(argc, argv, "do:svz");
+ if (c == EOF)
+ break;
+ switch (c) {
+ case 'd':
+ add_date = 1;
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);
- }
+ case 'o':
+ outfile = optarg;
+ break;
+ case 'v':
+ vibrate = 1;
+ break;
+ case 'z':
+ compress = 1;
+ break;
+ case 's':
+ socket = 1;
+ break;
+ case '?':
+ fprintf(stderr, "%s: invalid option -%c\n",
+ argv[0], optopt);
+ exit(1);
+ }
+ } while (1);
/* open vibrator before switching user */
if (vibrate) {
@@ -214,7 +238,31 @@ int main(int argc, char *argv[]) {
/* make it safe to use both printf and STDOUT_FILENO */
setvbuf(stdout, 0, _IONBF, 0);
- if (outfile) {
+ if (socket) {
+ struct sockaddr addr;
+ socklen_t alen;
+
+ int s = android_get_control_socket("dumpstate");
+ if (s < 0) {
+ fprintf(stderr, "could not open dumpstate socket\n");
+ exit(1);
+ }
+ if (listen(s, 4) < 0) {
+ fprintf(stderr, "could not listen on dumpstate socket\n");
+ exit(1);
+ }
+
+ alen = sizeof(addr);
+ fd = accept(s, &addr, &alen);
+ if (fd < 0) {
+ fprintf(stderr, "could not accept dumpstate socket\n");
+ exit(1);
+ }
+
+ /* redirect stdout to the socket */
+ dup2(fd, STDOUT_FILENO);
+ close(fd);
+ } else if (outfile) {
if (strlen(outfile) > sizeof(path) - 100)
exit(1);
@@ -292,6 +340,25 @@ int main(int argc, char *argv[]) {
/* so gzip will terminate */
close(STDOUT_FILENO);
+ LOGI("done\n");
+
return 0;
}
+static void dump_kernel_log(const char *path, const char *title)
+
+{
+ printf("------ KERNEL %s LOG ------\n", title);
+ if (access(path, R_OK) < 0)
+ printf("%s: %s\n", path, strerror(errno));
+ else {
+ struct stat sbuf;
+
+ if (stat(path, &sbuf) < 0)
+ printf("%s: stat failed (%s)\n", path, strerror(errno));
+ else
+ printf("Harvested %s", ctime(&sbuf.st_mtime));
+
+ DUMP(path);
+ }
+}
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 6862e5a3edb4..b99b6d792249 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -61,6 +61,15 @@
run_command(&c, TIMEOUT); \
}
+#define EXEC1(cmd, a1) \
+{ \
+ static struct Command c = { \
+ "/system/bin/" cmd, \
+ { cmd, a1, 0 } \
+ }; \
+ run_command(&c, TIMEOUT); \
+}
+
#define EXEC2(cmd, a1, a2) \
{ \
static struct Command c = { \
@@ -70,6 +79,15 @@
run_command(&c, TIMEOUT); \
}
+#define EXEC3(cmd, a1, a2, a3) \
+{ \
+ static struct Command c = { \
+ "/system/bin/" cmd, \
+ { cmd, a1, a2, a3, 0 } \
+ }; \
+ run_command(&c, TIMEOUT); \
+}
+
#define EXEC4(cmd, a1, a2, a3, a4) \
{ \
static struct Command c = { \
diff --git a/cmds/dumpsys/Android.mk b/cmds/dumpsys/Android.mk
index 0c623cc319c5..42b1b7365b1b 100644
--- a/cmds/dumpsys/Android.mk
+++ b/cmds/dumpsys/Android.mk
@@ -5,7 +5,9 @@ LOCAL_SRC_FILES:= \
dumpsys.cpp
LOCAL_SHARED_LIBRARIES := \
- libutils
+ libutils \
+ libbinder
+
ifeq ($(TARGET_OS),linux)
LOCAL_CFLAGS += -DXP_UNIX
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index a62fe55600e9..945a690ae0ab 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -6,9 +6,9 @@
#define LOG_TAG "dumpsys"
#include <utils/Log.h>
-#include <utils/Parcel.h>
-#include <utils/ProcessState.h>
-#include <utils/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
#include <utils/TextOutput.h>
#include <utils/Vector.h>
diff --git a/cmds/keystore/Android.mk b/cmds/keystore/Android.mk
index 3daf44e40a00..15a199f30c46 100644
--- a/cmds/keystore/Android.mk
+++ b/cmds/keystore/Android.mk
@@ -1,22 +1,36 @@
+#
+# Copyright (C) 2009 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
ifneq ($(TARGET_SIMULATOR),true)
LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- netkeystore.c keymgmt.c
-
-LOCAL_C_INCLUDES := \
- $(call include-path-for, system-core)/cutils \
- external/openssl/include
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils libssl
-
-LOCAL_STATIC_LIBRARIES :=
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := keystore.c
+LOCAL_C_INCLUDES := external/openssl/include
+LOCAL_SHARED_LIBRARIES := libcutils libcrypto
LOCAL_MODULE:= keystore
+include $(BUILD_EXECUTABLE)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := keystore_cli.c
+LOCAL_C_INCLUDES := external/openssl/include
+LOCAL_SHARED_LIBRARIES := libcutils libcrypto
+LOCAL_MODULE:= keystore_cli
+LOCAL_MODULE_TAGS := debug
include $(BUILD_EXECUTABLE)
-endif # !simulator))
+endif
diff --git a/cmds/keystore/certtool.h b/cmds/keystore/certtool.h
deleted file mode 100644
index aefad668d160..000000000000
--- a/cmds/keystore/certtool.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifndef __CERTTOOL_H__
-#define __CERTTOOL_H__
-
-#include <stdio.h>
-#include <string.h>
-#include <cutils/sockets.h>
-#include <cutils/log.h>
-
-#include "common.h"
-#include "netkeystore.h"
-
-#define CERT_NAME_LEN (2 * MAX_KEY_NAME_LENGTH + 2)
-
-/*
- * The specific function 'get_cert' is used in daemons to get the key value
- * from keystore. Caller should allocate the buffer and the length of the buffer
- * should be MAX_KEY_VALUE_LENGTH.
- */
-static inline int get_cert(const char *certname, unsigned char *value, int *size)
-{
- int count, fd, ret = -1;
- LPC_MARSHAL cmd;
- char delimiter[] = "_";
- char *namespace, *keyname;
- char *context = NULL;
- char cname[CERT_NAME_LEN];
-
- if ((certname == NULL) || (value == NULL)) {
- LOGE("get_cert: certname or value is null\n");
- return -1;
- }
-
- if (strlcpy(cname, certname, CERT_NAME_LEN) >= CERT_NAME_LEN) {
- LOGE("get_cert: keyname is too long\n");
- return -1;
- }
-
- fd = socket_local_client(SOCKET_PATH,
- ANDROID_SOCKET_NAMESPACE_RESERVED,
- SOCK_STREAM);
- if (fd == -1) {
- LOGE("Keystore service is not up and running.\n");
- return -1;
- }
-
- cmd.opcode = GET;
- if (((namespace = strtok_r(cname, delimiter, &context)) == NULL) ||
- ((keyname = strtok_r(NULL, delimiter, &context)) == NULL)) {
- goto err;
- }
- if ((cmd.len = snprintf((char*)cmd.data, BUFFER_MAX, "%s %s", namespace, keyname))
- > (2 * MAX_KEY_NAME_LENGTH + 1)) goto err;
-
- if (write_marshal(fd, &cmd)) {
- LOGE("Incorrect command or command line is too long.\n");
- goto err;
- }
- if (read_marshal(fd, &cmd)) {
- LOGE("Failed to read the result.\n");
- goto err;
- }
-
- // copy the result if succeeded.
- if (!cmd.retcode && cmd.len <= BUFFER_MAX) {
- memcpy(value, cmd.data, cmd.len);
- ret = 0;
- *size = cmd.len;
- }
-err:
- close(fd);
- return ret;
-}
-
-#endif
diff --git a/cmds/keystore/common.h b/cmds/keystore/common.h
deleted file mode 100644
index a18114e91abc..000000000000
--- a/cmds/keystore/common.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifndef __COMMON_H__
-#define __COMMON_H__
-
-#define SOCKET_PATH "keystore"
-#define KEYSTORE_DIR "/data/misc/keystore/"
-
-#define READ_TIMEOUT 3
-#define MAX_KEY_NAME_LENGTH 64
-#define MAX_NAMESPACE_LENGTH MAX_KEY_NAME_LENGTH
-#define MAX_KEY_VALUE_LENGTH 4096
-
-#define BUFFER_MAX MAX_KEY_VALUE_LENGTH
-
-typedef enum {
- BOOTUP,
- UNINITIALIZED,
- LOCKED,
- UNLOCKED,
-} KEYSTORE_STATE;
-
-typedef enum {
- LOCK,
- UNLOCK,
- PASSWD,
- GETSTATE,
- LISTKEYS,
- GET,
- PUT,
- REMOVE,
- RESET,
- MAX_OPCODE
-} KEYSTORE_OPCODE;
-
-typedef struct {
- uint32_t len;
- union {
- uint32_t opcode;
- uint32_t retcode;
- };
- unsigned char data[BUFFER_MAX + 1];
-} LPC_MARSHAL;
-
-#endif
diff --git a/cmds/keystore/keymgmt.c b/cmds/keystore/keymgmt.c
deleted file mode 100644
index 9a1f8457d224..000000000000
--- a/cmds/keystore/keymgmt.c
+++ /dev/null
@@ -1,426 +0,0 @@
-/*
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <errno.h>
-#include <openssl/aes.h>
-#include <openssl/evp.h>
-#include <cutils/log.h>
-
-#include "common.h"
-#include "keymgmt.h"
-
-static int retry_count = 0;
-static unsigned char iv[IV_LEN];
-static KEYSTORE_STATE state = BOOTUP;
-static AES_KEY encryptKey, decryptKey;
-
-inline void unlock_keystore(unsigned char *master_key)
-{
- AES_set_encrypt_key(master_key, AES_KEY_LEN, &encryptKey);
- AES_set_decrypt_key(master_key, AES_KEY_LEN, &decryptKey);
- memset(master_key, 0, sizeof(master_key));
- state = UNLOCKED;
-}
-
-inline void lock_keystore()
-{
- memset(&encryptKey, 0 , sizeof(AES_KEY));
- memset(&decryptKey, 0 , sizeof(AES_KEY));
- state = LOCKED;
-}
-
-inline void get_encrypt_key(char *passwd, AES_KEY *key)
-{
- unsigned char user_key[USER_KEY_LEN];
- gen_key(passwd, user_key, USER_KEY_LEN);
- AES_set_encrypt_key(user_key, AES_KEY_LEN, key);
-}
-
-inline void get_decrypt_key(char *passwd, AES_KEY *key)
-{
- unsigned char user_key[USER_KEY_LEN];
- gen_key(passwd, user_key, USER_KEY_LEN);
- AES_set_decrypt_key(user_key, AES_KEY_LEN, key);
-}
-
-static int gen_random_blob(unsigned char *key, int size)
-{
- int ret = 0;
- int fd = open("/dev/urandom", O_RDONLY);
- if (fd == -1) return -1;
- if (read(fd, key, size) != size) ret = -1;
- close(fd);
- return ret;
-}
-
-static int encrypt_n_save(AES_KEY *enc_key, DATA_BLOB *blob,
- const char *keyfile)
-{
- int size, fd, ret = -1;
- unsigned char enc_blob[MAX_BLOB_LEN];
- char tmpfile[KEYFILE_LEN];
-
- if ((keyfile == NULL) || (strlen(keyfile) >= (KEYFILE_LEN - 4))) {
- LOGE("keyfile name is too long or null");
- return -1;
- }
- strcpy(tmpfile, keyfile);
- strcat(tmpfile, ".tmp");
-
- // prepare the blob
- if (IV_LEN > USER_KEY_LEN) {
- LOGE("iv length is too long.");
- return -1;
- }
- memcpy(blob->iv, iv, IV_LEN);
- blob->blob_size = get_blob_size(blob);
- if (blob->blob_size > MAX_BLOB_LEN) {
- LOGE("blob data size is too large.");
- return -1;
- }
- memcpy(enc_blob, blob->blob, blob->blob_size);
- AES_cbc_encrypt((unsigned char *)enc_blob, (unsigned char *)blob->blob,
- blob->blob_size, enc_key, iv, AES_ENCRYPT);
- // write to keyfile
- size = data_blob_size(blob);
- if ((fd = open(tmpfile, O_CREAT|O_RDWR)) == -1) return -1;
- if (write(fd, blob, size) == size) ret = 0;
- close(fd);
- if (!ret) {
- unlink(keyfile);
- rename(tmpfile, keyfile);
- chmod(keyfile, 0440);
- }
- return ret;
-}
-
-static int load_n_decrypt(const char *keyname, const char *keyfile,
- AES_KEY *key, DATA_BLOB *blob)
-{
- int fd, ret = -1;
- if ((fd = open(keyfile, O_RDONLY)) == -1) return -1;
- // get the encrypted blob and iv
- if ((read(fd, blob->iv, sizeof(blob->iv)) != sizeof(blob->iv)) ||
- (read(fd, &blob->blob_size, sizeof(uint32_t)) != sizeof(uint32_t)) ||
- (blob->blob_size > MAX_BLOB_LEN)) {
- goto err;
- } else {
- unsigned char enc_blob[MAX_BLOB_LEN];
- if (read(fd, enc_blob, blob->blob_size) !=
- (int) blob->blob_size) goto err;
- // decrypt the blob
- AES_cbc_encrypt((unsigned char *)enc_blob, (unsigned char*)blob->blob,
- blob->blob_size, key, blob->iv, AES_DECRYPT);
- if (strcmp(keyname, (char*)blob->keyname) == 0) ret = 0;
- }
-err:
- close(fd);
- return ret;
-}
-
-static int store_master_key(char *upasswd, unsigned char *master_key)
-{
- AES_KEY key;
- DATA_BLOB blob;
-
- // prepare the blob
- if (strlen(MASTER_KEY_TAG) >= USER_KEY_LEN) return -1;
- strlcpy(blob.keyname, MASTER_KEY_TAG, USER_KEY_LEN);
- blob.value_size = USER_KEY_LEN;
- if (USER_KEY_LEN > MAX_KEY_VALUE_LENGTH) {
- LOGE("master_key length is too long.");
- return -1;
- }
- memcpy((void*)blob.value, (const void*)master_key, USER_KEY_LEN);
-
- // generate the encryption key
- get_encrypt_key(upasswd, &key);
- return encrypt_n_save(&key, &blob, MASTER_KEY);
-}
-
-static int get_master_key(char *upasswd, unsigned char *master_key)
-{
- AES_KEY key;
- int size, ret = 0;
- DATA_BLOB blob;
-
- get_decrypt_key(upasswd, &key);
- ret = load_n_decrypt(MASTER_KEY_TAG, MASTER_KEY, &key, &blob);
- if (blob.value_size > USER_KEY_LEN) {
- LOGE("the blob's value size is too large");
- return -1;
- }
- if (!ret) memcpy(master_key, blob.value, blob.value_size);
- return ret;
-}
-
-static int create_master_key(char *upasswd)
-{
- int ret;
- unsigned char mpasswd[AES_KEY_LEN];
- unsigned char master_key[USER_KEY_LEN];
-
- gen_random_blob(mpasswd, AES_KEY_LEN);
- gen_key((char*)mpasswd, master_key, USER_KEY_LEN);
- if ((ret = store_master_key(upasswd, master_key)) == 0) {
- unlock_keystore(master_key);
- }
- memset(master_key, 0, USER_KEY_LEN);
- memset(mpasswd, 0, AES_KEY_LEN);
-
- return ret;
-}
-
-static int change_passwd(char *data)
-{
- unsigned char master_key[USER_KEY_LEN];
- char *old_pass, *new_pass = NULL, *p, *delimiter=" ";
- int ret, count = 0;
- char *context = NULL;
-
- old_pass = p = strtok_r(data, delimiter, &context);
- while (p != NULL) {
- count++;
- new_pass = p;
- p = strtok_r(NULL, delimiter, &context);
- }
- if (count != 2) return -1;
- if (strlen(new_pass) < MIN_PASSWD_LENGTH) return -1;
- if ((ret = get_master_key(old_pass, master_key)) == 0) {
- ret = store_master_key(new_pass, master_key);
- retry_count = 0;
- } else {
- ret = MAX_RETRY_COUNT - ++retry_count;
- if (ret == 0) {
- retry_count = 0;
- LOGE("passwd:reach max retry count, reset the keystore now.");
- reset_keystore();
- return -1;
- }
-
- }
- return ret;
-}
-
-int remove_key(const char *namespace, const char *keyname)
-{
- char keyfile[KEYFILE_LEN];
-
- if (state != UNLOCKED) return -state;
- if ((strlen(namespace) >= MAX_KEY_NAME_LENGTH) ||
- (strlen(keyname) >= MAX_KEY_NAME_LENGTH)) {
- LOGE("keyname is too long.");
- return -1;
- }
- sprintf(keyfile, KEYFILE_NAME, namespace, keyname);
- return unlink(keyfile);
-}
-
-int put_key(const char *namespace, const char *keyname,
- unsigned char *data, int size)
-{
- DATA_BLOB blob;
- uint32_t real_size;
- char keyfile[KEYFILE_LEN];
-
- if (state != UNLOCKED) {
- LOGE("Can not store key with current state %d\n", state);
- return -state;
- }
- if ((strlen(namespace) >= MAX_KEY_NAME_LENGTH) ||
- (strlen(keyname) >= MAX_KEY_NAME_LENGTH)) {
- LOGE("keyname is too long.");
- return -1;
- }
- sprintf(keyfile, KEYFILE_NAME, namespace, keyname);
- strcpy(blob.keyname, keyname);
- blob.value_size = size;
- if (size > MAX_KEY_VALUE_LENGTH) {
- LOGE("the data size is too large.");
- return -1;
- }
- memcpy(blob.value, data, size);
- return encrypt_n_save(&encryptKey, &blob, keyfile);
-}
-
-int get_key(const char *namespace, const char *keyname,
- unsigned char *data, int *size)
-{
- int ret;
- DATA_BLOB blob;
- uint32_t blob_size;
- char keyfile[KEYFILE_LEN];
-
- if (state != UNLOCKED) {
- LOGE("Can not retrieve key value with current state %d\n", state);
- return -state;
- }
- if ((strlen(namespace) >= MAX_KEY_NAME_LENGTH) ||
- (strlen(keyname) >= MAX_KEY_NAME_LENGTH)) {
- LOGE("keyname is too long.");
- return -1;
- }
- sprintf(keyfile, KEYFILE_NAME, namespace, keyname);
- ret = load_n_decrypt(keyname, keyfile, &decryptKey, &blob);
- if (!ret) {
- if ((blob.value_size > MAX_KEY_VALUE_LENGTH)) {
- LOGE("blob value size is too large.");
- ret = -1;
- } else {
- *size = blob.value_size;
- memcpy(data, blob.value, *size);
- }
- }
- return ret;
-}
-
-int list_keys(const char *namespace, char reply[BUFFER_MAX])
-{
- DIR *d;
- struct dirent *de;
-
- if (state != UNLOCKED) {
- LOGE("Can not list key with current state %d\n", state);
- return -1;
- }
-
- if (!namespace || ((d = opendir("."))) == NULL) {
- LOGE("cannot open keystore dir or namespace is null\n");
- return -1;
- }
-
- if (strlen(namespace) >= MAX_KEY_NAME_LENGTH) {
- LOGE("namespace is too long.");
- return -1;
- }
-
- reply[0] = 0;
- while ((de = readdir(d))) {
- char *prefix, *name, *keyfile = de->d_name;
- char *context = NULL;
-
- if (de->d_type != DT_REG) continue;
- if ((prefix = strtok_r(keyfile, NAME_DELIMITER, &context))
- == NULL) continue;
- if (strcmp(prefix, namespace)) continue;
- if ((name = strtok_r(NULL, NAME_DELIMITER, &context)) == NULL) continue;
- // append the key name into reply
- if (reply[0] != 0) strlcat(reply, " ", BUFFER_MAX);
- if (strlcat(reply, name, BUFFER_MAX) >= BUFFER_MAX) {
- LOGE("too many files under keystore directory\n");
- return -1;
- }
- }
- closedir(d);
- return 0;
-}
-
-int passwd(char *data)
-{
- if (state == UNINITIALIZED) {
- if (strchr(data, ' ')) return -1;
- if (strlen(data) < MIN_PASSWD_LENGTH) return -1;
- return create_master_key(data);
- }
- return change_passwd(data);
-}
-
-int lock()
-{
- switch(state) {
- case UNLOCKED:
- lock_keystore();
- case LOCKED:
- return 0;
- default:
- return -1;
- }
-}
-
-int unlock(char *passwd)
-{
- unsigned char master_key[USER_KEY_LEN];
- int ret = get_master_key(passwd, master_key);
- if (!ret) {
- unlock_keystore(master_key);
- retry_count = 0;
- } else {
- ret = MAX_RETRY_COUNT - ++retry_count;
- if (ret == 0) {
- retry_count = 0;
- LOGE("unlock:reach max retry count, reset the keystore now.");
- reset_keystore();
- return -1;
- }
- }
- return ret;
-}
-
-KEYSTORE_STATE get_state()
-{
- return state;
-}
-
-int reset_keystore()
-{
- int ret = 0;
- DIR *d;
- struct dirent *de;
-
- if ((d = opendir(".")) == NULL) {
- LOGE("cannot open keystore dir\n");
- return -1;
- }
- while ((de = readdir(d))) {
- if (unlink(de->d_name) != 0) ret = -1;
- }
- closedir(d);
- state = UNINITIALIZED;
- if (ret == 0) {
- LOGI("keystore is reset.");
- } else {
- LOGI("keystore can not be cleaned up entirely.");
- }
- return ret;
-}
-
-int init_keystore(const char *dir)
-{
- int fd;
-
- if (dir) mkdir(dir, 0770);
- if (!dir || chdir(dir)) {
- LOGE("Can not open/create the keystore directory %s\n",
- dir ? dir : "(null)");
- return -1;
- }
- gen_random_blob(iv, IV_LEN);
- if ((fd = open(MASTER_KEY, O_RDONLY)) == -1) {
- state = UNINITIALIZED;
- return 0;
- }
- close(fd);
- state = LOCKED;
- return 0;
-}
diff --git a/cmds/keystore/keymgmt.h b/cmds/keystore/keymgmt.h
deleted file mode 100644
index 0e928db494fd..000000000000
--- a/cmds/keystore/keymgmt.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifndef __KEYMGMT_H__
-#define __KEYMGMT_H__
-
-#define MASTER_KEY_TAG "master_key"
-#define MASTER_KEY ".keymaster"
-#define MAX_PATH_LEN 128
-#define SALT "Android Keystore 0.1"
-#define NAME_DELIMITER "_"
-#define KEYFILE_NAME "%s"NAME_DELIMITER"%s"
-#define KEYGEN_ITER 1024
-#define AES_KEY_LEN 128
-#define USER_KEY_LEN (AES_KEY_LEN/8)
-#define IV_LEN USER_KEY_LEN
-#define MAX_RETRY_COUNT 6
-#define MIN_PASSWD_LENGTH 8
-
-#define gen_key(passwd, key, len) \
- PKCS5_PBKDF2_HMAC_SHA1(passwd, strlen(passwd), \
- (unsigned char*)SALT, \
- strlen(SALT), KEYGEN_ITER, \
- len, key)
-
-#define KEYFILE_LEN MAX_NAMESPACE_LENGTH + MAX_KEY_NAME_LENGTH + 6
-
-#define get_blob_size(blob) \
- (((blob->value_size + sizeof(uint32_t) + MAX_KEY_NAME_LENGTH \
- + USER_KEY_LEN - 1) / USER_KEY_LEN) * USER_KEY_LEN)
-
-#define MAX_BLOB_LEN ((MAX_KEY_VALUE_LENGTH + MAX_KEY_NAME_LENGTH + \
- sizeof(uint32_t) + USER_KEY_LEN - 1) / USER_KEY_LEN)\
- * USER_KEY_LEN
-
-#define data_blob_size(blob) USER_KEY_LEN + sizeof(uint32_t) + blob->blob_size
-
-typedef struct {
- unsigned char iv[USER_KEY_LEN];
- uint32_t blob_size;
- union {
- unsigned char blob[1];
- struct {
- uint32_t value_size;
- char keyname[MAX_KEY_NAME_LENGTH];
- unsigned char value[MAX_KEY_VALUE_LENGTH];
- } __attribute__((packed));
- };
-} DATA_BLOB;
-
-typedef struct {
- char tag[USER_KEY_LEN];
- unsigned char master_key[USER_KEY_LEN];
-} MASTER_BLOB;
-
-int put_key(const char *namespace, const char *keyname,
- unsigned char *data, int size);
-int get_key(const char *namespace, const char *keyname,
- unsigned char *data, int *size);
-int remove_key(const char *namespace, const char *keyname);
-int list_keys(const char *namespace, char reply[BUFFER_MAX]);
-int passwd(char *data);
-int lock();
-int unlock(char *passwd);
-KEYSTORE_STATE get_state();
-int reset_keystore();
-int init_keystore(const char *dir);
-
-#endif
diff --git a/cmds/keystore/keystore.c b/cmds/keystore/keystore.c
new file mode 100644
index 000000000000..ba74c7814e81
--- /dev/null
+++ b/cmds/keystore/keystore.c
@@ -0,0 +1,542 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <arpa/inet.h>
+
+#include <openssl/aes.h>
+#include <openssl/evp.h>
+#include <openssl/md5.h>
+
+#define LOG_TAG "keystore"
+#include <cutils/log.h>
+#include <cutils/sockets.h>
+#include <private/android_filesystem_config.h>
+
+#include "keystore.h"
+
+/* KeyStore is a secured storage for key-value pairs. In this implementation,
+ * each file stores one key-value pair. Keys are encoded in file names, and
+ * values are encrypted with checksums. The encryption key is protected by a
+ * user-defined password. To keep things simple, buffers are always larger than
+ * the maximum space we needed, so boundary checks on buffers are omitted. */
+
+#define KEY_SIZE 120
+#define VALUE_SIZE 32768
+#define PASSWORD_SIZE VALUE_SIZE
+
+/* Here is the encoding of keys. This is necessary in order to allow arbitrary
+ * characters in keys. Characters in [0-~] are not encoded. Others are encoded
+ * into two bytes. The first byte is one of [+-.] which represents the first
+ * two bits of the character. The second byte encodes the rest of the bits into
+ * [0-o]. Therefore in the worst case the length of a key gets doubled. Note
+ * that Base64 cannot be used here due to the need of prefix match on keys. */
+
+static int encode_key(char *out, uint8_t *in, int length)
+{
+ int i;
+ for (i = length; i > 0; --i, ++in, ++out) {
+ if (*in >= '0' && *in <= '~') {
+ *out = *in;
+ } else {
+ *out = '+' + (*in >> 6);
+ *++out = '0' + (*in & 0x3F);
+ ++length;
+ }
+ }
+ *out = 0;
+ return length;
+}
+
+static int decode_key(uint8_t *out, char *in, int length)
+{
+ int i;
+ for (i = 0; i < length; ++i, ++in, ++out) {
+ if (*in >= '0' && *in <= '~') {
+ *out = *in;
+ } else {
+ *out = (*in - '+') << 6;
+ *out |= (*++in - '0') & 0x3F;
+ --length;
+ }
+ }
+ *out = 0;
+ return length;
+}
+
+/* Here is the protocol used in both requests and responses:
+ * code [length_1 message_1 ... length_n message_n] end-of-file
+ * where code is one byte long and lengths are unsigned 16-bit integers in
+ * network order. Thus the maximum length of a message is 65535 bytes. */
+
+static int the_socket = -1;
+
+static int recv_code(int8_t *code)
+{
+ return recv(the_socket, code, 1, 0) == 1;
+}
+
+static int recv_message(uint8_t *message, int length)
+{
+ uint8_t bytes[2];
+ if (recv(the_socket, &bytes[0], 1, 0) != 1 ||
+ recv(the_socket, &bytes[1], 1, 0) != 1) {
+ return -1;
+ } else {
+ int offset = bytes[0] << 8 | bytes[1];
+ if (length < offset) {
+ return -1;
+ }
+ length = offset;
+ offset = 0;
+ while (offset < length) {
+ int n = recv(the_socket, &message[offset], length - offset, 0);
+ if (n <= 0) {
+ return -1;
+ }
+ offset += n;
+ }
+ }
+ return length;
+}
+
+static int recv_end_of_file()
+{
+ uint8_t byte;
+ return recv(the_socket, &byte, 1, 0) == 0;
+}
+
+static void send_code(int8_t code)
+{
+ send(the_socket, &code, 1, 0);
+}
+
+static void send_message(uint8_t *message, int length)
+{
+ uint16_t bytes = htons(length);
+ send(the_socket, &bytes, 2, 0);
+ send(the_socket, message, length, 0);
+}
+
+/* Here is the file format. Values are encrypted by AES CBC, and MD5 is used to
+ * compute their checksums. To make the files portable, the length is stored in
+ * network order. Note that the first four bytes are reserved for future use and
+ * are always set to zero in this implementation. */
+
+static int the_entropy = -1;
+
+static struct __attribute__((packed)) {
+ uint32_t reserved;
+ uint8_t vector[AES_BLOCK_SIZE];
+ uint8_t encrypted[0];
+ uint8_t digest[MD5_DIGEST_LENGTH];
+ uint8_t digested[0];
+ int32_t length;
+ uint8_t value[VALUE_SIZE + AES_BLOCK_SIZE];
+} blob;
+
+static int8_t encrypt_blob(char *name, AES_KEY *aes_key)
+{
+ uint8_t vector[AES_BLOCK_SIZE];
+ int length = blob.length;
+ int fd;
+
+ if (read(the_entropy, vector, AES_BLOCK_SIZE) != AES_BLOCK_SIZE) {
+ return SYSTEM_ERROR;
+ }
+
+ length += blob.value - blob.digested;
+ blob.length = htonl(blob.length);
+ MD5(blob.digested, length, blob.digest);
+
+ length += blob.digested - blob.encrypted;
+ length = (length + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE * AES_BLOCK_SIZE;
+ memcpy(vector, blob.vector, AES_BLOCK_SIZE);
+ AES_cbc_encrypt(blob.encrypted, blob.encrypted, length, aes_key, vector,
+ AES_ENCRYPT);
+
+ blob.reserved = 0;
+ length += blob.encrypted - (uint8_t *)&blob;
+
+ fd = open(".tmp", O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
+ if (fd == -1 || write(fd, &blob, length) != length) {
+ return SYSTEM_ERROR;
+ }
+ close(fd);
+ return rename(".tmp", name) ? SYSTEM_ERROR : NO_ERROR;
+}
+
+static int8_t decrypt_blob(char *name, AES_KEY *aes_key)
+{
+ int fd = open(name, O_RDONLY);
+ int length;
+
+ if (fd == -1) {
+ return (errno == ENOENT) ? KEY_NOT_FOUND : SYSTEM_ERROR;
+ }
+ length = read(fd, &blob, sizeof(blob));
+ close(fd);
+
+ length -= blob.encrypted - (uint8_t *)&blob;
+ if (length < blob.value - blob.encrypted || length % AES_BLOCK_SIZE != 0) {
+ return VALUE_CORRUPTED;
+ }
+
+ AES_cbc_encrypt(blob.encrypted, blob.encrypted, length, aes_key,
+ blob.vector, AES_DECRYPT);
+ length -= blob.digested - blob.encrypted;
+ if (!memcmp(blob.digest, MD5(blob.digested, length, NULL),
+ MD5_DIGEST_LENGTH)) {
+ return VALUE_CORRUPTED;
+ }
+
+ length -= blob.value - blob.digested;
+ blob.length = ntohl(blob.length);
+ return (length < blob.length) ? VALUE_CORRUPTED : NO_ERROR;
+}
+
+/* Here are the actions. Each of them is a function without arguments. All
+ * information is defined in global variables, which are set properly before
+ * performing an action. The number of parameters required by each action is
+ * fixed and defined in a table. If the return value of an action is positive,
+ * it will be treated as a response code and transmitted to the client. Note
+ * that the lengths of parameters are checked when they are received, so
+ * boundary checks on parameters are omitted. */
+
+#define MAX_PARAM 2
+#define MAX_RETRY 4
+
+static uid_t uid = -1;
+static int8_t state = UNINITIALIZED;
+static int8_t retry = MAX_RETRY;
+
+static struct {
+ int length;
+ uint8_t value[VALUE_SIZE];
+} params[MAX_PARAM];
+
+static AES_KEY encryption_key;
+static AES_KEY decryption_key;
+
+static int8_t test()
+{
+ return state;
+}
+
+static int8_t get()
+{
+ char name[NAME_MAX];
+ int n = sprintf(name, "%u_", uid);
+ encode_key(&name[n], params[0].value, params[0].length);
+ n = decrypt_blob(name, &decryption_key);
+ if (n != NO_ERROR) {
+ return n;
+ }
+ send_code(NO_ERROR);
+ send_message(blob.value, blob.length);
+ return -NO_ERROR;
+}
+
+static int8_t insert()
+{
+ char name[NAME_MAX];
+ int n = sprintf(name, "%u_", uid);
+ encode_key(&name[n], params[0].value, params[0].length);
+ blob.length = params[1].length;
+ memcpy(blob.value, params[1].value, params[1].length);
+ return encrypt_blob(name, &encryption_key);
+}
+
+static int8_t delete()
+{
+ char name[NAME_MAX];
+ int n = sprintf(name, "%u_", uid);
+ encode_key(&name[n], params[0].value, params[0].length);
+ return (unlink(name) && errno != ENOENT) ? SYSTEM_ERROR : NO_ERROR;
+}
+
+static int8_t exist()
+{
+ char name[NAME_MAX];
+ int n = sprintf(name, "%u_", uid);
+ encode_key(&name[n], params[0].value, params[0].length);
+ if (access(name, R_OK) == -1) {
+ return (errno != ENOENT) ? SYSTEM_ERROR : KEY_NOT_FOUND;
+ }
+ return NO_ERROR;
+}
+
+static int8_t saw()
+{
+ DIR *dir = opendir(".");
+ struct dirent *file;
+ char name[NAME_MAX];
+ int n;
+
+ if (!dir) {
+ return SYSTEM_ERROR;
+ }
+ n = sprintf(name, "%u_", uid);
+ n += encode_key(&name[n], params[0].value, params[0].length);
+ send_code(NO_ERROR);
+ while ((file = readdir(dir)) != NULL) {
+ if (!strncmp(name, file->d_name, n)) {
+ char *p = &file->d_name[n];
+ params[0].length = decode_key(params[0].value, p, strlen(p));
+ send_message(params[0].value, params[0].length);
+ }
+ }
+ closedir(dir);
+ return -NO_ERROR;
+}
+
+static int8_t reset()
+{
+ DIR *dir = opendir(".");
+ struct dirent *file;
+
+ memset(&encryption_key, 0, sizeof(encryption_key));
+ memset(&decryption_key, 0, sizeof(decryption_key));
+ state = UNINITIALIZED;
+ retry = MAX_RETRY;
+
+ if (!dir) {
+ return SYSTEM_ERROR;
+ }
+ while ((file = readdir(dir)) != NULL) {
+ unlink(file->d_name);
+ }
+ closedir(dir);
+ return NO_ERROR;
+}
+
+#define MASTER_KEY_FILE ".masterkey"
+#define MASTER_KEY_SIZE 16
+
+static void generate_key(uint8_t *key, uint8_t *password, int length)
+{
+ PKCS5_PBKDF2_HMAC_SHA1((char *)password, length, (uint8_t *)"keystore",
+ sizeof("keystore"), 1024, MASTER_KEY_SIZE, key);
+}
+
+static int8_t password()
+{
+ uint8_t key[MASTER_KEY_SIZE];
+ AES_KEY aes_key;
+ int n;
+
+ if (state == UNINITIALIZED) {
+ blob.length = MASTER_KEY_SIZE;
+ if (read(the_entropy, blob.value, MASTER_KEY_SIZE) != MASTER_KEY_SIZE) {
+ return SYSTEM_ERROR;
+ }
+ } else {
+ generate_key(key, params[0].value, params[0].length);
+ AES_set_decrypt_key(key, MASTER_KEY_SIZE * 8, &aes_key);
+ n = decrypt_blob(MASTER_KEY_FILE, &aes_key);
+ if (n == SYSTEM_ERROR) {
+ return SYSTEM_ERROR;
+ }
+ if (n != NO_ERROR || blob.length != MASTER_KEY_SIZE) {
+ if (retry <= 0) {
+ reset();
+ return UNINITIALIZED;
+ }
+ return WRONG_PASSWORD + --retry;
+ }
+ }
+
+ if (params[1].length == -1) {
+ memcpy(key, blob.value, MASTER_KEY_SIZE);
+ } else {
+ generate_key(key, params[1].value, params[1].length);
+ AES_set_encrypt_key(key, MASTER_KEY_SIZE * 8, &aes_key);
+ memcpy(key, blob.value, MASTER_KEY_SIZE);
+ n = encrypt_blob(MASTER_KEY_FILE, &aes_key);
+ }
+
+ if (n == NO_ERROR) {
+ AES_set_encrypt_key(key, MASTER_KEY_SIZE * 8, &encryption_key);
+ AES_set_decrypt_key(key, MASTER_KEY_SIZE * 8, &decryption_key);
+ state = NO_ERROR;
+ retry = MAX_RETRY;
+ }
+ return n;
+}
+
+static int8_t lock()
+{
+ memset(&encryption_key, 0, sizeof(encryption_key));
+ memset(&decryption_key, 0, sizeof(decryption_key));
+ state = LOCKED;
+ return NO_ERROR;
+}
+
+static int8_t unlock()
+{
+ params[1].length = -1;
+ return password();
+}
+
+/* Here are the permissions, actions, users, and the main function. */
+
+enum perm {
+ TEST = 1,
+ GET = 2,
+ INSERT = 4,
+ DELETE = 8,
+ EXIST = 16,
+ SAW = 32,
+ RESET = 64,
+ PASSWORD = 128,
+ LOCK = 256,
+ UNLOCK = 512,
+};
+
+static struct action {
+ int8_t (*run)();
+ int8_t code;
+ int8_t state;
+ uint32_t perm;
+ int lengths[MAX_PARAM];
+} actions[] = {
+ {test, 't', 0, TEST, {0}},
+ {get, 'g', NO_ERROR, GET, {KEY_SIZE}},
+ {insert, 'i', NO_ERROR, INSERT, {KEY_SIZE, VALUE_SIZE}},
+ {delete, 'd', 0, DELETE, {KEY_SIZE}},
+ {exist, 'e', 0, EXIST, {KEY_SIZE}},
+ {saw, 's', 0, SAW, {KEY_SIZE}},
+ {reset, 'r', 0, RESET, {0}},
+ {password, 'p', 0, PASSWORD, {PASSWORD_SIZE, PASSWORD_SIZE}},
+ {lock, 'l', NO_ERROR, LOCK, {0}},
+ {unlock, 'u', LOCKED, UNLOCK, {PASSWORD_SIZE}},
+ {NULL, 0 , 0, 0, {0}},
+};
+
+static struct user {
+ uid_t uid;
+ uid_t euid;
+ uint32_t perms;
+} users[] = {
+ {AID_SYSTEM, 0, ~GET},
+ {AID_VPN, AID_SYSTEM, GET},
+ {AID_WIFI, AID_SYSTEM, GET},
+ {0, 0, TEST | GET | INSERT | DELETE | EXIST | SAW},
+};
+
+static int8_t process(int8_t code) {
+ struct user *user = users;
+ struct action *action = actions;
+ int i;
+
+ while (user->uid && user->uid != uid) {
+ ++user;
+ }
+ while (action->code && action->code != code) {
+ ++action;
+ }
+ if (!action->code) {
+ return UNDEFINED_ACTION;
+ }
+ if (!(action->perm & user->perms)) {
+ return PERMISSION_DENIED;
+ }
+ if (action->state && action->state != state) {
+ return state;
+ }
+ if (user->euid) {
+ uid = user->euid;
+ }
+ for (i = 0; i < MAX_PARAM && action->lengths[i]; ++i) {
+ params[i].length = recv_message(params[i].value, action->lengths[i]);
+ if (params[i].length == -1) {
+ return PROTOCOL_ERROR;
+ }
+ }
+ if (!recv_end_of_file()) {
+ return PROTOCOL_ERROR;
+ }
+ return action->run();
+}
+
+#define RANDOM_DEVICE "/dev/urandom"
+
+int main(int argc, char **argv)
+{
+ int control_socket = android_get_control_socket("keystore");
+ if (argc < 2) {
+ LOGE("A directory must be specified!");
+ return 1;
+ }
+ if (chdir(argv[1]) == -1) {
+ LOGE("chdir: %s: %s", argv[1], strerror(errno));
+ return 1;
+ }
+ if ((the_entropy = open(RANDOM_DEVICE, O_RDONLY)) == -1) {
+ LOGE("open: %s: %s", RANDOM_DEVICE, strerror(errno));
+ return 1;
+ }
+ if (listen(control_socket, 3) == -1) {
+ LOGE("listen: %s", strerror(errno));
+ return 1;
+ }
+
+ signal(SIGPIPE, SIG_IGN);
+ if (access(MASTER_KEY_FILE, R_OK) == 0) {
+ state = LOCKED;
+ }
+
+ while ((the_socket = accept(control_socket, NULL, 0)) != -1) {
+ struct timeval tv = {.tv_sec = 3};
+ struct ucred cred;
+ socklen_t size = sizeof(cred);
+ int8_t request;
+
+ setsockopt(the_socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
+ setsockopt(the_socket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
+
+ if (getsockopt(the_socket, SOL_SOCKET, SO_PEERCRED, &cred, &size)) {
+ LOGW("getsockopt: %s", strerror(errno));
+ } else if (recv_code(&request)) {
+ int8_t old_state = state;
+ int8_t response;
+ uid = cred.uid;
+
+ if ((response = process(request)) > 0) {
+ send_code(response);
+ response = -response;
+ }
+
+ LOGI("uid: %d action: %c -> %d state: %d -> %d retry: %d",
+ cred.uid, request, -response, old_state, state, retry);
+ }
+ close(the_socket);
+ }
+ LOGE("accept: %s", strerror(errno));
+ return 1;
+}
diff --git a/cmds/keystore/keystore.h b/cmds/keystore/keystore.h
new file mode 100644
index 000000000000..5ef51e9cd7d0
--- /dev/null
+++ b/cmds/keystore/keystore.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __KEYSTORE_H__
+#define __KEYSTORE_H__
+
+enum response_code {
+ NO_ERROR = 1,
+ LOCKED = 2,
+ UNINITIALIZED = 3,
+ SYSTEM_ERROR = 4,
+ PROTOCOL_ERROR = 5,
+ PERMISSION_DENIED = 6,
+ KEY_NOT_FOUND = 7,
+ VALUE_CORRUPTED = 8,
+ UNDEFINED_ACTION = 9,
+ WRONG_PASSWORD = 10,
+};
+
+#endif
diff --git a/cmds/keystore/keystore_cli.c b/cmds/keystore/keystore_cli.c
new file mode 100644
index 000000000000..e8afb5a945b2
--- /dev/null
+++ b/cmds/keystore/keystore_cli.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <cutils/sockets.h>
+
+#include "keystore.h"
+
+char *responses[256] = {
+ [NO_ERROR] = "No error",
+ [LOCKED] = "Locked",
+ [UNINITIALIZED] = "Uninitialized",
+ [SYSTEM_ERROR] = "System error",
+ [PROTOCOL_ERROR] = "Protocol error",
+ [PERMISSION_DENIED] = "Permission denied",
+ [KEY_NOT_FOUND] = "Key not found",
+ [VALUE_CORRUPTED] = "Value corrupted",
+ [UNDEFINED_ACTION] = "Undefined action",
+ [WRONG_PASSWORD] = "Wrong password (last chance)",
+ [WRONG_PASSWORD + 1] = "Wrong password (2 tries left)",
+ [WRONG_PASSWORD + 2] = "Wrong password (3 tries left)",
+ [WRONG_PASSWORD + 3] = "Wrong password (4 tries left)",
+};
+
+#define MAX_RESPONSE (WRONG_PASSWORD + 3)
+
+int main(int argc, char **argv)
+{
+ uint8_t bytes[65536];
+ uint8_t code;
+ int sock, i;
+
+ if (argc < 2) {
+ printf("Usage: %s action [parameter ...]\n", argv[0]);
+ return 0;
+ }
+
+ sock = socket_local_client("keystore", ANDROID_SOCKET_NAMESPACE_RESERVED,
+ SOCK_STREAM);
+ if (sock == -1) {
+ puts("Failed to connect");
+ return 1;
+ }
+
+ send(sock, argv[1], 1, 0);
+ for (i = 2; i < argc; ++i) {
+ uint16_t length = strlen(argv[i]);
+ bytes[0] = length >> 8;
+ bytes[1] = length;
+ send(sock, &bytes, 2, 0);
+ send(sock, argv[i], length, 0);
+ }
+ shutdown(sock, SHUT_WR);
+
+ if (recv(sock, &code, 1, 0) != 1) {
+ puts("Failed to receive");
+ return 1;
+ }
+ printf("%d %s\n", code , responses[code] ? responses[code] : "Unknown");
+ while ((i = recv(sock, &bytes[0], 1, 0)) == 1) {
+ int length;
+ int offset;
+ if ((i = recv(sock, &bytes[1], 1, 0)) != 1) {
+ puts("Failed to receive");
+ return 1;
+ }
+ length = bytes[0] << 8 | bytes[1];
+ for (offset = 0; offset < length; offset += i) {
+ i = recv(sock, &bytes[offset], length - offset, 0);
+ if (i <= 0) {
+ puts("Failed to receive");
+ return 1;
+ }
+ }
+ fwrite(bytes, 1, length, stdout);
+ puts("");
+ }
+ return 0;
+}
diff --git a/cmds/keystore/keystore_get.h b/cmds/keystore/keystore_get.h
index 7665e81a314d..0e7e1aeabb0f 100644
--- a/cmds/keystore/keystore_get.h
+++ b/cmds/keystore/keystore_get.h
@@ -1,53 +1,69 @@
/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#ifndef __KEYSTORE_GET_H__
#define __KEYSTORE_GET_H__
#include <stdio.h>
-#include <stdlib.h>
+#include <stdint.h>
#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
-#include "certtool.h"
+#include <cutils/sockets.h>
-/* This function is provided to native components to get values from keystore.
- * Users are required to link against libcutils. If something goes wrong, NULL
- * is returned. Otherwise it returns the value in dynamically allocated memory
- * and sets the size if the pointer is not NULL. One can release the memory by
- * calling free(). */
-static char *keystore_get(const char *key, int *size)
+#define KEYSTORE_MESSAGE_SIZE 65535
+
+/* This function is provided for native components to get values from keystore.
+ * Users are required to link against libcutils. The lengths of keys and values
+ * are limited to KEYSTORE_MESSAGE_SIZE. This function returns the length of
+ * the requested value or -1 if something goes wrong. */
+static int keystore_get(const char *key, char *value)
{
- char buffer[MAX_KEY_VALUE_LENGTH];
- char *value;
- int length;
+ int length = strlen(key);
+ uint8_t bytes[2] = {length >> 8, length};
+ uint8_t code = 'g';
+ int sock;
- if (get_cert(key, (unsigned char *)buffer, &length) != 0) {
- return NULL;
+ if (length > KEYSTORE_MESSAGE_SIZE) {
+ return -1;
}
- value = malloc(length + 1);
- if (!value) {
- return NULL;
+ sock = socket_local_client("keystore", ANDROID_SOCKET_NAMESPACE_RESERVED,
+ SOCK_STREAM);
+ if (sock == -1) {
+ return -1;
}
- memcpy(value, buffer, length);
- value[length] = 0;
- if (size) {
- *size = length;
+ if (send(sock, &code, 1, 0) == 1 && send(sock, bytes, 2, 0) == 2 &&
+ send(sock, key, length, 0) == length && shutdown(sock, SHUT_WR) == 0 &&
+ recv(sock, &code, 1, 0) == 1 && code == /* NO_ERROR */ 1 &&
+ recv(sock, &bytes[0], 1, 0) == 1 && recv(sock, &bytes[1], 1, 0) == 1) {
+ int offset = 0;
+ length = bytes[0] << 8 | bytes[1];
+ while (offset < length) {
+ int n = recv(sock, &value[offset], length - offset, 0);
+ if (n <= 0) {
+ length = -1;
+ break;
+ }
+ offset += n;
+ }
}
- return value;
+ close(sock);
+ return length;
}
#endif
diff --git a/cmds/keystore/netkeystore.c b/cmds/keystore/netkeystore.c
deleted file mode 100644
index 637e0d87600d..000000000000
--- a/cmds/keystore/netkeystore.c
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define LOG_TAG "keystore"
-
-#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 <private/android_filesystem_config.h>
-
-#include <cutils/sockets.h>
-#include <cutils/log.h>
-#include <cutils/properties.h>
-
-#include "netkeystore.h"
-#include "keymgmt.h"
-
-#define DBG 1
-#define CMD_PUT_WITH_FILE "putfile"
-
-typedef void CMD_FUNC(LPC_MARSHAL *cmd, LPC_MARSHAL *reply);
-
-struct cmdinfo {
- const char *name;
- CMD_FUNC *func;
-};
-
-static CMD_FUNC do_lock;
-static CMD_FUNC do_unlock;
-static CMD_FUNC do_passwd;
-static CMD_FUNC do_get_state;;
-static CMD_FUNC do_listkeys;
-static CMD_FUNC do_get_key;
-static CMD_FUNC do_put_key;
-static CMD_FUNC do_remove_key;
-static CMD_FUNC do_reset_keystore;
-
-#define str(x) #x
-
-struct cmdinfo cmds[] = {
- { str(LOCK), do_lock },
- { str(UNLOCK), do_unlock },
- { str(PASSWD), do_passwd },
- { str(GETSTATE), do_get_state },
- { str(LISTKEYS), do_listkeys },
- { str(GET), do_get_key },
- { str(PUT), do_put_key },
- { str(REMOVE), do_remove_key },
- { str(RESET), do_reset_keystore },
-};
-
-static struct ucred cr;
-
-static int check_get_perm(int uid)
-{
- if (uid == AID_WIFI || uid == AID_VPN) return 0;
- return -1;
-}
-
-static int check_reset_perm(int uid)
-{
- if (uid == AID_SYSTEM) return 0;
- return -1;
-}
-
-static int parse_keyname(char *name, uint32_t len,
- char *namespace, char *keyname)
-{
- int count = 0;
- char *c = namespace, *p = namespace, *t = name;
-
- if (!name || !namespace || !keyname) return -1;
- while (t < name + len && (*t != 0)) {
- if (*t == ' ') {
- if (c == keyname) return -1;
- *p = count = 0;
- c = p = keyname;
- t++;
- } else {
- if (!isalnum(*t)) return -1;
- *p++ = *t++;
- // also check if the keyname/namespace is too long.
- if (count++ == MAX_KEY_NAME_LENGTH) return -1;
- }
- }
- *p = 0;
- return 0;
-}
-
-// args of passwd():
-// firstPassword - for the first time
-// oldPassword newPassword - for changing the password
-static void do_passwd(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
-{
- reply->retcode = passwd((char*)cmd->data);
-}
-
-// args of lock():
-// no argument
-static void do_lock(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
-{
- reply->retcode = lock();
-}
-
-// args of unlock():
-// password
-static void do_unlock(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
-{
- reply->retcode = unlock((char*)cmd->data);
-}
-
-// args of get_state():
-// no argument
-static void do_get_state(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
-{
- reply->retcode = get_state();
-}
-
-// args of listkeys():
-// namespace
-static void do_listkeys(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
-{
- reply->retcode = list_keys((const char*)cmd->data, (char*)reply->data);
- if (!reply->retcode) reply->len = strlen((char*)reply->data);
-}
-
-// args of get():
-// namespace keyname
-static void do_get_key(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
-{
- char namespace[MAX_KEY_NAME_LENGTH];
- char keyname[MAX_KEY_NAME_LENGTH];
-
- if (check_get_perm(cr.uid)) {
- LOGE("uid %d doesn't have the permission to get key value\n", cr.uid);
- reply->retcode = -1;
- return;
- }
-
- if (parse_keyname((char*)cmd->data, cmd->len, namespace, keyname)) {
- reply->retcode = -1;
- } else {
- reply->retcode = get_key(namespace, keyname, reply->data,
- (int*)&reply->len);
- }
-}
-
-static int get_value_index(LPC_MARSHAL *cmd)
-{
- uint32_t count = 0, i;
- for (i = 0 ; i < cmd->len ; ++i) {
- if (cmd->data[i] == ' ') {
- if (++count == 2) return ++i;
- }
- }
- return -1;
-}
-
-// args of put():
-// namespace keyname keyvalue
-static void do_put_key(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
-{
- char namespace[MAX_KEY_NAME_LENGTH];
- char keyname[MAX_KEY_NAME_LENGTH];
-
- int p = get_value_index(cmd);
- if (p == -1) {
- reply->retcode = -1;
- } else {
- unsigned char *value;
- if (parse_keyname((char*)cmd->data, p - 1, namespace, keyname)) {
- reply->retcode = -1;
- return;
- }
- value = &cmd->data[p];
- int len = cmd->len - p;
- reply->retcode = put_key(namespace, keyname, value, len);
- }
-}
-
-// args of remove_key():
-// namespace keyname
-static void do_remove_key(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
-{
- char namespace[MAX_KEY_NAME_LENGTH];
- char keyname[MAX_KEY_NAME_LENGTH];
- if (parse_keyname((char*)cmd->data, cmd->len, namespace, keyname)) {
- reply->retcode = -1;
- return;
- }
- reply->retcode = remove_key(namespace, keyname);
-}
-
-// args of reset_keystore():
-// no argument
-static void do_reset_keystore(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
-{
- if (check_reset_perm(cr.uid)) {
- LOGE("uid %d doesn't have the permission to reset the keystore\n",
- cr.uid);
- reply->retcode = -1;
- return;
- }
- reply->retcode = reset_keystore();
-}
-
-static void execute(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
-{
- uint32_t cmd_max = sizeof(cmds)/sizeof(struct cmdinfo);
-
- if (cmd->opcode >= cmd_max) {
- LOGE("the opcode (%d) is not valid", cmd->opcode);
- reply->retcode = -1;
- return;
- }
- cmds[cmd->opcode].func(cmd, reply);
-}
-
-static int set_read_timeout(int socket)
-{
- struct timeval tv;
- tv.tv_sec = READ_TIMEOUT;
- if (setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof tv))
- {
- LOGE("setsockopt failed");
- return -1;
- }
- return 0;
-}
-
-static int append_input_from_file(const char *filename, LPC_MARSHAL *cmd)
-{
- int fd, len, ret = 0;
-
- // get opcode of the function put()
- if ((fd = open(filename, O_RDONLY)) == -1) {
- fprintf(stderr, "Can not open file %s\n", filename);
- return -1;
- }
- cmd->data[cmd->len] = ' ';
- cmd->len++;
- len = read(fd, cmd->data + cmd->len, BUFFER_MAX - cmd->len);
- if (len < 0 || (len == (int)(BUFFER_MAX - cmd->len))) {
- ret = -1;
- } else {
- cmd->len += len;
- }
- close(fd);
- return ret;
-}
-
-static int flatten_str_args(int argc, const char **argv, LPC_MARSHAL *cmd)
-{
- int i, len = 0;
- char *buf = (char*)cmd->data;
- buf[0] = 0;
- for (i = 0 ; i < argc ; ++i) {
- if (i == 0) {
- len = strlcpy(buf, argv[i], BUFFER_MAX);
- } else {
- len += snprintf(buf + len, BUFFER_MAX - len, " %s", argv[i]);
- }
- if (len >= BUFFER_MAX) return -1;
- }
- if (len) cmd->len = len;
- return 0;
-}
-
-static int parse_cmd(int argc, const char **argv, LPC_MARSHAL *cmd)
-{
- uint32_t i, len = 0;
- uint32_t cmd_max = sizeof(cmds)/sizeof(cmds[0]);
-
- for (i = 0 ; i < cmd_max ; ++i) {
- if (!strcasecmp(argv[0], cmds[i].name)) break;
- }
-
- if (i == cmd_max) {
- // check if this is a command to put the key value with a file.
- if (strcmp(argv[0], CMD_PUT_WITH_FILE) != 0) return -1;
- cmd->opcode = PUT;
- if (argc != 4) {
- fprintf(stderr, "%s args\n\tnamespace keyname filename\n",
- argv[0]);
- return -1;
- }
- if (flatten_str_args(argc - 2, argv + 1, cmd)) return -1;
- return append_input_from_file(argv[3], cmd);
- } else {
- cmd->opcode = i;
- return flatten_str_args(argc - 1, argv + 1, cmd);
- }
-}
-
-static int shell_command(const int argc, const char **argv)
-{
- int fd, i;
- LPC_MARSHAL cmd;
-
- if (parse_cmd(argc, argv , &cmd)) {
- fprintf(stderr, "Incorrect command or command line is too long.\n");
- exit(1);
- }
- fd = socket_local_client(SOCKET_PATH,
- ANDROID_SOCKET_NAMESPACE_RESERVED,
- SOCK_STREAM);
- if (fd == -1) {
- fprintf(stderr, "Keystore service is not up and running.\n");
- exit(1);
- }
-
- if (write_marshal(fd, &cmd)) {
- fprintf(stderr, "Incorrect command or command line is too long.\n");
- exit(1);
- }
- if (read_marshal(fd, &cmd)) {
- fprintf(stderr, "Failed to read the result.\n");
- exit(1);
- }
- cmd.data[cmd.len] = 0;
- fprintf(stdout, "%s\n", (cmd.retcode == 0) ? "Succeeded!" : "Failed!");
- if (cmd.len) fprintf(stdout, "\t%s\n", (char*)cmd.data);
- close(fd);
- return 0;
-}
-
-int main(const int argc, const char *argv[])
-{
- struct sockaddr addr;
- socklen_t alen;
- int lsocket, s;
- LPC_MARSHAL cmd, reply;
-
- if (argc > 1) {
- return shell_command(argc - 1, argv + 1);
- }
-
- if (init_keystore(KEYSTORE_DIR)) {
- LOGE("Can not initialize the keystore, the directory exist?\n");
- exit(1);
- }
-
- 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);
- memset(&reply, 0, sizeof(LPC_MARSHAL));
-
- for (;;) {
- socklen_t cr_size = sizeof(cr);
- alen = sizeof(addr);
- s = accept(lsocket, &addr, &alen);
-
- /* retrieve the caller info here */
- if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cr_size) < 0) {
- close(s);
- LOGE("Unable to recieve socket options\n");
- continue;
- }
-
- if (s < 0) {
- LOGE("Accept failed: %s\n", strerror(errno));
- continue;
- }
- fcntl(s, F_SETFD, FD_CLOEXEC);
- if (set_read_timeout(s)) {
- close(s);
- continue;
- }
-
- // read the command, execute and send the result back.
- if(read_marshal(s, &cmd)) goto err;
- if (DBG) LOGD("new connection\n");
- execute(&cmd, &reply);
- write_marshal(s, &reply);
-err:
- memset(&reply, 0, sizeof(LPC_MARSHAL));
- if (DBG) LOGD("closing connection\n");
- close(s);
- }
-
- return 0;
-}
diff --git a/cmds/keystore/netkeystore.h b/cmds/keystore/netkeystore.h
deleted file mode 100644
index a87a667e9123..000000000000
--- a/cmds/keystore/netkeystore.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifndef __NETKEYSTORE_H__
-#define __NETKEYSTORE_H__
-
-#include <stdio.h>
-#include <cutils/sockets.h>
-#include <cutils/log.h>
-
-#include "common.h"
-
-static inline 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 inline 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;
-}
-
-static inline int read_marshal(int s, LPC_MARSHAL *cmd)
-{
- if (readx(s, cmd, 2 * sizeof(uint32_t))) {
- LOGE("failed to read header\n");
- return -1;
- }
- if (cmd->len > BUFFER_MAX) {
- LOGE("invalid size %d\n", cmd->len);
- return -1;
- }
- if (readx(s, cmd->data, cmd->len)) {
- LOGE("failed to read data\n");
- return -1;
- }
- cmd->data[cmd->len] = 0;
- return 0;
-}
-
-static inline int write_marshal(int s, LPC_MARSHAL *cmd)
-{
- if (writex(s, cmd, 2 * sizeof(uint32_t))) {
- LOGE("failed to write marshal header\n");
- return -1;
- }
- if (writex(s, cmd->data, cmd->len)) {
- LOGE("failed to write marshal data\n");
- return -1;
- }
- return 0;
-}
-
-#endif
diff --git a/cmds/keystore/tests/Android.mk b/cmds/keystore/tests/Android.mk
deleted file mode 100644
index 33541cc79f19..000000000000
--- a/cmds/keystore/tests/Android.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright (C) 2009 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# define the KEYSTORE_TESTS environment variable to build the test programs
-ifdef KEYSTORE_TESTS
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= netkeystore_test.c ../keymgmt.c
-LOCAL_SHARED_LIBRARIES := libcutils libssl
-LOCAL_MODULE:= netkeystore_test
-LOCAL_MODULE_TAGS := optional
-LOCAL_C_INCLUDES := external/openssl/include \
- frameworks/base/cmds/keystore
-EXTRA_CFLAGS := -g -O0 -DGTEST_OS_LINUX -DGTEST_HAS_STD_STRING
-include $(BUILD_EXECUTABLE)
-
-endif #KEYSTORE_TESTS
diff --git a/cmds/keystore/tests/netkeystore_test.c b/cmds/keystore/tests/netkeystore_test.c
deleted file mode 100644
index e7e686bd4368..000000000000
--- a/cmds/keystore/tests/netkeystore_test.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "common.h"
-#include "keymgmt.h"
-
-typedef int FUNC_PTR();
-typedef struct {
- const char *name;
- FUNC_PTR *func;
-} TESTFUNC;
-
-#define FUNC_NAME(x) { #x, test_##x }
-#define FUNC_BODY(x) int test_##x()
-
-#define TEST_PASSWD "12345678"
-#define TEST_NPASSWD "11111111"
-#define TEST_DIR "/data/local/tmp/keystore"
-#define READONLY_DIR "/proc/keystore"
-#define TEST_NAMESPACE "test"
-#define TEST_KEYNAME "key"
-#define TEST_KEYNAME2 "key2"
-#define TEST_KEYVALUE "ANDROID"
-
-void setup()
-{
- if (init_keystore(TEST_DIR) != 0) {
- fprintf(stderr, "Can not create the test directory %s\n", TEST_DIR);
- exit(-1);
- }
-}
-
-void teardown()
-{
- reset_keystore();
- rmdir(TEST_DIR);
-}
-
-FUNC_BODY(init_keystore)
-{
- if (init_keystore(READONLY_DIR) == 0) return -1;
-
- return EXIT_SUCCESS;
-}
-
-FUNC_BODY(reset_keystore)
-{
- chdir("/procx");
- if (reset_keystore() == 0) return -1;
- chdir(TEST_DIR);
- return EXIT_SUCCESS;
-}
-
-FUNC_BODY(get_state)
-{
- if (get_state() != UNINITIALIZED) return -1;
- passwd(TEST_PASSWD);
- if (get_state() != UNLOCKED) return -1;
- lock();
- if (get_state() != LOCKED) return -1;
- reset_keystore();
- if (get_state() != UNINITIALIZED) return -1;
- return EXIT_SUCCESS;
-}
-
-FUNC_BODY(passwd)
-{
- char buf[512];
-
- if (passwd(" 23432dsfsdf") == 0) return -1;
- if (passwd("dsfsdf") == 0) return -1;
- passwd(TEST_PASSWD);
- lock();
- if (unlock("55555555") == 0) return -1;
- if (unlock(TEST_PASSWD) != 0) return -1;
-
- // change the password
- sprintf(buf, "%s %s", "klfdjdsklfjg", "abcdefghi");
- if (passwd(buf) == 0) return -1;
-
- sprintf(buf, "%s %s", TEST_PASSWD, TEST_NPASSWD);
- if (passwd(buf) != 0) return -1;
- lock();
-
- if (unlock(TEST_PASSWD) == 0) return -1;
- if (unlock(TEST_NPASSWD) != 0) return -1;
-
- return EXIT_SUCCESS;
-}
-
-FUNC_BODY(lock)
-{
- if (lock() == 0) return -1;
- passwd(TEST_PASSWD);
- if (lock() != 0) return -1;
- if (lock() != 0) return -1;
- return EXIT_SUCCESS;
-}
-
-FUNC_BODY(unlock)
-{
- int i = MAX_RETRY_COUNT;
- passwd(TEST_PASSWD);
- lock();
- while (i > 1) {
- if (unlock(TEST_NPASSWD) != --i) return -1;
- }
- if (unlock(TEST_NPASSWD) != -1) return -1;
- return EXIT_SUCCESS;
-}
-
-FUNC_BODY(put_key)
-{
- int i = 0;
- char keyname[512];
-
- if (put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
- strlen(TEST_KEYVALUE)) == 0) return -1;
- passwd(TEST_PASSWD);
- if (put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
- strlen(TEST_KEYVALUE)) != 0) return -1;
-
- for(i = 0; i < 500; i++) keyname[i] = 'K';
- keyname[i] = 0;
- if (put_key(TEST_NAMESPACE, keyname, (unsigned char *)TEST_KEYVALUE,
- strlen(TEST_KEYVALUE)) == 0) return -1;
- if (put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
- MAX_KEY_VALUE_LENGTH + 1) == 0) return -1;
- return EXIT_SUCCESS;
-}
-
-FUNC_BODY(get_key)
-{
- int size;
- unsigned char data[MAX_KEY_VALUE_LENGTH];
-
- if (get_key(TEST_NAMESPACE, TEST_KEYNAME, data, &size) == 0) return -1;
-
- passwd(TEST_PASSWD);
- put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
- strlen(TEST_KEYVALUE));
- if (get_key(TEST_NAMESPACE, TEST_KEYNAME, data, &size) != 0) return -1;
- if (memcmp(data, TEST_KEYVALUE, size) != 0) return -1;
-
- return EXIT_SUCCESS;
-}
-
-FUNC_BODY(remove_key)
-{
- if (remove_key(TEST_NAMESPACE, TEST_KEYNAME) == 0) return -1;
-
- passwd(TEST_PASSWD);
- if (remove_key(TEST_NAMESPACE, TEST_KEYNAME) == 0) return -1;
-
- put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
- strlen(TEST_KEYVALUE));
- if (remove_key(TEST_NAMESPACE, TEST_KEYNAME) != 0) return -1;
-
- return EXIT_SUCCESS;
-}
-
-FUNC_BODY(list_keys)
-{
- int i;
- char buf[128];
- char reply[BUFFER_MAX];
-
- for(i = 0; i < 100; i++) buf[i] = 'K';
- buf[i] = 0;
-
- if (list_keys(TEST_NAMESPACE, reply) == 0) return -1;
-
- passwd(TEST_PASSWD);
- if (list_keys(buf, reply) == 0) return -1;
-
- if (list_keys(TEST_NAMESPACE, reply) != 0) return -1;
- if (strcmp(reply, "") != 0) return -1;
-
- put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
- strlen(TEST_KEYVALUE));
- if (list_keys(TEST_NAMESPACE, reply) != 0) return -1;
- if (strcmp(reply, TEST_KEYNAME) != 0) return -1;
-
- put_key(TEST_NAMESPACE, TEST_KEYNAME2, (unsigned char *)TEST_KEYVALUE,
- strlen(TEST_KEYVALUE));
-
- if (list_keys(TEST_NAMESPACE, reply) != 0) return -1;
- sprintf(buf, "%s %s", TEST_KEYNAME2, TEST_KEYNAME);
- if (strcmp(reply, buf) != 0) return -1;
-
- return EXIT_SUCCESS;
-}
-
-TESTFUNC all_tests[] = {
- FUNC_NAME(init_keystore),
- FUNC_NAME(reset_keystore),
- FUNC_NAME(get_state),
- FUNC_NAME(passwd),
- FUNC_NAME(lock),
- FUNC_NAME(unlock),
- FUNC_NAME(put_key),
- FUNC_NAME(get_key),
- FUNC_NAME(remove_key),
- FUNC_NAME(list_keys),
-};
-
-int main(int argc, char **argv) {
- int i, ret;
- for (i = 0 ; i < (int)(sizeof(all_tests)/sizeof(TESTFUNC)) ; ++i) {
- setup();
- if ((ret = all_tests[i].func()) != EXIT_SUCCESS) {
- fprintf(stderr, "ERROR in function %s\n", all_tests[i].name);
- return ret;
- } else {
- fprintf(stderr, "function %s PASSED!\n", all_tests[i].name);
- }
- teardown();
- }
- return EXIT_SUCCESS;
-}
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index fd9e70884e68..79eb310bb0e5 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -18,6 +18,7 @@ package com.android.commands.pm;
import android.content.ComponentName;
import android.content.pm.ApplicationInfo;
+import android.content.pm.FeatureInfo;
import android.content.pm.IPackageDeleteObserver;
import android.content.pm.IPackageInstallObserver;
import android.content.pm.IPackageManager;
@@ -34,6 +35,8 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import java.io.File;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -42,21 +45,21 @@ 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 =
+
+ 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) {
@@ -73,37 +76,37 @@ public final class Pm {
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")) {
@@ -128,13 +131,14 @@ public final class Pm {
}
}
}
-
+
/**
* Execute the list sub-command.
- *
+ *
* pm list [package | packages]
* pm list permission-groups
* pm list permissions
+ * pm list features
* pm list instrumentation
*/
private void runList() {
@@ -150,6 +154,8 @@ public final class Pm {
runListPermissionGroups();
} else if ("permissions".equals(type)) {
runListPermissions();
+ } else if ("features".equals(type)) {
+ runListFeatures();
} else if ("instrumentation".equals(type)) {
runListInstrumentation();
} else {
@@ -157,7 +163,7 @@ public final class Pm {
showUsage();
}
}
-
+
/**
* Lists all the installed packages.
*/
@@ -182,10 +188,10 @@ public final class Pm {
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);
@@ -201,10 +207,48 @@ public final class Pm {
System.err.println(PM_NOT_RUNNING_ERR);
}
}
-
+
+ /**
+ * Lists all of the features supported by the current device.
+ *
+ * pm list features
+ */
+ private void runListFeatures() {
+ try {
+ List<FeatureInfo> list = new ArrayList<FeatureInfo>();
+ FeatureInfo[] rawList = mPm.getSystemAvailableFeatures();
+ for (int i=0; i<rawList.length; i++) {
+ list.add(rawList[i]);
+ }
+
+
+ // Sort by name
+ Collections.sort(list, new Comparator<FeatureInfo>() {
+ public int compare(FeatureInfo o1, FeatureInfo o2) {
+ if (o1.name == o2.name) return 0;
+ if (o1.name == null) return -1;
+ if (o2.name == null) return 1;
+ return o1.name.compareTo(o2.name);
+ }
+ });
+
+ int count = (list != null) ? list.size() : 0;
+ for (int p = 0; p < count; p++) {
+ FeatureInfo fi = list.get(p);
+ System.out.print("feature:");
+ if (fi.name != null) System.out.println(fi.name);
+ else System.out.println("reqGlEsVersion=0x"
+ + Integer.toHexString(fi.reqGlEsVersion));
+ }
+ } 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() {
@@ -260,14 +304,14 @@ public final class Pm {
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);
@@ -279,7 +323,7 @@ public final class Pm {
System.err.println(PM_NOT_RUNNING_ERR);
}
}
-
+
private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized) {
if (nonLocalized != null) {
return nonLocalized.toString();
@@ -290,7 +334,7 @@ public final class Pm {
}
return null;
}
-
+
/**
* Lists all the permissions in a group.
*/
@@ -321,7 +365,7 @@ public final class Pm {
return;
}
}
-
+
String grp = nextOption();
ArrayList<String> groupList = new ArrayList<String>();
if (groups) {
@@ -334,7 +378,7 @@ public final class Pm {
} else {
groupList.add(grp);
}
-
+
if (dangerousOnly) {
System.out.println("Dangerous Permissions:");
System.out.println("");
@@ -365,7 +409,7 @@ public final class Pm {
System.err.println(PM_NOT_RUNNING_ERR);
}
}
-
+
private void doListPermissions(ArrayList<String> groupList,
boolean groups, boolean labels, boolean summary,
int startProtectionLevel, int endProtectionLevel)
@@ -385,7 +429,7 @@ public final class Pm {
pgi.nonLocalizedLabel) + ": ");
} else {
System.out.print(pgi.name + ": ");
-
+
}
} else {
System.out.println((labels ? "+ " : "")
@@ -468,13 +512,13 @@ public final class Pm {
}
}
}
-
+
if (summary) {
System.out.println("");
}
}
}
-
+
private void runPath() {
String pkg = nextArg();
if (pkg == null) {
@@ -484,7 +528,7 @@ public final class Pm {
}
displayPackageFilePath(pkg);
}
-
+
class PackageInstallObserver extends IPackageInstallObserver.Stub {
boolean finished;
int result;
@@ -497,92 +541,40 @@ public final class Pm {
}
}
}
-
+
+ /**
+ * Converts a failure code into a string by using reflection to find a matching constant
+ * in PackageManager.
+ */
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_DEXOPT:
- s = "INSTALL_FAILED_DEXOPT";
- break;
- case PackageManager.INSTALL_FAILED_OLDER_SDK:
- s = "INSTALL_FAILED_OLDER_SDK";
- break;
- case PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER:
- s = "INSTALL_FAILED_CONFLICTING_PROVIDER";
- break;
- case PackageManager.INSTALL_FAILED_NEWER_SDK:
- s = "INSTALL_FAILED_NEWER_SDK";
- break;
- case PackageManager.INSTALL_FAILED_TEST_ONLY:
- s = "INSTALL_FAILED_TEST_ONLY";
- break;
- case PackageManager.INSTALL_FAILED_CPU_ABI_INCOMPATIBLE:
- s = "INSTALL_FAILED_CPU_ABI_INCOMPATIBLE";
- 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;
- default:
- s = Integer.toString(result);
- break;
- }
- return s;
+ Field[] fields = PackageManager.class.getFields();
+ for (Field f: fields) {
+ if (f.getType() == int.class) {
+ int modifiers = f.getModifiers();
+ // only look at public final static fields.
+ if (((modifiers & Modifier.FINAL) != 0) &&
+ ((modifiers & Modifier.PUBLIC) != 0) &&
+ ((modifiers & Modifier.STATIC) != 0)) {
+ String fieldName = f.getName();
+ if (fieldName.startsWith("INSTALL_FAILED_") ||
+ fieldName.startsWith("INSTALL_PARSE_FAILED_")) {
+ // get the int value and compare it to result.
+ try {
+ if (result == f.getInt(null)) {
+ return fieldName;
+ }
+ } catch (IllegalAccessException e) {
+ // this shouldn't happen since we only look for public static fields.
+ }
+ }
+ }
+ }
+ }
+
+ // couldn't find a matching constant? return the value
+ return Integer.toString(result);
}
-
+
private void runInstall() {
int installFlags = 0;
String installerPackageName = null;
@@ -621,7 +613,7 @@ public final class Pm {
try {
mPm.installPackage(Uri.fromFile(new File(apkFilePath)), obs, installFlags,
installerPackageName);
-
+
synchronized (obs) {
while (!obs.finished) {
try {
@@ -642,11 +634,11 @@ public final class Pm {
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;
@@ -655,7 +647,7 @@ public final class Pm {
}
}
}
-
+
private void runUninstall() {
int unInstallFlags = 0;
@@ -709,7 +701,7 @@ public final class Pm {
}
return "unknown";
}
-
+
private void runSetEnabledSetting(int state) {
String pkg = nextArg();
if (pkg == null) {
@@ -757,11 +749,11 @@ public final class Pm {
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();
@@ -775,7 +767,7 @@ public final class Pm {
return null;
}
}
-
+
private String nextOption() {
if (mNextArg >= mArgs.length) {
return null;
@@ -827,7 +819,8 @@ public final class Pm {
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 list instrumentation [-f] [TARGET-PACKAGE]");
+ System.err.println(" pm list features");
System.err.println(" pm path PACKAGE");
System.err.println(" pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] PATH");
System.err.println(" pm uninstall [-k] PACKAGE");
@@ -852,6 +845,8 @@ public final class Pm {
System.err.println("or only those that target a specified package. Options:");
System.err.println(" -f: see their associated file.");
System.err.println("");
+ System.err.println("The list features command prints all features of the system.");
+ 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. Options:");
diff --git a/cmds/runtime/Android.mk b/cmds/runtime/Android.mk
index 521eb2b2863e..6a72d1070850 100644
--- a/cmds/runtime/Android.mk
+++ b/cmds/runtime/Android.mk
@@ -10,6 +10,7 @@ LOCAL_SRC_FILES:= \
LOCAL_SHARED_LIBRARIES := \
libutils \
+ libbinder \
libandroid_runtime \
libcutils \
libui \
diff --git a/cmds/runtime/ServiceManager.cpp b/cmds/runtime/ServiceManager.cpp
index 758a95c07d56..b2bef07ff70e 100644
--- a/cmds/runtime/ServiceManager.cpp
+++ b/cmds/runtime/ServiceManager.cpp
@@ -9,9 +9,9 @@
#include <utils/Debug.h>
#include <utils/Log.h>
-#include <utils/Parcel.h>
+#include <binder/Parcel.h>
#include <utils/String8.h>
-#include <utils/ProcessState.h>
+#include <binder/ProcessState.h>
#include <private/utils/Static.h>
diff --git a/cmds/runtime/ServiceManager.h b/cmds/runtime/ServiceManager.h
index d09cec8ddad8..090ca6de648b 100644
--- a/cmds/runtime/ServiceManager.h
+++ b/cmds/runtime/ServiceManager.h
@@ -4,7 +4,7 @@
#ifndef ANDROID_SERVICE_MANAGER_H
#define ANDROID_SERVICE_MANAGER_H
-#include <utils/IServiceManager.h>
+#include <binder/IServiceManager.h>
#include <utils/KeyedVector.h>
#include <utils/threads.h>
diff --git a/cmds/runtime/main_runtime.cpp b/cmds/runtime/main_runtime.cpp
index 476f38a4d073..21e0e4d02662 100644
--- a/cmds/runtime/main_runtime.cpp
+++ b/cmds/runtime/main_runtime.cpp
@@ -7,9 +7,11 @@
#include "ServiceManager.h"
#include "SignalHandler.h"
-#include <utils.h>
-#include <utils/IPCThreadState.h>
-#include <utils/ProcessState.h>
+#include <utils/threads.h>
+#include <utils/Errors.h>
+
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
#include <utils/Log.h>
#include <cutils/zygote.h>
diff --git a/cmds/service/Android.mk b/cmds/service/Android.mk
index 8c5005c1fbb1..275bbb2e17be 100644
--- a/cmds/service/Android.mk
+++ b/cmds/service/Android.mk
@@ -4,8 +4,7 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
service.cpp
-LOCAL_SHARED_LIBRARIES := \
- libutils
+LOCAL_SHARED_LIBRARIES := libutils libbinder
ifeq ($(TARGET_OS),linux)
LOCAL_CFLAGS += -DXP_UNIX
diff --git a/cmds/service/service.cpp b/cmds/service/service.cpp
index 859a9bf9f93c..32db83ba1dcb 100644
--- a/cmds/service/service.cpp
+++ b/cmds/service/service.cpp
@@ -3,9 +3,9 @@
*
*/
-#include <utils/Parcel.h>
-#include <utils/ProcessState.h>
-#include <utils/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
#include <utils/TextOutput.h>
#include <getopt.h>
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
index e4aa8b51cf2a..f3a471394b6a 100644
--- a/cmds/servicemanager/service_manager.c
+++ b/cmds/servicemanager/service_manager.c
@@ -30,6 +30,7 @@ static struct {
{ AID_MEDIA, "media.audio_flinger" },
{ AID_MEDIA, "media.player" },
{ AID_MEDIA, "media.camera" },
+ { AID_MEDIA, "media.audio_policy" },
{ AID_RADIO, "radio.phone" },
{ AID_RADIO, "radio.sms" },
{ AID_RADIO, "radio.phonesubinfo" },
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
new file mode 100644
index 000000000000..5b5525240f02
--- /dev/null
+++ b/cmds/stagefright/Android.mk
@@ -0,0 +1,46 @@
+ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ stagefright.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libstagefright
+
+LOCAL_C_INCLUDES:= \
+ $(JNI_H_INCLUDE) \
+ frameworks/base/media/libstagefright \
+ $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include
+
+LOCAL_CFLAGS += -Wno-multichar
+
+LOCAL_MODULE:= stagefright
+
+include $(BUILD_EXECUTABLE)
+
+################################################################################
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ SineSource.cpp \
+ record.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libstagefright
+
+LOCAL_C_INCLUDES:= \
+ $(JNI_H_INCLUDE) \
+ frameworks/base/media/libstagefright \
+ $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include
+
+LOCAL_CFLAGS += -Wno-multichar
+
+LOCAL_MODULE:= record
+
+include $(BUILD_EXECUTABLE)
+
+endif
diff --git a/cmds/stagefright/SineSource.cpp b/cmds/stagefright/SineSource.cpp
new file mode 100644
index 000000000000..e5a6ccb6b32a
--- /dev/null
+++ b/cmds/stagefright/SineSource.cpp
@@ -0,0 +1,101 @@
+#include "SineSource.h"
+
+#include <math.h>
+
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+
+namespace android {
+
+SineSource::SineSource(int32_t sampleRate, int32_t numChannels)
+ : mStarted(false),
+ mSampleRate(sampleRate),
+ mNumChannels(numChannels),
+ mPhase(0),
+ mGroup(NULL) {
+ CHECK(numChannels == 1 || numChannels == 2);
+}
+
+SineSource::~SineSource() {
+ if (mStarted) {
+ stop();
+ }
+}
+
+status_t SineSource::start(MetaData *params) {
+ CHECK(!mStarted);
+
+ mGroup = new MediaBufferGroup;
+ mGroup->add_buffer(new MediaBuffer(kBufferSize));
+
+ mPhase = 0;
+ mStarted = true;
+
+ return OK;
+}
+
+status_t SineSource::stop() {
+ CHECK(mStarted);
+
+ delete mGroup;
+ mGroup = NULL;
+
+ mStarted = false;
+
+ return OK;
+}
+
+sp<MetaData> SineSource::getFormat() {
+ sp<MetaData> meta = new MetaData;
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
+ meta->setInt32(kKeyChannelCount, mNumChannels);
+ meta->setInt32(kKeySampleRate, mSampleRate);
+
+ return meta;
+}
+
+status_t SineSource::read(
+ MediaBuffer **out, const ReadOptions *options) {
+ *out = NULL;
+
+ MediaBuffer *buffer;
+ status_t err = mGroup->acquire_buffer(&buffer);
+
+ if (err != OK) {
+ return err;
+ }
+
+ size_t frameSize = mNumChannels * sizeof(int16_t);
+ size_t numFramesPerBuffer = buffer->size() / frameSize;
+
+ int16_t *ptr = (int16_t *)buffer->data();
+
+ const double k = kFrequency / mSampleRate * (2.0 * M_PI);
+
+ double x = mPhase * k;
+ for (size_t i = 0; i < numFramesPerBuffer; ++i) {
+ int16_t amplitude = (int16_t)(32767.0 * sin(x));
+
+ *ptr++ = amplitude;
+ if (mNumChannels == 2) {
+ *ptr++ = amplitude;
+ }
+
+ x += k;
+ }
+
+ buffer->meta_data()->setInt32(kKeyTimeUnits, mPhase);
+ buffer->meta_data()->setInt32(kKeyTimeScale, mSampleRate);
+
+ mPhase += numFramesPerBuffer;
+
+ buffer->set_range(0, numFramesPerBuffer * frameSize);
+
+ *out = buffer;
+
+ return OK;
+}
+
+} // namespace android
diff --git a/cmds/stagefright/SineSource.h b/cmds/stagefright/SineSource.h
new file mode 100644
index 000000000000..76ab669fbfc6
--- /dev/null
+++ b/cmds/stagefright/SineSource.h
@@ -0,0 +1,39 @@
+#ifndef SINE_SOURCE_H_
+
+#define SINE_SOURCE_H_
+
+#include <media/stagefright/MediaSource.h>
+
+namespace android {
+
+struct MediaBufferGroup;
+
+struct SineSource : public MediaSource {
+ SineSource(int32_t sampleRate, int32_t numChannels);
+
+ virtual status_t start(MetaData *params);
+ virtual status_t stop();
+
+ virtual sp<MetaData> getFormat();
+
+ virtual status_t read(
+ MediaBuffer **out, const ReadOptions *options = NULL);
+
+protected:
+ virtual ~SineSource();
+
+private:
+ enum { kBufferSize = 8192 };
+ static const double kFrequency = 500.0;
+
+ bool mStarted;
+ int32_t mSampleRate;
+ int32_t mNumChannels;
+ size_t mPhase;
+
+ MediaBufferGroup *mGroup;
+};
+
+} // namespace android
+
+#endif // SINE_SOURCE_H_
diff --git a/cmds/stagefright/WaveWriter.h b/cmds/stagefright/WaveWriter.h
new file mode 100644
index 000000000000..a0eb66e2b9bc
--- /dev/null
+++ b/cmds/stagefright/WaveWriter.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_WAVEWRITER_H_
+
+#define ANDROID_WAVEWRITER_H_
+
+namespace android {
+
+class WaveWriter {
+public:
+ WaveWriter(const char *filename,
+ uint16_t num_channels, uint32_t sampling_rate)
+ : mFile(fopen(filename, "wb")),
+ mTotalBytes(0) {
+ fwrite("RIFFxxxxWAVEfmt \x10\x00\x00\x00\x01\x00", 1, 22, mFile);
+ write_u16(num_channels);
+ write_u32(sampling_rate);
+ write_u32(sampling_rate * num_channels * 2);
+ write_u16(num_channels * 2);
+ write_u16(16);
+ fwrite("dataxxxx", 1, 8, mFile);
+ }
+
+ ~WaveWriter() {
+ fseek(mFile, 40, SEEK_SET);
+ write_u32(mTotalBytes);
+
+ fseek(mFile, 4, SEEK_SET);
+ write_u32(36 + mTotalBytes);
+
+ fclose(mFile);
+ mFile = NULL;
+ }
+
+ void Append(const void *data, size_t size) {
+ fwrite(data, 1, size, mFile);
+ mTotalBytes += size;
+ }
+
+private:
+ void write_u16(uint16_t x) {
+ fputc(x & 0xff, mFile);
+ fputc(x >> 8, mFile);
+ }
+
+ void write_u32(uint32_t x) {
+ write_u16(x & 0xffff);
+ write_u16(x >> 16);
+ }
+
+ FILE *mFile;
+ size_t mTotalBytes;
+};
+
+} // namespace android
+
+#endif // ANDROID_WAVEWRITER_H_
diff --git a/cmds/stagefright/record.cpp b/cmds/stagefright/record.cpp
new file mode 100644
index 000000000000..323d448663f9
--- /dev/null
+++ b/cmds/stagefright/record.cpp
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SineSource.h"
+
+#include <binder/ProcessState.h>
+#include <media/stagefright/AudioPlayer.h>
+#include <media/stagefright/CameraSource.h>
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/MPEG4Extractor.h>
+#include <media/stagefright/MPEG4Writer.h>
+#include <media/stagefright/MmapSource.h>
+#include <media/stagefright/OMXClient.h>
+#include <media/stagefright/OMXCodec.h>
+#include <media/MediaPlayerInterface.h>
+
+using namespace android;
+
+#if 0
+class DummySource : public MediaSource {
+public:
+ DummySource(int width, int height)
+ : mWidth(width),
+ mHeight(height),
+ mSize((width * height * 3) / 2) {
+ mGroup.add_buffer(new MediaBuffer(mSize));
+ }
+
+ virtual sp<MetaData> getFormat() {
+ sp<MetaData> meta = new MetaData;
+ meta->setInt32(kKeyWidth, mWidth);
+ meta->setInt32(kKeyHeight, mHeight);
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
+
+ return meta;
+ }
+
+ virtual status_t start(MetaData *params) {
+ return OK;
+ }
+
+ virtual status_t stop() {
+ return OK;
+ }
+
+ virtual status_t read(
+ MediaBuffer **buffer, const MediaSource::ReadOptions *options) {
+ status_t err = mGroup.acquire_buffer(buffer);
+ if (err != OK) {
+ return err;
+ }
+
+ char x = (char)((double)rand() / RAND_MAX * 255);
+ memset((*buffer)->data(), x, mSize);
+ (*buffer)->set_range(0, mSize);
+
+ return OK;
+ }
+
+protected:
+ virtual ~DummySource() {}
+
+private:
+ MediaBufferGroup mGroup;
+ int mWidth, mHeight;
+ size_t mSize;
+
+ DummySource(const DummySource &);
+ DummySource &operator=(const DummySource &);
+};
+
+sp<MediaSource> createSource(const char *filename) {
+ sp<MediaSource> source;
+
+ sp<MPEG4Extractor> extractor =
+ new MPEG4Extractor(new MmapSource(filename));
+
+ size_t num_tracks = extractor->countTracks();
+
+ sp<MetaData> meta;
+ for (size_t i = 0; i < num_tracks; ++i) {
+ meta = extractor->getTrackMetaData(i);
+ CHECK(meta.get() != NULL);
+
+ const char *mime;
+ if (!meta->findCString(kKeyMIMEType, &mime)) {
+ continue;
+ }
+
+ if (strncasecmp(mime, "video/", 6)) {
+ continue;
+ }
+
+ source = extractor->getTrack(i);
+ break;
+ }
+
+ return source;
+}
+
+int main(int argc, char **argv) {
+ android::ProcessState::self()->startThreadPool();
+
+#if 1
+ if (argc != 2) {
+ fprintf(stderr, "usage: %s filename\n", argv[0]);
+ return 1;
+ }
+
+ OMXClient client;
+ CHECK_EQ(client.connect(), OK);
+
+#if 0
+ sp<MediaSource> source = createSource(argv[1]);
+
+ if (source == NULL) {
+ fprintf(stderr, "Unable to find a suitable video track.\n");
+ return 1;
+ }
+
+ sp<MetaData> meta = source->getFormat();
+
+ sp<OMXCodec> decoder = OMXCodec::Create(
+ client.interface(), meta, false /* createEncoder */, source);
+
+ int width, height;
+ bool success = meta->findInt32(kKeyWidth, &width);
+ success = success && meta->findInt32(kKeyHeight, &height);
+ CHECK(success);
+#else
+ int width = 320;
+ int height = 240;
+ sp<MediaSource> decoder = new DummySource(width, height);
+#endif
+
+ sp<MetaData> enc_meta = new MetaData;
+ // enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
+ enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
+ enc_meta->setInt32(kKeyWidth, width);
+ enc_meta->setInt32(kKeyHeight, height);
+
+ sp<OMXCodec> encoder =
+ OMXCodec::Create(
+ client.interface(), enc_meta, true /* createEncoder */, decoder);
+
+#if 0
+ sp<MPEG4Writer> writer = new MPEG4Writer("/sdcard/output.mp4");
+ writer->addSource(enc_meta, encoder);
+ writer->start();
+ sleep(20);
+ printf("stopping now.\n");
+ writer->stop();
+#else
+ encoder->start();
+
+ MediaBuffer *buffer;
+ while (encoder->read(&buffer) == OK) {
+ printf("got an output frame of size %d\n", buffer->range_length());
+
+ buffer->release();
+ buffer = NULL;
+ }
+
+ encoder->stop();
+#endif
+
+ client.disconnect();
+#endif
+
+#if 0
+ CameraSource *source = CameraSource::Create();
+ printf("source = %p\n", source);
+
+ for (int i = 0; i < 100; ++i) {
+ MediaBuffer *buffer;
+ status_t err = source->read(&buffer);
+ CHECK_EQ(err, OK);
+
+ printf("got a frame, data=%p, size=%d\n",
+ buffer->data(), buffer->range_length());
+
+ buffer->release();
+ buffer = NULL;
+ }
+
+ delete source;
+ source = NULL;
+#endif
+
+ return 0;
+}
+#else
+
+int main(int argc, char **argv) {
+ android::ProcessState::self()->startThreadPool();
+
+ OMXClient client;
+ CHECK_EQ(client.connect(), OK);
+
+ const int32_t kSampleRate = 22050;
+ const int32_t kNumChannels = 2;
+ sp<MediaSource> audioSource = new SineSource(kSampleRate, kNumChannels);
+
+#if 0
+ sp<MediaPlayerBase::AudioSink> audioSink;
+ AudioPlayer *player = new AudioPlayer(audioSink);
+ player->setSource(audioSource);
+ player->start();
+
+ sleep(10);
+
+ player->stop();
+#endif
+
+ sp<MetaData> encMeta = new MetaData;
+ encMeta->setCString(kKeyMIMEType,
+ 1 ? MEDIA_MIMETYPE_AUDIO_AMR_WB : MEDIA_MIMETYPE_AUDIO_AAC);
+ encMeta->setInt32(kKeySampleRate, kSampleRate);
+ encMeta->setInt32(kKeyChannelCount, kNumChannels);
+ encMeta->setInt32(kKeyMaxInputSize, 8192);
+
+ sp<MediaSource> encoder =
+ OMXCodec::Create(client.interface(), encMeta, true, audioSource);
+
+ encoder->start();
+
+ int32_t n = 0;
+ status_t err;
+ MediaBuffer *buffer;
+ while ((err = encoder->read(&buffer)) == OK) {
+ printf(".");
+ fflush(stdout);
+
+ buffer->release();
+ buffer = NULL;
+
+ if (++n == 100) {
+ break;
+ }
+ }
+ printf("$\n");
+
+ encoder->stop();
+
+ client.disconnect();
+
+ return 0;
+}
+#endif
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
new file mode 100644
index 000000000000..4ffc8e437551
--- /dev/null
+++ b/cmds/stagefright/stagefright.cpp
@@ -0,0 +1,402 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/time.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <media/IMediaPlayerService.h>
+#include <media/stagefright/CachingDataSource.h>
+#include <media/stagefright/HTTPDataSource.h>
+#include <media/stagefright/JPEGSource.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaPlayerImpl.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/MmapSource.h>
+#include <media/stagefright/OMXClient.h>
+#include <media/stagefright/OMXCodec.h>
+
+using namespace android;
+
+static long gNumRepetitions;
+static long gMaxNumFrames; // 0 means decode all available.
+static long gReproduceBug; // if not -1.
+
+static int64_t getNowUs() {
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+
+ return (int64_t)tv.tv_usec + tv.tv_sec * 1000000;
+}
+
+static void playSource(OMXClient *client, const sp<MediaSource> &source) {
+ sp<MetaData> meta = source->getFormat();
+
+ int32_t durationUnits;
+ int32_t timeScale;
+ CHECK(meta->findInt32(kKeyDuration, &durationUnits));
+ CHECK(meta->findInt32(kKeyTimeScale, &timeScale));
+
+ int64_t durationUs = ((int64_t)durationUnits * 1000000) / timeScale;
+
+ sp<OMXCodec> decoder = OMXCodec::Create(
+ client->interface(), meta, false /* createEncoder */, source);
+
+ if (decoder == NULL) {
+ return;
+ }
+
+ decoder->start();
+
+ if (gReproduceBug >= 3 && gReproduceBug <= 5) {
+ status_t err;
+ MediaBuffer *buffer;
+ MediaSource::ReadOptions options;
+ int64_t seekTimeUs = -1;
+ for (;;) {
+ err = decoder->read(&buffer, &options);
+ options.clearSeekTo();
+
+ bool shouldSeek = false;
+ if (err != OK) {
+ printf("reached EOF.\n");
+
+ shouldSeek = true;
+ } else {
+ int32_t timestampUnits;
+ CHECK(buffer->meta_data()->findInt32(kKeyTimeUnits, &timestampUnits));
+
+ int64_t timestampUs = ((int64_t)timestampUnits * 1000000) / timeScale;
+
+ bool failed = false;
+
+ if (seekTimeUs >= 0) {
+ int64_t diff = timestampUs - seekTimeUs;
+ if (diff < 0) {
+ diff = -diff;
+ }
+
+ if ((gReproduceBug == 4 && diff > 500000)
+ || (gReproduceBug == 5 && timestampUs < 0)) {
+ printf("wanted: %.2f secs, got: %.2f secs\n",
+ seekTimeUs / 1E6, timestampUs / 1E6);
+
+ printf("ERROR: ");
+ failed = true;
+ }
+ }
+
+ printf("buffer has timestamp %lld us (%.2f secs)\n",
+ timestampUs, timestampUs / 1E6);
+
+ buffer->release();
+ buffer = NULL;
+
+ if (failed) {
+ break;
+ }
+
+ shouldSeek = ((double)rand() / RAND_MAX) < 0.1;
+
+ if (gReproduceBug == 3) {
+ shouldSeek = false;
+ }
+ }
+
+ seekTimeUs = -1;
+
+ if (shouldSeek) {
+ seekTimeUs = (rand() * (float)durationUs) / RAND_MAX;
+ options.setSeekTo(seekTimeUs);
+
+ printf("seeking to %lld us (%.2f secs)\n",
+ seekTimeUs, seekTimeUs / 1E6);
+ }
+ }
+
+ decoder->stop();
+
+ return;
+ }
+
+ int n = 0;
+ int64_t startTime = getNowUs();
+
+ long numIterationsLeft = gNumRepetitions;
+ MediaSource::ReadOptions options;
+
+ while (numIterationsLeft-- > 0) {
+ long numFrames = 0;
+
+ MediaBuffer *buffer;
+
+ for (;;) {
+ status_t err = decoder->read(&buffer, &options);
+ options.clearSeekTo();
+
+ if (err != OK) {
+ CHECK_EQ(buffer, NULL);
+
+ break;
+ }
+
+ if ((n++ % 16) == 0) {
+ printf(".");
+ fflush(stdout);
+ }
+
+ buffer->release();
+ buffer = NULL;
+
+ ++numFrames;
+ if (gMaxNumFrames > 0 && numFrames == gMaxNumFrames) {
+ break;
+ }
+
+ if (gReproduceBug == 1 && numFrames == 40) {
+ printf("seeking past the end now.");
+ options.setSeekTo(0x7fffffffL);
+ } else if (gReproduceBug == 2 && numFrames == 40) {
+ printf("seeking to 5 secs.");
+ options.setSeekTo(5000000);
+ }
+ }
+
+ printf("$");
+ fflush(stdout);
+
+ options.setSeekTo(0);
+ }
+
+ decoder->stop();
+ printf("\n");
+
+ int64_t delay = getNowUs() - startTime;
+ printf("avg. %.2f fps\n", n * 1E6 / delay);
+
+ printf("decoded a total of %d frame(s).\n", n);
+}
+
+static void usage(const char *me) {
+ fprintf(stderr, "usage: %s\n", me);
+ fprintf(stderr, " -h(elp)\n");
+ fprintf(stderr, " -a(udio)\n");
+ fprintf(stderr, " -n repetitions\n");
+ fprintf(stderr, " -l(ist) components\n");
+ fprintf(stderr, " -m max-number-of-frames-to-decode in each pass\n");
+ fprintf(stderr, " -b bug to reproduce\n");
+ fprintf(stderr, " -p(rofiles) dump decoder profiles supported\n");
+}
+
+int main(int argc, char **argv) {
+ android::ProcessState::self()->startThreadPool();
+
+ bool audioOnly = false;
+ bool listComponents = false;
+ bool dumpProfiles = false;
+ gNumRepetitions = 1;
+ gMaxNumFrames = 0;
+ gReproduceBug = -1;
+
+ int res;
+ while ((res = getopt(argc, argv, "han:lm:b:p")) >= 0) {
+ switch (res) {
+ case 'a':
+ {
+ audioOnly = true;
+ break;
+ }
+
+ case 'l':
+ {
+ listComponents = true;
+ break;
+ }
+
+ case 'm':
+ case 'n':
+ case 'b':
+ {
+ char *end;
+ long x = strtol(optarg, &end, 10);
+
+ if (*end != '\0' || end == optarg || x <= 0) {
+ x = 1;
+ }
+
+ if (res == 'n') {
+ gNumRepetitions = x;
+ } else if (res == 'm') {
+ gMaxNumFrames = x;
+ } else {
+ CHECK_EQ(res, 'b');
+ gReproduceBug = x;
+ }
+ break;
+ }
+
+ case 'p':
+ {
+ dumpProfiles = true;
+ break;
+ }
+
+ case '?':
+ case 'h':
+ default:
+ {
+ usage(argv[0]);
+ exit(1);
+ break;
+ }
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (dumpProfiles) {
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder = sm->getService(String16("media.player"));
+ sp<IMediaPlayerService> service =
+ interface_cast<IMediaPlayerService>(binder);
+
+ CHECK(service.get() != NULL);
+
+ sp<IOMX> omx = service->getOMX();
+ CHECK(omx.get() != NULL);
+
+ const char *kMimeTypes[] = {
+ MEDIA_MIMETYPE_VIDEO_AVC, MEDIA_MIMETYPE_VIDEO_MPEG4,
+ MEDIA_MIMETYPE_VIDEO_H263
+ };
+
+ for (size_t k = 0; k < sizeof(kMimeTypes) / sizeof(kMimeTypes[0]);
+ ++k) {
+ printf("type '%s':\n", kMimeTypes[k]);
+
+ Vector<CodecCapabilities> results;
+ CHECK_EQ(QueryCodecs(omx, kMimeTypes[k],
+ true, // queryDecoders
+ &results), OK);
+
+ for (size_t i = 0; i < results.size(); ++i) {
+ printf(" decoder '%s' supports ",
+ results[i].mComponentName.string());
+
+ if (results[i].mProfileLevels.size() == 0) {
+ printf("NOTHING.\n");
+ continue;
+ }
+
+ for (size_t j = 0; j < results[i].mProfileLevels.size(); ++j) {
+ const CodecProfileLevel &profileLevel =
+ results[i].mProfileLevels[j];
+
+ printf("%s%ld/%ld", j > 0 ? ", " : "",
+ profileLevel.mProfile, profileLevel.mLevel);
+ }
+
+ printf("\n");
+ }
+ }
+ }
+
+ if (listComponents) {
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder = sm->getService(String16("media.player"));
+ sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
+
+ CHECK(service.get() != NULL);
+
+ sp<IOMX> omx = service->getOMX();
+ CHECK(omx.get() != NULL);
+
+ List<String8> list;
+ omx->listNodes(&list);
+
+ for (List<String8>::iterator it = list.begin();
+ it != list.end(); ++it) {
+ printf("%s\n", (*it).string());
+ }
+ }
+
+ DataSource::RegisterDefaultSniffers();
+
+ OMXClient client;
+ status_t err = client.connect();
+
+ for (int k = 0; k < argc; ++k) {
+ const char *filename = argv[k];
+
+ sp<DataSource> dataSource;
+ if (!strncasecmp("http://", filename, 7)) {
+ dataSource = new HTTPDataSource(filename);
+ dataSource = new CachingDataSource(dataSource, 64 * 1024, 10);
+ } else {
+ dataSource = new MmapSource(filename);
+ }
+
+ bool isJPEG = false;
+
+ size_t len = strlen(filename);
+ if (len >= 4 && !strcasecmp(filename + len - 4, ".jpg")) {
+ isJPEG = true;
+ }
+
+ sp<MediaSource> mediaSource;
+
+ if (isJPEG) {
+ mediaSource = new JPEGSource(dataSource);
+ } else {
+ sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
+
+ size_t numTracks = extractor->countTracks();
+
+ sp<MetaData> meta;
+ size_t i;
+ for (i = 0; i < numTracks; ++i) {
+ meta = extractor->getTrackMetaData(i);
+
+ const char *mime;
+ meta->findCString(kKeyMIMEType, &mime);
+
+ if (audioOnly && !strncasecmp(mime, "audio/", 6)) {
+ break;
+ }
+
+ if (!audioOnly && !strncasecmp(mime, "video/", 6)) {
+ break;
+ }
+ }
+
+ mediaSource = extractor->getTrack(i);
+ }
+
+ playSource(&client, mediaSource);
+ }
+
+ client.disconnect();
+
+ return 0;
+}
diff --git a/cmds/surfaceflinger/Android.mk b/cmds/surfaceflinger/Android.mk
index 37c3d942414a..bfa58a1cbf7f 100644
--- a/cmds/surfaceflinger/Android.mk
+++ b/cmds/surfaceflinger/Android.mk
@@ -6,6 +6,7 @@ LOCAL_SRC_FILES:= \
LOCAL_SHARED_LIBRARIES := \
libsurfaceflinger \
+ libbinder \
libutils
LOCAL_C_INCLUDES := \
diff --git a/cmds/surfaceflinger/main_surfaceflinger.cpp b/cmds/surfaceflinger/main_surfaceflinger.cpp
index 7c895783d762..d65072132783 100644
--- a/cmds/surfaceflinger/main_surfaceflinger.cpp
+++ b/cmds/surfaceflinger/main_surfaceflinger.cpp
@@ -1,6 +1,6 @@
-#include <utils/IPCThreadState.h>
-#include <utils/ProcessState.h>
-#include <utils/IServiceManager.h>
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
#include <utils/Log.h>
#include <SurfaceFlinger.h>
diff --git a/cmds/svc/src/com/android/commands/svc/PowerCommand.java b/cmds/svc/src/com/android/commands/svc/PowerCommand.java
index 2b54f549f389..e021012268c9 100644
--- a/cmds/svc/src/com/android/commands/svc/PowerCommand.java
+++ b/cmds/svc/src/com/android/commands/svc/PowerCommand.java
@@ -16,7 +16,10 @@
package com.android.commands.svc;
+import android.os.Binder;
+import android.os.IBinder;
import android.os.IPowerManager;
+import android.os.PowerManager;
import android.os.ServiceManager;
import android.os.RemoteException;
import android.os.BatteryManager;
@@ -60,7 +63,10 @@ public class PowerCommand extends Svc.Command {
IPowerManager pm
= IPowerManager.Stub.asInterface(ServiceManager.getService(Context.POWER_SERVICE));
try {
+ IBinder lock = new Binder();
+ pm.acquireWakeLock(PowerManager.FULL_WAKE_LOCK, lock, "svc power");
pm.setStayOnSetting(val);
+ pm.releaseWakeLock(lock);
}
catch (RemoteException e) {
System.err.println("Faild to set setting: " + e);
diff --git a/cmds/system_server/Android.mk b/cmds/system_server/Android.mk
index 0a684e86b1c7..ad537977d9eb 100644
--- a/cmds/system_server/Android.mk
+++ b/cmds/system_server/Android.mk
@@ -6,6 +6,7 @@ LOCAL_SRC_FILES:= \
LOCAL_SHARED_LIBRARIES := \
libutils \
+ libbinder \
libsystem_server
LOCAL_C_INCLUDES := \
diff --git a/cmds/system_server/library/Android.mk b/cmds/system_server/library/Android.mk
index 580331a695af..1813d3e5ab0c 100644
--- a/cmds/system_server/library/Android.mk
+++ b/cmds/system_server/library/Android.mk
@@ -20,6 +20,7 @@ LOCAL_SHARED_LIBRARIES := \
libcameraservice \
libmediaplayerservice \
libutils \
+ libbinder \
libcutils
LOCAL_MODULE:= libsystem_server
diff --git a/cmds/system_server/library/system_init.cpp b/cmds/system_server/library/system_init.cpp
index 73b23e27e3bd..1d57fdcc4c77 100644
--- a/cmds/system_server/library/system_init.cpp
+++ b/cmds/system_server/library/system_init.cpp
@@ -8,15 +8,16 @@
#define LOG_TAG "sysproc"
-#include <utils/IPCThreadState.h>
-#include <utils/ProcessState.h>
-#include <utils/IServiceManager.h>
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
#include <utils/TextOutput.h>
#include <utils/Log.h>
#include <SurfaceFlinger.h>
#include <AudioFlinger.h>
#include <CameraService.h>
+#include <AudioPolicyService.h>
#include <MediaPlayerService.h>
#include <android_runtime/AndroidRuntime.h>
@@ -80,6 +81,9 @@ extern "C" status_t system_init()
// Start the camera service
CameraService::instantiate();
+
+ // Start the audio policy service
+ AudioPolicyService::instantiate();
}
// And now start the Android runtime. We have to do this bit
diff --git a/cmds/system_server/system_main.cpp b/cmds/system_server/system_main.cpp
index ca16e5700622..543f650a4d22 100644
--- a/cmds/system_server/system_main.cpp
+++ b/cmds/system_server/system_main.cpp
@@ -9,7 +9,7 @@
#define LOG_TAG "sysproc"
-#include <utils/IPCThreadState.h>
+#include <binder/IPCThreadState.h>
#include <utils/Log.h>
#include <private/android_filesystem_config.h>