Merge "Check outInfo is not null" into jb-mr2-dev
diff --git a/api/current.txt b/api/current.txt
index 7fe166e..1e1f01c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -18504,10 +18504,6 @@
protected static abstract interface ContactsContract.DataUsageStatColumns {
field public static final java.lang.String LAST_TIME_USED = "last_time_used";
field public static final java.lang.String TIMES_USED = "times_used";
- field public static final java.lang.String USAGE_TYPE = "usage_type";
- field public static final int USAGE_TYPE_CALL = 0; // 0x0
- field public static final int USAGE_TYPE_LONG_TEXT = 1; // 0x1
- field public static final int USAGE_TYPE_SHORT_TEXT = 2; // 0x2
}
public static final class ContactsContract.Directory implements android.provider.BaseColumns {
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 1c02960..ccb9e1f 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -39,6 +39,7 @@
import android.os.UserHandle;
import android.util.AndroidException;
import android.view.IWindowManager;
+import com.android.internal.os.BaseCommand;
import java.io.BufferedReader;
import java.io.File;
@@ -50,12 +51,9 @@
import java.util.HashSet;
import java.util.List;
-public class Am {
+public class Am extends BaseCommand {
private IActivityManager mAm;
- private String[] mArgs;
- private int mNextArg;
- private String mCurArgData;
private int mStartFlags = 0;
private boolean mWaitOption = false;
@@ -67,33 +65,155 @@
private String mProfileFile;
- // 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) {
- try {
- (new Am()).run(args);
- } catch (IllegalArgumentException e) {
- showUsage();
- System.err.println("Error: " + e.getMessage());
- } catch (Exception e) {
- e.printStackTrace(System.err);
- System.exit(1);
- }
+ (new Am()).run(args);
}
- private void run(String[] args) throws Exception {
- if (args.length < 1) {
- showUsage();
- return;
- }
+ public void onShowUsage(PrintStream out) {
+ out.println(
+ "usage: am [subcommand] [options]\n" +
+ "usage: am start [-D] [-W] [-P <FILE>] [--start-profiler <FILE>]\n" +
+ " [--R COUNT] [-S] [--opengl-trace]\n" +
+ " [--user <USER_ID> | current] <INTENT>\n" +
+ " am startservice [--user <USER_ID> | current] <INTENT>\n" +
+ " am force-stop [--user <USER_ID> | all | current] <PACKAGE>\n" +
+ " am kill [--user <USER_ID> | all | current] <PACKAGE>\n" +
+ " am kill-all\n" +
+ " am broadcast [--user <USER_ID> | all | current] <INTENT>\n" +
+ " am instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]\n" +
+ " [--user <USER_ID> | current]\n" +
+ " [--no-window-animation] <COMPONENT>\n" +
+ " am profile start [--user <USER_ID> current] <PROCESS> <FILE>\n" +
+ " am profile stop [--user <USER_ID> current] [<PROCESS>]\n" +
+ " am dumpheap [--user <USER_ID> current] [-n] <PROCESS> <FILE>\n" +
+ " am set-debug-app [-w] [--persistent] <PACKAGE>\n" +
+ " am clear-debug-app\n" +
+ " am monitor [--gdb <port>]\n" +
+ " am screen-compat [on|off] <PACKAGE>\n" +
+ " am to-uri [INTENT]\n" +
+ " am to-intent-uri [INTENT]\n" +
+ " am switch-user <USER_ID>\n" +
+ " am stop-user <USER_ID>\n" +
+ "\n" +
+ "am start: start an Activity. Options are:\n" +
+ " -D: enable debugging\n" +
+ " -W: wait for launch to complete\n" +
+ " --start-profiler <FILE>: start profiler and send results to <FILE>\n" +
+ " -P <FILE>: like above, but profiling stops when app goes idle\n" +
+ " -R: repeat the activity launch <COUNT> times. Prior to each repeat,\n" +
+ " the top activity will be finished.\n" +
+ " -S: force stop the target app before starting the activity\n" +
+ " --opengl-trace: enable tracing of OpenGL functions\n" +
+ " --user <USER_ID> | current: Specify which user to run as; if not\n" +
+ " specified then run as the current user.\n" +
+ "\n" +
+ "am startservice: start a Service. Options are:\n" +
+ " --user <USER_ID> | current: Specify which user to run as; if not\n" +
+ " specified then run as the current user.\n" +
+ "\n" +
+ "am force-stop: force stop everything associated with <PACKAGE>.\n" +
+ " --user <USER_ID> | all | current: Specify user to force stop;\n" +
+ " all users if not specified.\n" +
+ "\n" +
+ "am kill: Kill all processes associated with <PACKAGE>. Only kills.\n" +
+ " processes that are safe to kill -- that is, will not impact the user\n" +
+ " experience.\n" +
+ " --user <USER_ID> | all | current: Specify user whose processes to kill;\n" +
+ " all users if not specified.\n" +
+ "\n" +
+ "am kill-all: Kill all background processes.\n" +
+ "\n" +
+ "am broadcast: send a broadcast Intent. Options are:\n" +
+ " --user <USER_ID> | all | current: Specify which user to send to; if not\n" +
+ " specified then send to all users.\n" +
+ " --receiver-permission <PERMISSION>: Require receiver to hold permission.\n" +
+ "\n" +
+ "am instrument: start an Instrumentation. Typically this target <COMPONENT>\n" +
+ " is the form <TEST_PACKAGE>/<RUNNER_CLASS>. Options are:\n" +
+ " -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT). Use with\n" +
+ " [-e perf true] to generate raw output for performance measurements.\n" +
+ " -e <NAME> <VALUE>: set argument <NAME> to <VALUE>. For test runners a\n" +
+ " common form is [-e <testrunner_flag> <value>[,<value>...]].\n" +
+ " -p <FILE>: write profiling data to <FILE>\n" +
+ " -w: wait for instrumentation to finish before returning. Required for\n" +
+ " test runners.\n" +
+ " --user <USER_ID> | current: Specify user instrumentation runs in;\n" +
+ " current user if not specified.\n" +
+ " --no-window-animation: turn off window animations will running.\n" +
+ "\n" +
+ "am profile: start and stop profiler on a process. The given <PROCESS> argument\n" +
+ " may be either a process name or pid. Options are:\n" +
+ " --user <USER_ID> | current: When supplying a process name,\n" +
+ " specify user of process to profile; uses current user if not specified.\n" +
+ "\n" +
+ "am dumpheap: dump the heap of a process. The given <PROCESS> argument may\n" +
+ " be either a process name or pid. Options are:\n" +
+ " -n: dump native heap instead of managed heap\n" +
+ " --user <USER_ID> | current: When supplying a process name,\n" +
+ " specify user of process to dump; uses current user if not specified.\n" +
+ "\n" +
+ "am set-debug-app: set application <PACKAGE> to debug. Options are:\n" +
+ " -w: wait for debugger when application starts\n" +
+ " --persistent: retain this value\n" +
+ "\n" +
+ "am clear-debug-app: clear the previously set-debug-app.\n" +
+ "\n" +
+ "am bug-report: request bug report generation; will launch UI\n" +
+ " when done to select where it should be delivered.\n" +
+ "\n" +
+ "am monitor: start monitoring for crashes or ANRs.\n" +
+ " --gdb: start gdbserv on the given port at crash/ANR\n" +
+ "\n" +
+ "am screen-compat: control screen compatibility mode of <PACKAGE>.\n" +
+ "\n" +
+ "am to-uri: print the given Intent specification as a URI.\n" +
+ "\n" +
+ "am to-intent-uri: print the given Intent specification as an intent: URI.\n" +
+ "\n" +
+ "am switch-user: switch to put USER_ID in the foreground, starting\n" +
+ " execution of that user if it is currently stopped.\n" +
+ "\n" +
+ "am stop-user: stop execution of USER_ID, not allowing it to run any\n" +
+ " code until a later explicit switch to it.\n" +
+ "\n" +
+ "<INTENT> specifications include these flags and arguments:\n" +
+ " [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" +
+ " [-c <CATEGORY> [-c <CATEGORY>] ...]\n" +
+ " [-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]\n" +
+ " [--esn <EXTRA_KEY> ...]\n" +
+ " [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]\n" +
+ " [--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]\n" +
+ " [--el <EXTRA_KEY> <EXTRA_LONG_VALUE> ...]\n" +
+ " [--ef <EXTRA_KEY> <EXTRA_FLOAT_VALUE> ...]\n" +
+ " [--eu <EXTRA_KEY> <EXTRA_URI_VALUE> ...]\n" +
+ " [--ecn <EXTRA_KEY> <EXTRA_COMPONENT_NAME_VALUE>]\n" +
+ " [--eia <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]\n" +
+ " [--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]\n" +
+ " [--efa <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]]\n" +
+ " [-n <COMPONENT>] [-f <FLAGS>]\n" +
+ " [--grant-read-uri-permission] [--grant-write-uri-permission]\n" +
+ " [--debug-log-resolution] [--exclude-stopped-packages]\n" +
+ " [--include-stopped-packages]\n" +
+ " [--activity-brought-to-front] [--activity-clear-top]\n" +
+ " [--activity-clear-when-task-reset] [--activity-exclude-from-recents]\n" +
+ " [--activity-launched-from-history] [--activity-multiple-task]\n" +
+ " [--activity-no-animation] [--activity-no-history]\n" +
+ " [--activity-no-user-action] [--activity-previous-is-top]\n" +
+ " [--activity-reorder-to-front] [--activity-reset-task-if-needed]\n" +
+ " [--activity-single-top] [--activity-clear-task]\n" +
+ " [--activity-task-on-home]\n" +
+ " [--receiver-registered-only] [--receiver-replace-pending]\n" +
+ " [--selector]\n" +
+ " [<URI> | <PACKAGE> | <COMPONENT>]\n"
+ );
+ }
+
+ public void onRun() throws Exception {
mAm = ActivityManagerNative.getDefault();
if (mAm == null) {
@@ -101,9 +221,7 @@
throw new AndroidException("Can't connect to activity manager; is the system running?");
}
- mArgs = args;
- String op = args[0];
- mNextArg = 1;
+ String op = nextArgRequired();
if (op.equals("start")) {
runStart();
@@ -142,7 +260,7 @@
} else if (op.equals("stop-user")) {
runStopUser();
} else {
- throw new IllegalArgumentException("Unknown command: " + op);
+ showError("Error: unknown command '" + op + "'");
}
}
@@ -1303,193 +1421,4 @@
return true;
}
}
-
- 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;
- }
- String arg = mArgs[mNextArg];
- if (!arg.startsWith("-")) {
- return null;
- }
- mNextArg++;
- if (arg.equals("--")) {
- return null;
- }
- if (arg.length() > 1 && arg.charAt(1) != '-') {
- if (arg.length() > 2) {
- mCurArgData = arg.substring(2);
- return arg.substring(0, 2);
- } else {
- mCurArgData = null;
- return arg;
- }
- }
- mCurArgData = null;
- return arg;
- }
-
- private String nextArg() {
- if (mCurArgData != null) {
- String arg = mCurArgData;
- mCurArgData = null;
- return arg;
- } else if (mNextArg < mArgs.length) {
- return mArgs[mNextArg++];
- } else {
- return null;
- }
- }
-
- private String nextArgRequired() {
- String arg = nextArg();
- if (arg == null) {
- String prev = mArgs[mNextArg - 1];
- throw new IllegalArgumentException("Argument expected after \"" + prev + "\"");
- }
- return arg;
- }
-
- private static void showUsage() {
- System.err.println(
- "usage: am [subcommand] [options]\n" +
- "usage: am start [-D] [-W] [-P <FILE>] [--start-profiler <FILE>]\n" +
- " [--R COUNT] [-S] [--opengl-trace]\n" +
- " [--user <USER_ID> | current] <INTENT>\n" +
- " am startservice [--user <USER_ID> | current] <INTENT>\n" +
- " am force-stop [--user <USER_ID> | all | current] <PACKAGE>\n" +
- " am kill [--user <USER_ID> | all | current] <PACKAGE>\n" +
- " am kill-all\n" +
- " am broadcast [--user <USER_ID> | all | current] <INTENT>\n" +
- " am instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]\n" +
- " [--user <USER_ID> | current]\n" +
- " [--no-window-animation] <COMPONENT>\n" +
- " am profile start [--user <USER_ID> current] <PROCESS> <FILE>\n" +
- " am profile stop [--user <USER_ID> current] [<PROCESS>]\n" +
- " am dumpheap [--user <USER_ID> current] [-n] <PROCESS> <FILE>\n" +
- " am set-debug-app [-w] [--persistent] <PACKAGE>\n" +
- " am clear-debug-app\n" +
- " am monitor [--gdb <port>]\n" +
- " am screen-compat [on|off] <PACKAGE>\n" +
- " am to-uri [INTENT]\n" +
- " am to-intent-uri [INTENT]\n" +
- " am switch-user <USER_ID>\n" +
- " am stop-user <USER_ID>\n" +
- "\n" +
- "am start: start an Activity. Options are:\n" +
- " -D: enable debugging\n" +
- " -W: wait for launch to complete\n" +
- " --start-profiler <FILE>: start profiler and send results to <FILE>\n" +
- " -P <FILE>: like above, but profiling stops when app goes idle\n" +
- " -R: repeat the activity launch <COUNT> times. Prior to each repeat,\n" +
- " the top activity will be finished.\n" +
- " -S: force stop the target app before starting the activity\n" +
- " --opengl-trace: enable tracing of OpenGL functions\n" +
- " --user <USER_ID> | current: Specify which user to run as; if not\n" +
- " specified then run as the current user.\n" +
- "\n" +
- "am startservice: start a Service. Options are:\n" +
- " --user <USER_ID> | current: Specify which user to run as; if not\n" +
- " specified then run as the current user.\n" +
- "\n" +
- "am force-stop: force stop everything associated with <PACKAGE>.\n" +
- " --user <USER_ID> | all | current: Specify user to force stop;\n" +
- " all users if not specified.\n" +
- "\n" +
- "am kill: Kill all processes associated with <PACKAGE>. Only kills.\n" +
- " processes that are safe to kill -- that is, will not impact the user\n" +
- " experience.\n" +
- " --user <USER_ID> | all | current: Specify user whose processes to kill;\n" +
- " all users if not specified.\n" +
- "\n" +
- "am kill-all: Kill all background processes.\n" +
- "\n" +
- "am broadcast: send a broadcast Intent. Options are:\n" +
- " --user <USER_ID> | all | current: Specify which user to send to; if not\n" +
- " specified then send to all users.\n" +
- " --receiver-permission <PERMISSION>: Require receiver to hold permission.\n" +
- "\n" +
- "am instrument: start an Instrumentation. Typically this target <COMPONENT>\n" +
- " is the form <TEST_PACKAGE>/<RUNNER_CLASS>. Options are:\n" +
- " -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT). Use with\n" +
- " [-e perf true] to generate raw output for performance measurements.\n" +
- " -e <NAME> <VALUE>: set argument <NAME> to <VALUE>. For test runners a\n" +
- " common form is [-e <testrunner_flag> <value>[,<value>...]].\n" +
- " -p <FILE>: write profiling data to <FILE>\n" +
- " -w: wait for instrumentation to finish before returning. Required for\n" +
- " test runners.\n" +
- " --user <USER_ID> | current: Specify user instrumentation runs in;\n" +
- " current user if not specified.\n" +
- " --no-window-animation: turn off window animations will running.\n" +
- "\n" +
- "am profile: start and stop profiler on a process. The given <PROCESS> argument\n" +
- " may be either a process name or pid. Options are:\n" +
- " --user <USER_ID> | current: When supplying a process name,\n" +
- " specify user of process to profile; uses current user if not specified.\n" +
- "\n" +
- "am dumpheap: dump the heap of a process. The given <PROCESS> argument may\n" +
- " be either a process name or pid. Options are:\n" +
- " -n: dump native heap instead of managed heap\n" +
- " --user <USER_ID> | current: When supplying a process name,\n" +
- " specify user of process to dump; uses current user if not specified.\n" +
- "\n" +
- "am set-debug-app: set application <PACKAGE> to debug. Options are:\n" +
- " -w: wait for debugger when application starts\n" +
- " --persistent: retain this value\n" +
- "\n" +
- "am clear-debug-app: clear the previously set-debug-app.\n" +
- "\n" +
- "am bug-report: request bug report generation; will launch UI\n" +
- " when done to select where it should be delivered.\n" +
- "\n" +
- "am monitor: start monitoring for crashes or ANRs.\n" +
- " --gdb: start gdbserv on the given port at crash/ANR\n" +
- "\n" +
- "am screen-compat: control screen compatibility mode of <PACKAGE>.\n" +
- "\n" +
- "am to-uri: print the given Intent specification as a URI.\n" +
- "\n" +
- "am to-intent-uri: print the given Intent specification as an intent: URI.\n" +
- "\n" +
- "am switch-user: switch to put USER_ID in the foreground, starting\n" +
- " execution of that user if it is currently stopped.\n" +
- "\n" +
- "am stop-user: stop execution of USER_ID, not allowing it to run any\n" +
- " code until a later explicit switch to it.\n" +
- "\n" +
- "<INTENT> specifications include these flags and arguments:\n" +
- " [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" +
- " [-c <CATEGORY> [-c <CATEGORY>] ...]\n" +
- " [-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]\n" +
- " [--esn <EXTRA_KEY> ...]\n" +
- " [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]\n" +
- " [--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]\n" +
- " [--el <EXTRA_KEY> <EXTRA_LONG_VALUE> ...]\n" +
- " [--ef <EXTRA_KEY> <EXTRA_FLOAT_VALUE> ...]\n" +
- " [--eu <EXTRA_KEY> <EXTRA_URI_VALUE> ...]\n" +
- " [--ecn <EXTRA_KEY> <EXTRA_COMPONENT_NAME_VALUE>]\n" +
- " [--eia <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]\n" +
- " [--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]\n" +
- " [--efa <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]]\n" +
- " [-n <COMPONENT>] [-f <FLAGS>]\n" +
- " [--grant-read-uri-permission] [--grant-write-uri-permission]\n" +
- " [--debug-log-resolution] [--exclude-stopped-packages]\n" +
- " [--include-stopped-packages]\n" +
- " [--activity-brought-to-front] [--activity-clear-top]\n" +
- " [--activity-clear-when-task-reset] [--activity-exclude-from-recents]\n" +
- " [--activity-launched-from-history] [--activity-multiple-task]\n" +
- " [--activity-no-animation] [--activity-no-history]\n" +
- " [--activity-no-user-action] [--activity-previous-is-top]\n" +
- " [--activity-reorder-to-front] [--activity-reset-task-if-needed]\n" +
- " [--activity-single-top] [--activity-clear-task]\n" +
- " [--activity-task-on-home]\n" +
- " [--receiver-registered-only] [--receiver-replace-pending]\n" +
- " [--selector]\n" +
- " [<URI> | <PACKAGE> | <COMPONENT>]\n"
- );
- }
}
diff --git a/cmds/media/Android.mk b/cmds/media/Android.mk
new file mode 100644
index 0000000..b9451c5
--- /dev/null
+++ b/cmds/media/Android.mk
@@ -0,0 +1,15 @@
+# Copyright 2013 The Android Open Source Project
+#
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_MODULE := media_cmd
+include $(BUILD_JAVA_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := media
+LOCAL_SRC_FILES := media
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_PREBUILT)
diff --git a/cmds/media/MODULE_LICENSE_APACHE2 b/cmds/media/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cmds/media/MODULE_LICENSE_APACHE2
diff --git a/cmds/media/NOTICE b/cmds/media/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/cmds/media/NOTICE
@@ -0,0 +1,190 @@
+
+ Copyright (c) 2005-2008, The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
diff --git a/cmds/media/media b/cmds/media/media
new file mode 100755
index 0000000..1194442
--- /dev/null
+++ b/cmds/media/media
@@ -0,0 +1,6 @@
+# Script to start "media_cmd" on the device, which has a very rudimentary
+# shell.
+#
+base=/system
+export CLASSPATH=$base/framework/media_cmd.jar
+exec app_process $base/bin com.android.commands.media.Media "$@"
diff --git a/cmds/media/src/com/android/commands/media/Media.java b/cmds/media/src/com/android/commands/media/Media.java
new file mode 100644
index 0000000..56af7d6
--- /dev/null
+++ b/cmds/media/src/com/android/commands/media/Media.java
@@ -0,0 +1,220 @@
+/*
+**
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package com.android.commands.media;
+
+import android.app.PendingIntent;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.media.IAudioService;
+import android.media.IRemoteControlDisplay;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.util.AndroidException;
+import android.view.InputDevice;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
+import com.android.internal.os.BaseCommand;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+
+public class Media extends BaseCommand {
+
+ private IAudioService mAudioService;
+
+ /**
+ * Command-line entry point.
+ *
+ * @param args The command-line arguments
+ */
+ public static void main(String[] args) {
+ (new Media()).run(args);
+ }
+
+ public void onShowUsage(PrintStream out) {
+ out.println(
+ "usage: media [subcommand] [options]\n" +
+ " media dispatch KEY\n" +
+ " media remote-display\n" +
+ "\n" +
+ "media dispatch: dispatch a media key to the current media client.\n" +
+ " KEY may be: play, pause, play-pause, mute, headsethook,\n" +
+ " stop, next, previous, rewind, recordm fast-forword.\n" +
+ "media remote-display: monitor remote display updates.\n"
+ );
+ }
+
+ public void onRun() throws Exception {
+ mAudioService = IAudioService.Stub.asInterface(ServiceManager.checkService(
+ Context.AUDIO_SERVICE));
+ if (mAudioService == null) {
+ System.err.println(NO_SYSTEM_ERROR_CODE);
+ throw new AndroidException("Can't connect to audio service; is the system running?");
+ }
+
+ String op = nextArgRequired();
+
+ if (op.equals("dispatch")) {
+ runDispatch();
+ } else if (op.equals("remote-display")) {
+ runRemoteDisplay();
+ } else {
+ showError("Error: unknown command '" + op + "'");
+ return;
+ }
+ }
+
+ private void sendMediaKey(KeyEvent event) {
+ try {
+ mAudioService.dispatchMediaKeyEvent(event);
+ } catch (RemoteException e) {
+ }
+ }
+
+ private void runDispatch() throws Exception {
+ String cmd = nextArgRequired();
+ int keycode;
+ if ("play".equals(cmd)) {
+ keycode = KeyEvent.KEYCODE_MEDIA_PLAY;
+ } else if ("pause".equals(cmd)) {
+ keycode = KeyEvent.KEYCODE_MEDIA_PAUSE;
+ } else if ("play-pause".equals(cmd)) {
+ keycode = KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE;
+ } else if ("mute".equals(cmd)) {
+ keycode = KeyEvent.KEYCODE_MUTE;
+ } else if ("headsethook".equals(cmd)) {
+ keycode = KeyEvent.KEYCODE_HEADSETHOOK;
+ } else if ("stop".equals(cmd)) {
+ keycode = KeyEvent.KEYCODE_MEDIA_STOP;
+ } else if ("next".equals(cmd)) {
+ keycode = KeyEvent.KEYCODE_MEDIA_NEXT;
+ } else if ("previous".equals(cmd)) {
+ keycode = KeyEvent.KEYCODE_MEDIA_PREVIOUS;
+ } else if ("rewind".equals(cmd)) {
+ keycode = KeyEvent.KEYCODE_MEDIA_REWIND;
+ } else if ("record".equals(cmd)) {
+ keycode = KeyEvent.KEYCODE_MEDIA_RECORD;
+ } else if ("fast-forward".equals(cmd)) {
+ keycode = KeyEvent.KEYCODE_MEDIA_FAST_FORWARD;
+ } else {
+ showError("Error: unknown dispatch code '" + cmd + "'");
+ return;
+ }
+
+ final long now = SystemClock.uptimeMillis();
+ sendMediaKey(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keycode, 0, 0,
+ KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD));
+ sendMediaKey(new KeyEvent(now, now, KeyEvent.ACTION_UP, keycode, 0, 0,
+ KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD));
+ }
+
+ class RemoteDisplayMonitor extends IRemoteControlDisplay.Stub {
+ RemoteDisplayMonitor() {
+ }
+
+
+ @Override
+ public void setCurrentClientId(int clientGeneration, PendingIntent clientMediaIntent,
+ boolean clearing) {
+ System.out.println("New client: id=" + clientGeneration
+ + " intent=" + clientMediaIntent + " clearing=" + clearing);
+ }
+
+ @Override
+ public void setPlaybackState(int generationId, int state, long stateChangeTimeMs,
+ long currentPosMs, float speed) {
+ System.out.println("New state: id=" + generationId + " state=" + state
+ + " time=" + stateChangeTimeMs + " pos=" + currentPosMs + " speed=" + speed);
+ }
+
+ @Override
+ public void setTransportControlInfo(int generationId, int transportControlFlags,
+ int posCapabilities) {
+ System.out.println("New control info: id=" + generationId
+ + " flags=0x" + Integer.toHexString(transportControlFlags)
+ + " cap=0x" + Integer.toHexString(posCapabilities));
+ }
+
+ @Override
+ public void setMetadata(int generationId, Bundle metadata) {
+ System.out.println("New metadata: id=" + generationId
+ + " data=" + metadata);
+ }
+
+ @Override
+ public void setArtwork(int generationId, Bitmap artwork) {
+ System.out.println("New artwork: id=" + generationId
+ + " art=" + artwork);
+ }
+
+ @Override
+ public void setAllMetadata(int generationId, Bundle metadata, Bitmap artwork) {
+ System.out.println("New metadata+artwork: id=" + generationId
+ + " data=" + metadata + " art=" + artwork);
+ }
+
+ void printUsageMessage() {
+ System.out.println("Monitoring remote control displays... available commands:");
+ System.out.println("(q)uit: finish monitoring");
+ }
+
+ void run() throws RemoteException {
+ printUsageMessage();
+
+ mAudioService.registerRemoteControlDisplay(this, 0, 0);
+
+ try {
+ InputStreamReader converter = new InputStreamReader(System.in);
+ BufferedReader in = new BufferedReader(converter);
+ String line;
+
+ while ((line = in.readLine()) != null) {
+ boolean addNewline = true;
+ if (line.length() <= 0) {
+ addNewline = false;
+ } else if ("q".equals(line) || "quit".equals(line)) {
+ break;
+ } else {
+ System.out.println("Invalid command: " + line);
+ }
+
+ synchronized (this) {
+ if (addNewline) {
+ System.out.println("");
+ }
+ printUsageMessage();
+ }
+ }
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ mAudioService.unregisterRemoteControlDisplay(this);
+ }
+ }
+ }
+
+ private void runRemoteDisplay() throws Exception {
+ RemoteDisplayMonitor monitor = new RemoteDisplayMonitor();
+ monitor.run();
+ }
+}
diff --git a/cmds/wm/src/com/android/commands/wm/Wm.java b/cmds/wm/src/com/android/commands/wm/Wm.java
index 31eba96..815a0ac 100644
--- a/cmds/wm/src/com/android/commands/wm/Wm.java
+++ b/cmds/wm/src/com/android/commands/wm/Wm.java
@@ -26,21 +26,15 @@
import android.util.AndroidException;
import android.view.Display;
import android.view.IWindowManager;
+import com.android.internal.os.BaseCommand;
+import java.io.PrintStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-public class Wm {
+public class Wm extends BaseCommand {
private IWindowManager mWm;
- private String[] mArgs;
- private int mNextArg;
- private String mCurArgData;
-
- // 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.
@@ -48,23 +42,25 @@
* @param args The command-line arguments
*/
public static void main(String[] args) {
- try {
- (new Wm()).run(args);
- } catch (IllegalArgumentException e) {
- showUsage();
- System.err.println("Error: " + e.getMessage());
- } catch (Exception e) {
- e.printStackTrace(System.err);
- System.exit(1);
- }
+ (new Wm()).run(args);
}
- private void run(String[] args) throws Exception {
- if (args.length < 1) {
- showUsage();
- return;
- }
+ public void onShowUsage(PrintStream out) {
+ out.println(
+ "usage: wm [subcommand] [options]\n" +
+ " wm size [reset|WxH]\n" +
+ " wm density [reset|DENSITY]\n" +
+ " wm overscan [reset|LEFT,TOP,RIGHT,BOTTOM]\n" +
+ "\n" +
+ "wm size: return or override display size.\n" +
+ "\n" +
+ "wm density: override display density.\n" +
+ "\n" +
+ "wm overscan: set overscan area for display.\n"
+ );
+ }
+ public void onRun() throws Exception {
mWm = IWindowManager.Stub.asInterface(ServiceManager.checkService(
Context.WINDOW_SERVICE));
if (mWm == null) {
@@ -72,9 +68,7 @@
throw new AndroidException("Can't connect to window manager; is the system running?");
}
- mArgs = args;
- String op = args[0];
- mNextArg = 1;
+ String op = nextArgRequired();
if (op.equals("size")) {
runDisplaySize();
@@ -83,7 +77,8 @@
} else if (op.equals("overscan")) {
runDisplayOverscan();
} else {
- throw new IllegalArgumentException("Unknown command: " + op);
+ showError("Error: unknown command '" + op + "'");
+ return;
}
}
@@ -198,69 +193,4 @@
} catch (RemoteException e) {
}
}
-
- 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;
- }
- String arg = mArgs[mNextArg];
- if (!arg.startsWith("-")) {
- return null;
- }
- mNextArg++;
- if (arg.equals("--")) {
- return null;
- }
- if (arg.length() > 1 && arg.charAt(1) != '-') {
- if (arg.length() > 2) {
- mCurArgData = arg.substring(2);
- return arg.substring(0, 2);
- } else {
- mCurArgData = null;
- return arg;
- }
- }
- mCurArgData = null;
- return arg;
- }
-
- private String nextArg() {
- if (mCurArgData != null) {
- String arg = mCurArgData;
- mCurArgData = null;
- return arg;
- } else if (mNextArg < mArgs.length) {
- return mArgs[mNextArg++];
- } else {
- return null;
- }
- }
-
- private String nextArgRequired() {
- String arg = nextArg();
- if (arg == null) {
- String prev = mArgs[mNextArg - 1];
- throw new IllegalArgumentException("Argument expected after \"" + prev + "\"");
- }
- return arg;
- }
-
- private static void showUsage() {
- System.err.println(
- "usage: wm [subcommand] [options]\n" +
- " wm size [reset|WxH]\n" +
- " wm density [reset|DENSITY]\n" +
- " wm overscan [reset|LEFT,TOP,RIGHT,BOTTOM]\n" +
- "\n" +
- "wm size: return or override display size.\n" +
- "\n" +
- "wm density: override display density.\n" +
- "\n" +
- "wm overscan: set overscan area for display.\n"
- );
- }
}
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 66083c8..367d576 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -3796,50 +3796,11 @@
* Columns in the Data_Usage_Stat table
*/
protected interface DataUsageStatColumns {
- /** What the referenced {@link Data} was used for.
- * @see DataUsageStatColumns#USAGE_TYPE_CALL
- * @see DataUsageStatColumns#USAGE_TYPE_LONG_TEXT
- * @see DataUsageStatColumns#USAGE_TYPE_SHORT_TEXT
- */
- public static final String USAGE_TYPE = "usage_type";
-
/** The last time (in milliseconds) this {@link Data} was used. */
public static final String LAST_TIME_USED = "last_time_used";
- /** The number of times the referenced {@link Data} has been used for the purpose described
- * in {@link DataUsageStatColumns#USAGE_TYPE}.
- */
+ /** The number of times the referenced {@link Data} has been used. */
public static final String TIMES_USED = "times_used";
-
- /**
- * Integer value for USAGE_TYPE.
- * This type of usage refers to voice interaction, which includes phone calls, voice chat,
- * and video chat.
- *
- * @see DataUsageFeedback#USAGE_TYPE
- * @see DataUsageStatColumns#USAGE_TYPE
- */
- public static final int USAGE_TYPE_CALL = 0;
-
- /**
- * Integer value for USAGE_TYPE.
- * This type of usage refers to text interaction involving longer messages, which includes
- * email.
- *
- * @see DataUsageFeedback#USAGE_TYPE
- * @see DataUsageStatColumns#USAGE_TYPE
- */
- public static final int USAGE_TYPE_LONG_TEXT = 1;
-
- /**
- * Integer value for USAGE_TYPE.
- * This type of usage for text interaction involving shorter messages, which includes SMS
- * and text chat with email addresses.
- *
- * @see DataUsageFeedback#USAGE_TYPE
- * @see DataUsageStatColumns#USAGE_TYPE
- */
- public static final int USAGE_TYPE_SHORT_TEXT = 2;
}
/**
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index a520e17..7c82f7e 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -14060,6 +14060,10 @@
* managed: remove them when they should not be displayed anymore. The
* overlay will always have the same size as its host view.
*
+ * <p>Note: Overlays do not currently work correctly with {@link
+ * SurfaceView} or {@link TextureView}; contents in overlays for these
+ * types of views may not display correctly.</p>
+ *
* @return The ViewOverlay object for this view.
* @see ViewOverlay
*/
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index c07191a..311d1d0 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -2975,6 +2975,10 @@
* representation of a view in a parent container, such as might be used
* by an animation effect.
*
+ * <p>Note: Overlays do not currently work correctly with {@link
+ * SurfaceView} or {@link TextureView}; contents in overlays for these
+ * types of views may not display correctly.</p>
+ *
* @return The ViewGroupOverlay object for this view.
* @see ViewGroupOverlay
*/
diff --git a/core/java/android/webkit/HTML5Audio.java b/core/java/android/webkit/HTML5Audio.java
index 684ec07..17eb2df 100644
--- a/core/java/android/webkit/HTML5Audio.java
+++ b/core/java/android/webkit/HTML5Audio.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
+import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -84,6 +85,7 @@
// See http://www.whatwg.org/specs/web-apps/current-work/#event-media-timeupdate
private Timer mTimer;
private final class TimeupdateTask extends TimerTask {
+ @Override
public void run() {
HTML5Audio.this.obtainMessage(TIMEUPDATE).sendToTarget();
}
@@ -139,11 +141,13 @@
// (i.e. the webviewcore thread here)
// MediaPlayer.OnBufferingUpdateListener
+ @Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
nativeOnBuffering(percent, mNativePointer);
}
// MediaPlayer.OnCompletionListener;
+ @Override
public void onCompletion(MediaPlayer mp) {
mState = COMPLETE;
mProcessingOnEnd = true;
@@ -156,6 +160,7 @@
}
// MediaPlayer.OnErrorListener
+ @Override
public boolean onError(MediaPlayer mp, int what, int extra) {
mState = ERROR;
resetMediaPlayer();
@@ -164,6 +169,7 @@
}
// MediaPlayer.OnPreparedListener
+ @Override
public void onPrepared(MediaPlayer mp) {
mState = PREPARED;
if (mTimer != null) {
@@ -178,6 +184,7 @@
}
// MediaPlayer.OnSeekCompleteListener
+ @Override
public void onSeekComplete(MediaPlayer mp) {
nativeOnTimeupdate(mp.getCurrentPosition(), mNativePointer);
}
@@ -231,7 +238,7 @@
headers.put(HIDE_URL_LOGS, "true");
}
- mMediaPlayer.setDataSource(url, headers);
+ mMediaPlayer.setDataSource(mContext, Uri.parse(url), headers);
mState = INITIALIZED;
mMediaPlayer.prepareAsync();
} catch (IOException e) {
diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java
index 589a358..34cfea5 100644
--- a/core/java/android/widget/AppSecurityPermissions.java
+++ b/core/java/android/widget/AppSecurityPermissions.java
@@ -244,11 +244,11 @@
public void onClick(DialogInterface dialog, int which) {
PackageManager pm = getContext().getPackageManager();
pm.revokePermission(mPackageName, mPerm.name);
- PermissionItemView.this.setVisibility(View.INVISIBLE);
+ PermissionItemView.this.setVisibility(View.GONE);
}
};
- builder.setNegativeButton(R.string.cancel, null);
- builder.setPositiveButton(R.string.revoke, ocl);
+ builder.setNegativeButton(R.string.revoke, ocl);
+ builder.setPositiveButton(R.string.ok, null);
}
}
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 4b62c2d..c7914f3 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -2433,7 +2433,7 @@
mFirstPosition;
} else {
final int lastPos = mFirstPosition + getChildCount() - 1;
- nextSelected = selectedPos != INVALID_POSITION && selectedPos < lastPos?
+ nextSelected = selectedPos != INVALID_POSITION && selectedPos <= lastPos ?
selectedPos - 1 :
lastPos;
}
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index 529de2e..3df7258 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -220,28 +220,29 @@
// with MeasureSpec value overflow and RelativeLayout was one source of them.
// Some apps came to rely on them. :(
private boolean mAllowBrokenMeasureSpecs = false;
+ // Compatibility hack. Old versions of the platform would not take
+ // margins and padding into account when generating the height measure spec
+ // for children during the horizontal measure pass.
+ private boolean mMeasureVerticalWithPaddingMargin = false;
// A default width used for RTL measure pass
- private static int DEFAULT_WIDTH = Integer.MAX_VALUE / 2;
+ private static final int DEFAULT_WIDTH = Integer.MAX_VALUE / 2;
public RelativeLayout(Context context) {
super(context);
- mAllowBrokenMeasureSpecs = context.getApplicationInfo().targetSdkVersion <=
- Build.VERSION_CODES.JELLY_BEAN_MR1;
+ queryCompatibilityModes(context);
}
public RelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
initFromAttributes(context, attrs);
- mAllowBrokenMeasureSpecs = context.getApplicationInfo().targetSdkVersion <=
- Build.VERSION_CODES.JELLY_BEAN_MR1;
+ queryCompatibilityModes(context);
}
public RelativeLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initFromAttributes(context, attrs);
- mAllowBrokenMeasureSpecs = context.getApplicationInfo().targetSdkVersion <=
- Build.VERSION_CODES.JELLY_BEAN_MR1;
+ queryCompatibilityModes(context);
}
private void initFromAttributes(Context context, AttributeSet attrs) {
@@ -251,6 +252,12 @@
a.recycle();
}
+ private void queryCompatibilityModes(Context context) {
+ int version = context.getApplicationInfo().targetSdkVersion;
+ mAllowBrokenMeasureSpecs = version <= Build.VERSION_CODES.JELLY_BEAN_MR1;
+ mMeasureVerticalWithPaddingMargin = version >= Build.VERSION_CODES.JELLY_BEAN_MR2;
+ }
+
@Override
public boolean shouldDelayChildPressedState() {
return false;
@@ -692,6 +699,11 @@
params.leftMargin, params.rightMargin,
mPaddingLeft, mPaddingRight,
myWidth);
+ int maxHeight = myHeight;
+ if (mMeasureVerticalWithPaddingMargin) {
+ maxHeight = Math.max(0, myHeight - mPaddingTop - mPaddingBottom -
+ params.topMargin - params.bottomMargin);
+ }
int childHeightMeasureSpec;
if (myHeight < 0 && !mAllowBrokenMeasureSpecs) {
if (params.height >= 0) {
@@ -704,9 +716,9 @@
childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
}
} else if (params.width == LayoutParams.MATCH_PARENT) {
- childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(myHeight, MeasureSpec.EXACTLY);
+ childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.EXACTLY);
} else {
- childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(myHeight, MeasureSpec.AT_MOST);
+ childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST);
}
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
diff --git a/core/java/com/android/internal/os/BaseCommand.java b/core/java/com/android/internal/os/BaseCommand.java
new file mode 100644
index 0000000..e26b27d
--- /dev/null
+++ b/core/java/com/android/internal/os/BaseCommand.java
@@ -0,0 +1,146 @@
+/*
+**
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package com.android.internal.os;
+
+import java.io.PrintStream;
+
+public abstract class BaseCommand {
+
+ protected String[] mArgs;
+ private int mNextArg;
+ private String mCurArgData;
+
+ // These are magic strings understood by the Eclipse plugin.
+ public static final String FATAL_ERROR_CODE = "Error type 1";
+ public static final String NO_SYSTEM_ERROR_CODE = "Error type 2";
+ public static final String NO_CLASS_ERROR_CODE = "Error type 3";
+
+ /**
+ * Call to run the command.
+ */
+ public void run(String[] args) {
+ if (args.length < 1) {
+ onShowUsage(System.out);
+ return;
+ }
+
+ mArgs = args;
+ mNextArg = 0;
+ mCurArgData = null;
+
+ try {
+ onRun();
+ } catch (IllegalArgumentException e) {
+ onShowUsage(System.err);
+ System.err.println();
+ System.err.println("Error: " + e.getMessage());
+ } catch (Exception e) {
+ e.printStackTrace(System.err);
+ System.exit(1);
+ }
+ }
+
+ /**
+ * Convenience to show usage information to error output.
+ */
+ public void showUsage() {
+ onShowUsage(System.err);
+ }
+
+ /**
+ * Convenience to show usage information to error output along
+ * with an error message.
+ */
+ public void showError(String message) {
+ onShowUsage(System.err);
+ System.err.println();
+ System.err.println(message);
+ }
+
+ /**
+ * Implement the command.
+ */
+ public abstract void onRun() throws Exception;
+
+ /**
+ * Print help text for the command.
+ */
+ public abstract void onShowUsage(PrintStream out);
+
+ /**
+ * Return the next option on the command line -- that is an argument that
+ * starts with '-'. If the next argument is not an option, null is returned.
+ */
+ public String nextOption() {
+ if (mCurArgData != null) {
+ String prev = mArgs[mNextArg - 1];
+ throw new IllegalArgumentException("No argument expected after \"" + prev + "\"");
+ }
+ if (mNextArg >= mArgs.length) {
+ return null;
+ }
+ String arg = mArgs[mNextArg];
+ if (!arg.startsWith("-")) {
+ return null;
+ }
+ mNextArg++;
+ if (arg.equals("--")) {
+ return null;
+ }
+ if (arg.length() > 1 && arg.charAt(1) != '-') {
+ if (arg.length() > 2) {
+ mCurArgData = arg.substring(2);
+ return arg.substring(0, 2);
+ } else {
+ mCurArgData = null;
+ return arg;
+ }
+ }
+ mCurArgData = null;
+ return arg;
+ }
+
+ /**
+ * Return the next argument on the command line, whatever it is; if there are
+ * no arguments left, return null.
+ */
+ public String nextArg() {
+ if (mCurArgData != null) {
+ String arg = mCurArgData;
+ mCurArgData = null;
+ return arg;
+ } else if (mNextArg < mArgs.length) {
+ return mArgs[mNextArg++];
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Return the next argument on the command line, whatever it is; if there are
+ * no arguments left, throws an IllegalArgumentException to report this to the user.
+ */
+ public String nextArgRequired() {
+ String arg = nextArg();
+ if (arg == null) {
+ String prev = mArgs[mNextArg - 1];
+ throw new IllegalArgumentException("Argument expected after \"" + prev + "\"");
+ }
+ return arg;
+ }
+}
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 1995670..a0e1603 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2997,11 +2997,11 @@
<!-- [CHAR LIMIT=NONE] Stub notification title for an app running a service that has provided
a bad bad notification for itself. -->
<string name="app_running_notification_title"><xliff:g id="app_name">%1$s</xliff:g>
- running</string>
+ is running</string>
<!-- [CHAR LIMIT=NONE] Stub notification text for an app running a service that has provided
a bad bad notification for itself. -->
- <string name="app_running_notification_text"><xliff:g id="app_name">%1$s</xliff:g>
- is currently running</string>
+ <string name="app_running_notification_text">Touch for more information
+ or to stop the app.</string>
<!-- Preference framework strings. -->
<string name="ok">OK</string>
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index b80a166..917a47d 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -50,6 +50,7 @@
private long mVolumeKeyUpTime;
private final boolean mUseMasterVolume;
private final boolean mUseVolumeKeySounds;
+ private final Binder mToken = new Binder();
private static String TAG = "AudioManager";
/**
@@ -2075,7 +2076,8 @@
IAudioService service = getService();
try {
// pi != null
- service.registerMediaButtonIntent(pi, eventReceiver);
+ service.registerMediaButtonIntent(pi, eventReceiver,
+ eventReceiver == null ? mToken : null);
} catch (RemoteException e) {
Log.e(TAG, "Dead object in registerMediaButtonIntent"+e);
}
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index b22aa1d..773d7b6 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -530,6 +530,9 @@
// Register for package removal intent broadcasts for media button receiver persistence
IntentFilter pkgFilter = new IntentFilter();
pkgFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ pkgFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
+ pkgFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+ pkgFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
pkgFilter.addDataScheme("package");
context.registerReceiver(mReceiver, pkgFilter);
@@ -4033,14 +4036,21 @@
0,
null,
SAFE_VOLUME_CONFIGURE_TIMEOUT_MS);
- } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)) {
+ } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)
+ || action.equals(Intent.ACTION_PACKAGE_DATA_CLEARED)) {
if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
// a package is being removed, not replaced
String packageName = intent.getData().getSchemeSpecificPart();
if (packageName != null) {
- removeMediaButtonReceiverForPackage(packageName);
+ cleanupMediaButtonReceiverForPackage(packageName, true);
}
}
+ } else if (action.equals(Intent.ACTION_PACKAGE_ADDED)
+ || action.equals(Intent.ACTION_PACKAGE_CHANGED)) {
+ String packageName = intent.getData().getSchemeSpecificPart();
+ if (packageName != null) {
+ cleanupMediaButtonReceiverForPackage(packageName, false);
+ }
} else if (action.equals(Intent.ACTION_SCREEN_ON)) {
AudioSystem.setParameters("screen_state=on");
} else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
@@ -4847,8 +4857,9 @@
}
}
- private static class RemoteControlStackEntry {
+ private static class RemoteControlStackEntry implements DeathRecipient {
public int mRccId = RemoteControlClient.RCSE_ID_UNREGISTERED;
+ final public AudioService mService;
/**
* The target for the ACTION_MEDIA_BUTTON events.
* Always non null.
@@ -4859,6 +4870,7 @@
* Always non null.
*/
final public ComponentName mReceiverComponent;
+ public IBinder mToken;
public String mCallingPackageName;
public int mCallingUid;
/**
@@ -4889,9 +4901,12 @@
}
/** precondition: mediaIntent != null */
- public RemoteControlStackEntry(PendingIntent mediaIntent, ComponentName eventReceiver) {
+ public RemoteControlStackEntry(AudioService service, PendingIntent mediaIntent,
+ ComponentName eventReceiver, IBinder token) {
+ mService = service;
mMediaIntent = mediaIntent;
mReceiverComponent = eventReceiver;
+ mToken = token;
mCallingUid = -1;
mRcClient = null;
mRccId = ++sLastRccId;
@@ -4901,6 +4916,17 @@
RemoteControlClient.PLAYBACK_SPEED_1X);
resetPlaybackInfo();
+ if (mToken != null) {
+ try {
+ mToken.linkToDeath(this, 0);
+ } catch (RemoteException e) {
+ mService.mAudioHandler.post(new Runnable() {
+ @Override public void run() {
+ mService.unregisterMediaButtonIntent(mMediaIntent);
+ }
+ });
+ }
+ }
}
public void unlinkToRcClientDeath() {
@@ -4916,9 +4942,22 @@
}
}
+ public void destroy() {
+ unlinkToRcClientDeath();
+ if (mToken != null) {
+ mToken.unlinkToDeath(this, 0);
+ mToken = null;
+ }
+ }
+
+ @Override
+ public void binderDied() {
+ mService.unregisterMediaButtonIntent(mMediaIntent);
+ }
+
@Override
protected void finalize() throws Throwable {
- unlinkToRcClientDeath();// unlink exception handled inside method
+ destroy(); // unlink exception handled inside method
super.finalize();
}
}
@@ -5017,11 +5056,12 @@
* Remove any entry in the remote control stack that has the same package name as packageName
* Pre-condition: packageName != null
*/
- private void removeMediaButtonReceiverForPackage(String packageName) {
+ private void cleanupMediaButtonReceiverForPackage(String packageName, boolean removeAll) {
synchronized(mRCStack) {
if (mRCStack.empty()) {
return;
} else {
+ final PackageManager pm = mContext.getPackageManager();
RemoteControlStackEntry oldTop = mRCStack.peek();
Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator();
// iterate over the stack entries
@@ -5029,10 +5069,19 @@
// evaluated it, traversal order doesn't matter here)
while(stackIterator.hasNext()) {
RemoteControlStackEntry rcse = (RemoteControlStackEntry)stackIterator.next();
- if (packageName.equals(rcse.mMediaIntent.getCreatorPackage())) {
+ if (removeAll && packageName.equals(rcse.mMediaIntent.getCreatorPackage())) {
// a stack entry is from the package being removed, remove it from the stack
stackIterator.remove();
- rcse.unlinkToRcClientDeath();
+ rcse.destroy();
+ } else if (rcse.mReceiverComponent != null) {
+ try {
+ // Check to see if this receiver still exists.
+ pm.getReceiverInfo(rcse.mReceiverComponent, 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ // Not found -- remove it!
+ stackIterator.remove();
+ rcse.destroy();
+ }
}
}
if (mRCStack.empty()) {
@@ -5075,7 +5124,7 @@
mediaButtonIntent.setComponent(eventReceiver);
PendingIntent pi = PendingIntent.getBroadcast(mContext,
0/*requestCode, ignored*/, mediaButtonIntent, 0/*flags*/);
- registerMediaButtonIntent(pi, eventReceiver);
+ registerMediaButtonIntent(pi, eventReceiver, null);
}
}
@@ -5085,7 +5134,8 @@
* Called synchronized on mAudioFocusLock, then mRCStack
* precondition: mediaIntent != null
*/
- private void pushMediaButtonReceiver_syncAfRcs(PendingIntent mediaIntent, ComponentName target) {
+ private void pushMediaButtonReceiver_syncAfRcs(PendingIntent mediaIntent, ComponentName target,
+ IBinder token) {
// already at top of stack?
if (!mRCStack.empty() && mRCStack.peek().mMediaIntent.equals(mediaIntent)) {
return;
@@ -5107,7 +5157,7 @@
Log.e(TAG, "Wrong index accessing media button stack, lock error? ", e);
}
if (!wasInsideStack) {
- rcse = new RemoteControlStackEntry(mediaIntent, target);
+ rcse = new RemoteControlStackEntry(this, mediaIntent, target, token);
}
mRCStack.push(rcse); // rcse is never null
@@ -5129,7 +5179,7 @@
for (int index = mRCStack.size()-1; index >= 0; index--) {
final RemoteControlStackEntry rcse = mRCStack.elementAt(index);
if (rcse.mMediaIntent.equals(pi)) {
- rcse.unlinkToRcClientDeath();
+ rcse.destroy();
// ok to remove element while traversing the stack since we're leaving the loop
mRCStack.removeElementAt(index);
break;
@@ -5417,12 +5467,13 @@
* see AudioManager.registerMediaButtonIntent(PendingIntent pi, ComponentName c)
* precondition: mediaIntent != null
*/
- public void registerMediaButtonIntent(PendingIntent mediaIntent, ComponentName eventReceiver) {
+ public void registerMediaButtonIntent(PendingIntent mediaIntent, ComponentName eventReceiver,
+ IBinder token) {
Log.i(TAG, " Remote Control registerMediaButtonIntent() for " + mediaIntent);
synchronized(mAudioFocusLock) {
synchronized(mRCStack) {
- pushMediaButtonReceiver_syncAfRcs(mediaIntent, eventReceiver);
+ pushMediaButtonReceiver_syncAfRcs(mediaIntent, eventReceiver, token);
// new RC client, assume every type of information shall be queried
checkUpdateRemoteControlDisplay_syncAfRcs(RC_INFO_ALL);
}
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 25aae8f..13f6c02 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -120,7 +120,7 @@
oneway void dispatchMediaKeyEvent(in KeyEvent keyEvent);
void dispatchMediaKeyEventUnderWakelock(in KeyEvent keyEvent);
- void registerMediaButtonIntent(in PendingIntent pi, in ComponentName c);
+ void registerMediaButtonIntent(in PendingIntent pi, in ComponentName c, IBinder token);
oneway void unregisterMediaButtonIntent(in PendingIntent pi);
oneway void registerMediaButtonEventReceiverForCalls(in ComponentName c);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 52f552b..c2dc159 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -708,6 +708,7 @@
private View.OnClickListener mRecentsClickListener = new View.OnClickListener() {
public void onClick(View v) {
+ awakenDreams();
toggleRecentApps();
}
};
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 49460de..5f9e921 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -59,6 +59,8 @@
import android.os.UserHandle;
import android.os.Vibrator;
import android.provider.Settings;
+import android.service.dreams.DreamService;
+import android.service.dreams.IDreamManager;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
@@ -1801,7 +1803,23 @@
? com.android.internal.R.anim.lock_screen_wallpaper_behind_enter
: com.android.internal.R.anim.lock_screen_behind_enter);
}
-
+
+ private static void awakenDreams() {
+ IDreamManager dreamManager = getDreamManager();
+ if (dreamManager != null) {
+ try {
+ dreamManager.awaken();
+ } catch (RemoteException e) {
+ // fine, stay asleep then
+ }
+ }
+ }
+
+ static IDreamManager getDreamManager() {
+ return IDreamManager.Stub.asInterface(
+ ServiceManager.checkService(DreamService.DREAM_SERVICE));
+ }
+
static ITelephony getTelephonyService() {
return ITelephony.Stub.asInterface(
ServiceManager.checkService(Context.TELEPHONY_SERVICE));
@@ -4550,6 +4568,7 @@
}
void startDockOrHome() {
+ awakenDreams();
// We don't have dock home anymore. Home is home. If you lived here, you'd be home by now.
mContext.startActivityAsUser(mHomeIntent, UserHandle.CURRENT);
}
diff --git a/services/java/com/android/server/EventLogTags.logtags b/services/java/com/android/server/EventLogTags.logtags
index 8bc2da2..59577ad 100644
--- a/services/java/com/android/server/EventLogTags.logtags
+++ b/services/java/com/android/server/EventLogTags.logtags
@@ -157,3 +157,8 @@
# ConfigUpdateInstallReceiver.java
# ---------------------------
51300 config_install_failed (dir|3)
+
+# ---------------------------
+# IntentFirewall.java
+# ---------------------------
+51400 ifw_intent_matched (Intent Type|1|5),(Component Name|3),(Caller Uid|1|5),(Caller Pkg Count|1|1),(Caller Pkgs|3),(Action|3),(MIME Type|3),(URI|3),(Flags|1|5)
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 3d7da7b..3d2e912 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -2594,8 +2594,7 @@
}
boolean abort = !mService.mIntentFirewall.checkStartActivity(intent,
- callerApp==null?null:callerApp.info, callingPackage, callingUid, callingPid,
- resolvedType, aInfo);
+ callerApp==null?null:callerApp.info, callingUid, callingPid, resolvedType, aInfo);
if (mMainStack) {
if (mService.mController != null) {
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index 8ff1c7d..fccaab5 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -376,37 +376,37 @@
// icon, but this used to be able to slip through, so for
// those dirty apps give it the app's icon.
foregroundNoti.icon = appInfo.icon;
- if (foregroundNoti.contentView == null) {
- // In this case the app may not have specified a
- // content view... so we'll give them something to show.
- CharSequence appName = appInfo.loadLabel(
- ams.mContext.getPackageManager());
- if (appName == null) {
- appName = appInfo.packageName;
- }
- Context ctx = null;
- try {
- ctx = ams.mContext.createPackageContext(
- appInfo.packageName, 0);
- Intent runningIntent = new Intent(
- Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
- runningIntent.setData(Uri.fromParts("package",
- appInfo.packageName, null));
- PendingIntent pi = PendingIntent.getActivity(ams.mContext, 0,
- runningIntent, PendingIntent.FLAG_UPDATE_CURRENT);
- foregroundNoti.setLatestEventInfo(ctx,
- ams.mContext.getString(
- com.android.internal.R.string
- .app_running_notification_title,
- appName),
- ams.mContext.getString(
- com.android.internal.R.string
- .app_running_notification_text,
- appName),
- pi);
- } catch (PackageManager.NameNotFoundException e) {
- foregroundNoti.icon = 0;
- }
+
+ // Do not allow apps to present a sneaky invisible content view either.
+ foregroundNoti.contentView = null;
+ foregroundNoti.bigContentView = null;
+ CharSequence appName = appInfo.loadLabel(
+ ams.mContext.getPackageManager());
+ if (appName == null) {
+ appName = appInfo.packageName;
+ }
+ Context ctx = null;
+ try {
+ ctx = ams.mContext.createPackageContext(
+ appInfo.packageName, 0);
+ Intent runningIntent = new Intent(
+ Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+ runningIntent.setData(Uri.fromParts("package",
+ appInfo.packageName, null));
+ PendingIntent pi = PendingIntent.getActivity(ams.mContext, 0,
+ runningIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+ foregroundNoti.setLatestEventInfo(ctx,
+ ams.mContext.getString(
+ com.android.internal.R.string
+ .app_running_notification_title,
+ appName),
+ ams.mContext.getString(
+ com.android.internal.R.string
+ .app_running_notification_text,
+ appName),
+ pi);
+ } catch (PackageManager.NameNotFoundException e) {
+ foregroundNoti.icon = 0;
}
}
if (foregroundNoti.icon == 0) {
diff --git a/services/java/com/android/server/firewall/AndFilter.java b/services/java/com/android/server/firewall/AndFilter.java
index cabf00b..e4276d0 100644
--- a/services/java/com/android/server/firewall/AndFilter.java
+++ b/services/java/com/android/server/firewall/AndFilter.java
@@ -26,11 +26,10 @@
class AndFilter extends FilterList {
@Override
public boolean matches(IntentFirewall ifw, Intent intent, ApplicationInfo callerApp,
- String callerPackage, int callerUid, int callerPid, String resolvedType,
- ApplicationInfo resolvedApp) {
+ int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
for (int i=0; i<children.size(); i++) {
- if (!children.get(i).matches(ifw, intent, callerApp, callerPackage, callerUid,
- callerPid, resolvedType, resolvedApp)) {
+ if (!children.get(i).matches(ifw, intent, callerApp, callerUid, callerPid, resolvedType,
+ resolvedApp)) {
return false;
}
}
diff --git a/services/java/com/android/server/firewall/CategoryFilter.java b/services/java/com/android/server/firewall/CategoryFilter.java
index d5e9fe8..4938cb8 100644
--- a/services/java/com/android/server/firewall/CategoryFilter.java
+++ b/services/java/com/android/server/firewall/CategoryFilter.java
@@ -34,7 +34,7 @@
}
@Override
- public boolean matches(IntentFirewall ifw, Intent intent, ApplicationInfo callerApp, String callerPackage,
+ public boolean matches(IntentFirewall ifw, Intent intent, ApplicationInfo callerApp,
int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
Set<String> categories = intent.getCategories();
if (categories == null) {
diff --git a/services/java/com/android/server/firewall/Filter.java b/services/java/com/android/server/firewall/Filter.java
index 7639466..0e783e8 100644
--- a/services/java/com/android/server/firewall/Filter.java
+++ b/services/java/com/android/server/firewall/Filter.java
@@ -26,17 +26,14 @@
* @param ifw The IntentFirewall instance
* @param intent The intent being started/bound/broadcast
* @param callerApp An ApplicationInfo of an application in the caller's process. This may not
- * be the specific app that is actually sending the intent. This also may be
- * null, if the caller is the system process, or an unrecognized process (e.g.
- * am start)
- * @param callerPackage The package name of the component sending the intent. This value is
-* provided by the caller and might be forged/faked.
+ * be the specific app that is actually sending the intent. This also may be
+ * null, if the caller is the system process, or an unrecognized process (e.g.
+ * am start)
* @param callerUid
* @param callerPid
* @param resolvedType The resolved mime type of the intent
* @param resolvedApp The application that contains the resolved component that the intent is
*/
boolean matches(IntentFirewall ifw, Intent intent, ApplicationInfo callerApp,
- String callerPackage, int callerUid, int callerPid, String resolvedType,
- ApplicationInfo resolvedApp);
+ int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp);
}
diff --git a/services/java/com/android/server/firewall/IntentFirewall.java b/services/java/com/android/server/firewall/IntentFirewall.java
index 062183b..08e6b45 100644
--- a/services/java/com/android/server/firewall/IntentFirewall.java
+++ b/services/java/com/android/server/firewall/IntentFirewall.java
@@ -16,18 +16,21 @@
package com.android.server.firewall;
+import android.app.AppGlobals;
+import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.os.Environment;
-import android.os.ServiceManager;
+import android.os.RemoteException;
import android.util.Slog;
import android.util.Xml;
import com.android.internal.util.XmlUtils;
+import com.android.server.EventLogTags;
import com.android.server.IntentResolver;
-import com.android.server.pm.PackageManagerService;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -46,11 +49,18 @@
private static final File RULES_FILE =
new File(Environment.getSystemSecureDirectory(), "ifw/ifw.xml");
+ private static final int LOG_PACKAGES_MAX_LENGTH = 150;
+ private static final int LOG_PACKAGES_SUFFICIENT_LENGTH = 125;
+
private static final String TAG_RULES = "rules";
private static final String TAG_ACTIVITY = "activity";
private static final String TAG_SERVICE = "service";
private static final String TAG_BROADCAST = "broadcast";
+ private static final int TYPE_ACTIVITY = 0;
+ private static final int TYPE_SERVICE = 1;
+ private static final int TYPE_BROADCAST = 2;
+
private static final HashMap<String, FilterFactory> factoryMap;
private final AMSInterface mAms;
@@ -76,7 +86,6 @@
StringFilter.HOST,
StringFilter.MIME_TYPE,
StringFilter.PATH,
- StringFilter.SENDER_PACKAGE,
StringFilter.SSP,
CategoryFilter.FACTORY,
@@ -98,17 +107,16 @@
readRules(getRulesFile());
}
- public boolean checkStartActivity(Intent intent, ApplicationInfo callerApp,
- String callerPackage, int callerUid, int callerPid, String resolvedType,
- ActivityInfo resolvedActivity) {
+ public boolean checkStartActivity(Intent intent, ApplicationInfo callerApp, int callerUid,
+ int callerPid, String resolvedType, ActivityInfo resolvedActivity) {
List<Rule> matchingRules = mActivityResolver.queryIntent(intent, resolvedType, false, 0);
boolean log = false;
boolean block = false;
for (int i=0; i< matchingRules.size(); i++) {
Rule rule = matchingRules.get(i);
- if (rule.matches(this, intent, callerApp, callerPackage, callerUid, callerPid,
- resolvedType, resolvedActivity.applicationInfo)) {
+ if (rule.matches(this, intent, callerApp, callerUid, callerPid, resolvedType,
+ resolvedActivity.applicationInfo)) {
block |= rule.getBlock();
log |= rule.getLog();
@@ -121,12 +129,81 @@
}
if (log) {
- // TODO: log info about intent to event log
+ logIntent(TYPE_ACTIVITY, intent, callerUid, resolvedType);
}
return !block;
}
+ private static void logIntent(int intentType, Intent intent, int callerUid,
+ String resolvedType) {
+ // The component shouldn't be null, but let's double check just to be safe
+ ComponentName cn = intent.getComponent();
+ String shortComponent = null;
+ if (cn != null) {
+ shortComponent = cn.flattenToShortString();
+ }
+
+ String callerPackages = null;
+ int callerPackageCount = 0;
+ IPackageManager pm = AppGlobals.getPackageManager();
+ if (pm != null) {
+ try {
+ String[] callerPackagesArray = pm.getPackagesForUid(callerUid);
+ if (callerPackagesArray != null) {
+ callerPackageCount = callerPackagesArray.length;
+ callerPackages = joinPackages(callerPackagesArray);
+ }
+ } catch (RemoteException ex) {
+ Slog.e(TAG, "Remote exception while retrieving packages", ex);
+ }
+ }
+
+ EventLogTags.writeIfwIntentMatched(intentType, shortComponent, callerUid,
+ callerPackageCount, callerPackages, intent.getAction(), resolvedType,
+ intent.getDataString(), intent.getFlags());
+ }
+
+ /**
+ * Joins a list of package names such that the resulting string is no more than
+ * LOG_PACKAGES_MAX_LENGTH.
+ *
+ * Only full package names will be added to the result, unless every package is longer than the
+ * limit, in which case one of the packages will be truncated and added. In this case, an
+ * additional '-' character will be added to the end of the string, to denote the truncation.
+ *
+ * If it encounters a package that won't fit in the remaining space, it will continue on to the
+ * next package, unless the total length of the built string so far is greater than
+ * LOG_PACKAGES_SUFFICIENT_LENGTH, in which case it will stop and return what it has.
+ */
+ private static String joinPackages(String[] packages) {
+ boolean first = true;
+ StringBuilder sb = new StringBuilder();
+ for (int i=0; i<packages.length; i++) {
+ String pkg = packages[i];
+
+ // + 1 length for the comma. This logic technically isn't correct for the first entry,
+ // but it's not critical.
+ if (sb.length() + pkg.length() + 1 < LOG_PACKAGES_MAX_LENGTH) {
+ if (!first) {
+ sb.append(',');
+ } else {
+ first = false;
+ }
+ sb.append(pkg);
+ } else if (sb.length() >= LOG_PACKAGES_SUFFICIENT_LENGTH) {
+ return sb.toString();
+ }
+ }
+ if (sb.length() == 0 && packages.length > 0) {
+ String pkg = packages[0];
+ // truncating from the end - the last part of the package name is more likely to be
+ // interesting/unique
+ return pkg.substring(pkg.length() - LOG_PACKAGES_MAX_LENGTH + 1) + '-';
+ }
+ return null;
+ }
+
public static File getRulesFile() {
return RULES_FILE;
}
@@ -313,7 +390,12 @@
}
boolean signaturesMatch(int uid1, int uid2) {
- PackageManagerService pm = (PackageManagerService)ServiceManager.getService("package");
- return pm.checkUidSignatures(uid1, uid2) == PackageManager.SIGNATURE_MATCH;
+ try {
+ IPackageManager pm = AppGlobals.getPackageManager();
+ return pm.checkUidSignatures(uid1, uid2) == PackageManager.SIGNATURE_MATCH;
+ } catch (RemoteException ex) {
+ Slog.e(TAG, "Remote exception while checking signatures", ex);
+ return false;
+ }
}
}
diff --git a/services/java/com/android/server/firewall/NotFilter.java b/services/java/com/android/server/firewall/NotFilter.java
index 2ff108a1..f0fc337 100644
--- a/services/java/com/android/server/firewall/NotFilter.java
+++ b/services/java/com/android/server/firewall/NotFilter.java
@@ -33,10 +33,9 @@
@Override
public boolean matches(IntentFirewall ifw, Intent intent, ApplicationInfo callerApp,
- String callerPackage, int callerUid, int callerPid, String resolvedType,
- ApplicationInfo resolvedApp) {
- return !mChild.matches(ifw, intent, callerApp, callerPackage, callerUid, callerPid,
- resolvedType, resolvedApp);
+ int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
+ return !mChild.matches(ifw, intent, callerApp, callerUid, callerPid, resolvedType,
+ resolvedApp);
}
public static final FilterFactory FACTORY = new FilterFactory("not") {
diff --git a/services/java/com/android/server/firewall/OrFilter.java b/services/java/com/android/server/firewall/OrFilter.java
index 1ed1c85..72db31e 100644
--- a/services/java/com/android/server/firewall/OrFilter.java
+++ b/services/java/com/android/server/firewall/OrFilter.java
@@ -26,11 +26,10 @@
class OrFilter extends FilterList {
@Override
public boolean matches(IntentFirewall ifw, Intent intent, ApplicationInfo callerApp,
- String callerPackage, int callerUid, int callerPid, String resolvedType,
- ApplicationInfo resolvedApp) {
+ int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
for (int i=0; i<children.size(); i++) {
- if (children.get(i).matches(ifw, intent, callerApp, callerPackage, callerUid, callerPid,
- resolvedType, resolvedApp)) {
+ if (children.get(i).matches(ifw, intent, callerApp, callerUid, callerPid, resolvedType,
+ resolvedApp)) {
return true;
}
}
diff --git a/services/java/com/android/server/firewall/PortFilter.java b/services/java/com/android/server/firewall/PortFilter.java
index 2b2a198..fe7e085 100644
--- a/services/java/com/android/server/firewall/PortFilter.java
+++ b/services/java/com/android/server/firewall/PortFilter.java
@@ -42,8 +42,7 @@
@Override
public boolean matches(IntentFirewall ifw, Intent intent, ApplicationInfo callerApp,
- String callerPackage, int callerUid, int callerPid, String resolvedType,
- ApplicationInfo resolvedApp) {
+ int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
int port = -1;
Uri uri = intent.getData();
if (uri != null) {
diff --git a/services/java/com/android/server/firewall/SenderFilter.java b/services/java/com/android/server/firewall/SenderFilter.java
index 0b790bd..58bdd73 100644
--- a/services/java/com/android/server/firewall/SenderFilter.java
+++ b/services/java/com/android/server/firewall/SenderFilter.java
@@ -68,8 +68,7 @@
private static final Filter SIGNATURE = new Filter() {
@Override
public boolean matches(IntentFirewall ifw, Intent intent, ApplicationInfo callerApp,
- String callerPackage, int callerUid, int callerPid, String resolvedType,
- ApplicationInfo resolvedApp) {
+ int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
if (callerApp == null) {
return false;
}
@@ -80,8 +79,7 @@
private static final Filter SYSTEM = new Filter() {
@Override
public boolean matches(IntentFirewall ifw, Intent intent, ApplicationInfo callerApp,
- String callerPackage, int callerUid, int callerPid, String resolvedType,
- ApplicationInfo resolvedApp) {
+ int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
if (callerApp == null) {
// if callerApp is null, the caller is the system process
return false;
@@ -93,8 +91,7 @@
private static final Filter SYSTEM_OR_SIGNATURE = new Filter() {
@Override
public boolean matches(IntentFirewall ifw, Intent intent, ApplicationInfo callerApp,
- String callerPackage, int callerUid, int callerPid, String resolvedType,
- ApplicationInfo resolvedApp) {
+ int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
return isSystemApp(callerApp, callerUid, callerPid) ||
ifw.signaturesMatch(callerUid, resolvedApp.uid);
}
@@ -103,8 +100,7 @@
private static final Filter USER_ID = new Filter() {
@Override
public boolean matches(IntentFirewall ifw, Intent intent, ApplicationInfo callerApp,
- String callerPackage, int callerUid, int callerPid, String resolvedType,
- ApplicationInfo resolvedApp) {
+ int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
// This checks whether the caller is either the system process, or has the same user id
// I.e. the same app, or an app that uses the same shared user id.
// This is the same set of applications that would be able to access the component if
diff --git a/services/java/com/android/server/firewall/SenderPermissionFilter.java b/services/java/com/android/server/firewall/SenderPermissionFilter.java
index 02d8b15..310da20 100644
--- a/services/java/com/android/server/firewall/SenderPermissionFilter.java
+++ b/services/java/com/android/server/firewall/SenderPermissionFilter.java
@@ -34,8 +34,7 @@
@Override
public boolean matches(IntentFirewall ifw, Intent intent, ApplicationInfo callerApp,
- String callerPackage, int callerUid, int callerPid, String resolvedType,
- ApplicationInfo resolvedApp) {
+ int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
// We assume the component is exported here. If the component is not exported, then
// ActivityManager would only resolve to this component for callers from the same uid.
// In this case, it doesn't matter whether the component is exported or not.
diff --git a/services/java/com/android/server/firewall/StringFilter.java b/services/java/com/android/server/firewall/StringFilter.java
index de5a69f..ed5d3f3 100644
--- a/services/java/com/android/server/firewall/StringFilter.java
+++ b/services/java/com/android/server/firewall/StringFilter.java
@@ -119,10 +119,9 @@
protected abstract boolean matchesValue(String value);
@Override
- public boolean matches(IntentFirewall ifw, Intent intent, ApplicationInfo callerApp, String callerPackage,
+ public boolean matches(IntentFirewall ifw, Intent intent, ApplicationInfo callerApp,
int callerUid, int callerPid, String resolvedType, ApplicationInfo resolvedApp) {
- String value = mValueProvider.getValue(intent, callerApp, callerPackage, resolvedType,
- resolvedApp);
+ String value = mValueProvider.getValue(intent, callerApp, resolvedType, resolvedApp);
return matchesValue(value);
}
@@ -137,7 +136,7 @@
}
public abstract String getValue(Intent intent, ApplicationInfo callerApp,
- String callerPackage, String resolvedType, ApplicationInfo resolvedApp);
+ String resolvedType, ApplicationInfo resolvedApp);
}
private static class EqualsFilter extends StringFilter {
@@ -231,8 +230,8 @@
public static final ValueProvider COMPONENT = new ValueProvider("component") {
@Override
- public String getValue(Intent intent, ApplicationInfo callerApp, String callerPackage,
- String resolvedType, ApplicationInfo resolvedApp) {
+ public String getValue(Intent intent, ApplicationInfo callerApp, String resolvedType,
+ ApplicationInfo resolvedApp) {
ComponentName cn = intent.getComponent();
if (cn != null) {
return cn.flattenToString();
@@ -243,8 +242,8 @@
public static final ValueProvider COMPONENT_NAME = new ValueProvider("component-name") {
@Override
- public String getValue(Intent intent, ApplicationInfo callerApp, String callerPackage,
- String resolvedType, ApplicationInfo resolvedApp) {
+ public String getValue(Intent intent, ApplicationInfo callerApp, String resolvedType,
+ ApplicationInfo resolvedApp) {
ComponentName cn = intent.getComponent();
if (cn != null) {
return cn.getClassName();
@@ -255,8 +254,8 @@
public static final ValueProvider COMPONENT_PACKAGE = new ValueProvider("component-package") {
@Override
- public String getValue(Intent intent, ApplicationInfo callerApp, String callerPackage,
- String resolvedType, ApplicationInfo resolvedApp) {
+ public String getValue(Intent intent, ApplicationInfo callerApp, String resolvedType,
+ ApplicationInfo resolvedApp) {
ComponentName cn = intent.getComponent();
if (cn != null) {
return cn.getPackageName();
@@ -265,28 +264,18 @@
}
};
- public static final ValueProvider SENDER_PACKAGE = new ValueProvider("sender-package") {
- @Override
- public String getValue(Intent intent, ApplicationInfo callerApp, String callerPackage,
- String resolvedType, ApplicationInfo resolvedApp) {
- // TODO: We can't trust this value, so maybe should check all packages in the caller process?
- return callerPackage;
- }
- };
-
-
public static final FilterFactory ACTION = new ValueProvider("action") {
@Override
- public String getValue(Intent intent, ApplicationInfo callerApp, String callerPackage,
- String resolvedType, ApplicationInfo resolvedApp) {
+ public String getValue(Intent intent, ApplicationInfo callerApp, String resolvedType,
+ ApplicationInfo resolvedApp) {
return intent.getAction();
}
};
public static final ValueProvider DATA = new ValueProvider("data") {
@Override
- public String getValue(Intent intent, ApplicationInfo callerApp, String callerPackage,
- String resolvedType, ApplicationInfo resolvedApp) {
+ public String getValue(Intent intent, ApplicationInfo callerApp, String resolvedType,
+ ApplicationInfo resolvedApp) {
Uri data = intent.getData();
if (data != null) {
return data.toString();
@@ -297,16 +286,16 @@
public static final ValueProvider MIME_TYPE = new ValueProvider("mime-type") {
@Override
- public String getValue(Intent intent, ApplicationInfo callerApp, String callerPackage,
- String resolvedType, ApplicationInfo resolvedApp) {
+ public String getValue(Intent intent, ApplicationInfo callerApp, String resolvedType,
+ ApplicationInfo resolvedApp) {
return resolvedType;
}
};
public static final ValueProvider SCHEME = new ValueProvider("scheme") {
@Override
- public String getValue(Intent intent, ApplicationInfo callerApp, String callerPackage,
- String resolvedType, ApplicationInfo resolvedApp) {
+ public String getValue(Intent intent, ApplicationInfo callerApp, String resolvedType,
+ ApplicationInfo resolvedApp) {
Uri data = intent.getData();
if (data != null) {
return data.getScheme();
@@ -317,8 +306,8 @@
public static final ValueProvider SSP = new ValueProvider("scheme-specific-part") {
@Override
- public String getValue(Intent intent, ApplicationInfo callerApp, String callerPackage,
- String resolvedType, ApplicationInfo resolvedApp) {
+ public String getValue(Intent intent, ApplicationInfo callerApp, String resolvedType,
+ ApplicationInfo resolvedApp) {
Uri data = intent.getData();
if (data != null) {
return data.getSchemeSpecificPart();
@@ -329,8 +318,8 @@
public static final ValueProvider HOST = new ValueProvider("host") {
@Override
- public String getValue(Intent intent, ApplicationInfo callerApp, String callerPackage,
- String resolvedType, ApplicationInfo resolvedApp) {
+ public String getValue(Intent intent, ApplicationInfo callerApp, String resolvedType,
+ ApplicationInfo resolvedApp) {
Uri data = intent.getData();
if (data != null) {
return data.getHost();
@@ -341,8 +330,8 @@
public static final ValueProvider PATH = new ValueProvider("path") {
@Override
- public String getValue(Intent intent, ApplicationInfo callerApp, String callerPackage,
- String resolvedType, ApplicationInfo resolvedApp) {
+ public String getValue(Intent intent, ApplicationInfo callerApp, String resolvedType,
+ ApplicationInfo resolvedApp) {
Uri data = intent.getData();
if (data != null) {
return data.getPath();
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index 3ed9cef..674955c 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -274,6 +274,33 @@
}
/**
+ * Make a SignalStrength object from the given parcel as passed up by
+ * the ril which does not have isGsm. isGsm will be changed by ServiceStateTracker
+ * so the default is a don't care.
+ *
+ * @hide
+ */
+ public static SignalStrength makeSignalStrengthFromRilParcel(Parcel in) {
+ if (DBG) log("Size of signalstrength parcel:" + in.dataSize());
+
+ SignalStrength ss = new SignalStrength();
+ ss.mGsmSignalStrength = in.readInt();
+ ss.mGsmBitErrorRate = in.readInt();
+ ss.mCdmaDbm = in.readInt();
+ ss.mCdmaEcio = in.readInt();
+ ss.mEvdoDbm = in.readInt();
+ ss.mEvdoEcio = in.readInt();
+ ss.mEvdoSnr = in.readInt();
+ ss.mLteSignalStrength = in.readInt();
+ ss.mLteRsrp = in.readInt();
+ ss.mLteRsrq = in.readInt();
+ ss.mLteRssnr = in.readInt();
+ ss.mLteCqi = in.readInt();
+
+ return ss;
+ }
+
+ /**
* {@link Parcelable#writeToParcel}
*/
public void writeToParcel(Parcel out, int flags) {