diff --git a/api/current.xml b/api/current.xml
index 2e8db511df36b..aa6471b7bbc26 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -6411,6 +6411,17 @@
visibility="public"
>
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
+
-
-
-
-
-
-
-
+
-
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -155024,6 +154903,17 @@
+
+ list = getContext().getPackageManager().
- queryIntentActivities(testIntent, PackageManager.MATCH_DEFAULT_ONLY);
- if (list.size() > 0) {
+ ResolveInfo ri = getContext().getPackageManager().
+ resolveActivity(testIntent, PackageManager.MATCH_DEFAULT_ONLY);
+ if (ri != null) {
visibility = View.VISIBLE;
}
}
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index 72692f4ebbf94..a6a436f4fd097 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -327,11 +327,15 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac
}
/**
- * Print the Service's state into the given stream.
+ * Print the Service's state into the given stream. This gets invoked if
+ * you run "adb shell dumpsys activity service ".
+ * This is distinct from "dumpsys ", which only works for
+ * named system services and which invokes the {@link IBinder#dump} method
+ * on the {@link IBinder} interface registered with ServiceManager.
*
* @param fd The raw file descriptor that the dump is being sent to.
* @param writer The PrintWriter to which you should dump your state. This will be
- * closed for you after you return.
+ * closed for you after you return.
* @param args additional arguments to the dump request.
*/
protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
diff --git a/core/java/android/bluetooth/ScoSocket.java b/core/java/android/bluetooth/ScoSocket.java
index 75b33296dd18e..a43a08be10567 100644
--- a/core/java/android/bluetooth/ScoSocket.java
+++ b/core/java/android/bluetooth/ScoSocket.java
@@ -16,17 +16,12 @@
package android.bluetooth;
-import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.util.Log;
-import java.io.IOException;
-import java.lang.Thread;
-
-
/**
* The Android Bluetooth API is not finalized, and *will* change. Use at your
* own risk.
@@ -56,7 +51,7 @@ public class ScoSocket {
private int mConnectedCode;
private int mClosedCode;
- private WakeLock mWakeLock; // held while STATE_CONNECTING or STATE_CONNECTED
+ private WakeLock mWakeLock; // held while in STATE_CONNECTING
static {
classInitNative();
@@ -130,6 +125,7 @@ public class ScoSocket {
public synchronized void close() {
if (DBG) log(this + " SCO OBJECT close() mState = " + mState);
+ acquireWakeLock();
mState = STATE_CLOSED;
closeNative();
releaseWakeLock();
@@ -152,19 +148,16 @@ public class ScoSocket {
mState = STATE_CLOSED;
}
mHandler.obtainMessage(mConnectedCode, mState, -1, this).sendToTarget();
- if (result < 0) {
- releaseWakeLock();
- }
+ releaseWakeLock();
}
private synchronized void onAccepted(int result) {
if (VDBG) log("onAccepted() " + this);
if (mState != STATE_ACCEPT) {
- if (DBG) log("Strange state" + this);
+ if (DBG) log("Strange state " + this);
return;
}
if (result >= 0) {
- acquireWakeLock();
mState = STATE_CONNECTED;
} else {
mState = STATE_CLOSED;
@@ -184,13 +177,13 @@ public class ScoSocket {
private void acquireWakeLock() {
if (!mWakeLock.isHeld()) {
mWakeLock.acquire();
- if (VDBG) log("mWakeLock.acquire()" + this);
+ if (VDBG) log("mWakeLock.acquire() " + this);
}
}
private void releaseWakeLock() {
if (mWakeLock.isHeld()) {
- if (VDBG) log("mWakeLock.release()" + this);
+ if (VDBG) log("mWakeLock.release() " + this);
mWakeLock.release();
}
}
diff --git a/core/java/android/content/BroadcastReceiver.java b/core/java/android/content/BroadcastReceiver.java
index ee08eea56fa48..08f6191ac71e7 100644
--- a/core/java/android/content/BroadcastReceiver.java
+++ b/core/java/android/content/BroadcastReceiver.java
@@ -79,7 +79,7 @@ import android.util.Log;
*
The BroadcastReceiver class (when launched as a component through
* a manifest's {@link android.R.styleable#AndroidManifestReceiver <receiver>}
* tag) is an important part of an
- * application's overall lifecycle.
See the Security and Permissions
* document for more information on permissions and security in general.
*
*
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 226c5ab77ebc5..3a64ceebc4fc6 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -41,8 +41,8 @@ import java.io.FileNotFoundException;
* multiple applications you can use a database directly via
* {@link android.database.sqlite.SQLiteDatabase}.
*
- *
See this page for more information on
- * content providers.
When a request is made via
* a {@link ContentResolver} the system inspects the authority of the given URI and passes the
@@ -226,9 +226,9 @@ public abstract class ContentProvider implements ComponentCallbacks {
/**
* Return the name of the permission required for read-only access to
* this content provider. This method can be called from multiple
- * threads, as described in the
- * Threading section of
- * the Application Model overview.
+ * threads, as described in
+ * Application Fundamentals:
+ * Processes and Threads.
*/
public final String getReadPermission() {
return mReadPermission;
@@ -248,9 +248,9 @@ public abstract class ContentProvider implements ComponentCallbacks {
/**
* Return the name of the permission required for read/write access to
* this content provider. This method can be called from multiple
- * threads, as described in the
- * Threading section of
- * the Application Model overview.
+ * threads, as described in
+ * Application Fundamentals:
+ * Processes and Threads.
*/
public final String getWritePermission() {
return mWritePermission;
@@ -273,9 +273,9 @@ public abstract class ContentProvider implements ComponentCallbacks {
* Receives a query request from a client in a local process, and
* returns a Cursor. This is called internally by the {@link ContentResolver}.
* This method can be called from multiple
- * threads, as described in the
- * Threading section of
- * the Application Model overview.
+ * threads, as described in
+ * Application Fundamentals:
+ * Processes and Threads.
*
* Example client call:
*
// Request a specific record.
@@ -330,9 +330,9 @@ public abstract class ContentProvider implements ComponentCallbacks {
* vnd.android.cursor.item for a single record,
* or vnd.android.cursor.dir/ for multiple items.
* This method can be called from multiple
- * threads, as described in the
- * Threading section of
- * the Application Model overview.
+ * threads, as described in
+ * Application Fundamentals:
+ * Processes and Threads.
*
* @param uri the URI to query.
* @return a MIME type string, or null if there is no type.
@@ -344,9 +344,9 @@ public abstract class ContentProvider implements ComponentCallbacks {
* As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
* after inserting.
* This method can be called from multiple
- * threads, as described in the
- * Threading section of the
- * Application Model overview.
+ * threads, as described in
+ * Application Fundamentals:
+ * Processes and Threads.
* @param uri The content:// URI of the insertion request.
* @param values A set of column_name/value pairs to add to the database.
* @return The URI for the newly inserted item.
@@ -359,9 +359,9 @@ public abstract class ContentProvider implements ComponentCallbacks {
* As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
* after inserting.
* This method can be called from multiple
- * threads, as described in the
- * Threading section of
- * the Application Model overview.
+ * threads, as described in
+ * Application Fundamentals:
+ * Processes and Threads.
*
* @param uri The content:// URI of the insertion request.
* @param values An array of sets of column_name/value pairs to add to the database.
@@ -382,9 +382,9 @@ public abstract class ContentProvider implements ComponentCallbacks {
* As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyDelete()}
* after deleting.
* This method can be called from multiple
- * threads, as described in the
- * Threading section of the
- * Application Model overview.
+ * threads, as described in
+ * Application Fundamentals:
+ * Processes and Threads.
*
*
The implementation is responsible for parsing out a row ID at the end
* of the URI, if a specific row is being deleted. That is, the client would
@@ -405,9 +405,9 @@ public abstract class ContentProvider implements ComponentCallbacks {
* As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
* after updating.
* This method can be called from multiple
- * threads, as described in the
- * Threading section of the
- * Application Model overview.
+ * threads, as described in
+ * Application Fundamentals:
+ * Processes and Threads.
*
* @param uri The URI to query. This can potentially have a record ID if this
* is an update request for a specific record.
@@ -422,9 +422,9 @@ public abstract class ContentProvider implements ComponentCallbacks {
/**
* Open a file blob associated with a content URI.
* This method can be called from multiple
- * threads, as described in the
- * Threading section of the
- * Application Model overview.
+ * threads, as described in
+ * Application Fundamentals:
+ * Processes and Threads.
*
*
Returns a
* ParcelFileDescriptor, from which you can obtain a
@@ -507,9 +507,9 @@ public abstract class ContentProvider implements ComponentCallbacks {
* This is intended for use by the sync system. If null then this
* content provider is considered not syncable.
* This method can be called from multiple
- * threads, as described in the
- * Threading section of
- * the Application Model overview.
+ * threads, as described in
+ * Application Fundamentals:
+ * Processes and Threads.
*
* @return the SyncAdapter that is to be used by this ContentProvider, or null
* if this ContentProvider is not syncable
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index c4d3f9d2ecee6..c1c3b499b0082 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1766,9 +1766,9 @@ public class Intent implements Parcelable {
* next task activity) defines an atomic group of activities that the
* user can move to. Tasks can be moved to the foreground and background;
* all of the activities inside of a particular task always remain in
- * the same order. See the
- * Application Model
- * documentation for more details on tasks.
+ * the same order. See
+ * Application Fundamentals:
+ * Activities and Tasks for more details on tasks.
*
*
This flag is generally used by activities that want
* to present a "launcher" style behavior: they give the user a list of
@@ -1801,9 +1801,8 @@ public class Intent implements Parcelable {
*
This flag is ignored if
* {@link #FLAG_ACTIVITY_NEW_TASK} is not set.
*
- *
See the
- * Application Model
- * documentation for more details on tasks.
+ *
See Application Fundamentals:
+ * Activities and Tasks for more details on tasks.
*/
public static final int FLAG_ACTIVITY_MULTIPLE_TASK = 0x08000000;
/**
@@ -1831,9 +1830,8 @@ public class Intent implements Parcelable {
* especially useful, for example, when launching an activity from the
* notification manager.
*
- *
See the
- * Application Model
- * documentation for more details on tasks.
+ *
See Application Fundamentals:
+ * Activities and Tasks for more details on tasks.
*/
public static final int FLAG_ACTIVITY_CLEAR_TOP = 0x04000000;
/**
@@ -3919,8 +3917,8 @@ public class Intent implements Parcelable {
* FLAG_RECEIVER_* flags are all for use with
* {@link Context#sendBroadcast(Intent) Context.sendBroadcast()}.
*
- *
See the Application Model
- * documentation for important information on how some of these options impact
+ *
See the Application Fundamentals:
+ * Activities and Tasks documentation for important information on how some of these options impact
* the behavior of your application.
*
* @param flags The desired flags.
@@ -4195,14 +4193,11 @@ public class Intent implements Parcelable {
@Override
public boolean equals(Object obj) {
- Intent other;
- try {
- other = ((FilterComparison)obj).mIntent;
- } catch (ClassCastException e) {
- return false;
+ if (obj instanceof FilterComparison) {
+ Intent other = ((FilterComparison)obj).mIntent;
+ return mIntent.filterEquals(other);
}
-
- return mIntent.filterEquals(other);
+ return false;
}
@Override
diff --git a/core/java/android/content/package.html b/core/java/android/content/package.html
index 7b3e8cfae7b1e..dd5360f651b46 100644
--- a/core/java/android/content/package.html
+++ b/core/java/android/content/package.html
@@ -50,9 +50,9 @@ an application's resources and transfer data between applications.
The Android resource system keeps track of all non-code
assets associated with an application. You use the
{@link android.content.res.Resources Resources} class to access your
@@ -175,7 +175,8 @@ download files with new appearances.
This section gives a few quick examples you can use to make your own resources.
For more details on how to define and use resources, see Resources.
+ href="{@docRoot}guide/topics/resources/resources-i18n.html">Resources and
+ Internationalization.
Using System Resources
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index 994afc8381ff1..d9326f211b5ba 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -28,6 +28,20 @@ public class PackageInfo implements Parcelable {
*/
public String versionName;
+ /**
+ * The shared user ID name of this package, as specified by the <manifest>
+ * tag's {@link android.R.styleable#AndroidManifest_sharedUserId sharedUserId}
+ * attribute.
+ */
+ public String sharedUserId;
+
+ /**
+ * The shared user ID label of this package, as specified by the <manifest>
+ * tag's {@link android.R.styleable#AndroidManifest_sharedUserLabel sharedUserLabel}
+ * attribute.
+ */
+ public int sharedUserLabel;
+
/**
* Information collected from the <application> tag, or null if
* there was none.
@@ -130,6 +144,8 @@ public class PackageInfo implements Parcelable {
dest.writeString(packageName);
dest.writeInt(versionCode);
dest.writeString(versionName);
+ dest.writeString(sharedUserId);
+ dest.writeInt(sharedUserLabel);
if (applicationInfo != null) {
dest.writeInt(1);
applicationInfo.writeToParcel(dest, parcelableFlags);
@@ -163,6 +179,8 @@ public class PackageInfo implements Parcelable {
packageName = source.readString();
versionCode = source.readInt();
versionName = source.readString();
+ sharedUserId = source.readString();
+ sharedUserLabel = source.readInt();
int hasApp = source.readInt();
if (hasApp != 0) {
applicationInfo = ApplicationInfo.CREATOR.createFromParcel(source);
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index e08f1d154dc2e..4ae8b08847086 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -101,6 +101,8 @@ public class PackageParser {
pi.packageName = p.packageName;
pi.versionCode = p.mVersionCode;
pi.versionName = p.mVersionName;
+ pi.sharedUserId = p.mSharedUserId;
+ pi.sharedUserLabel = p.mSharedUserLabel;
pi.applicationInfo = p.applicationInfo;
if ((flags&PackageManager.GET_GIDS) != 0) {
pi.gids = gids;
@@ -585,6 +587,8 @@ public class PackageParser {
return null;
}
pkg.mSharedUserId = str.intern();
+ pkg.mSharedUserLabel = sa.getResourceId(
+ com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
}
sa.recycle();
@@ -2045,6 +2049,9 @@ public class PackageParser {
// The shared user id that this package wants to use.
public String mSharedUserId;
+ // The shared user label that this package wants to use.
+ public int mSharedUserLabel;
+
// Signatures that were read from the package.
public Signature mSignatures[];
diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java
index 2ff72947879f8..10f3806d0ec9d 100644
--- a/core/java/android/database/DatabaseUtils.java
+++ b/core/java/android/database/DatabaseUtils.java
@@ -84,6 +84,7 @@ public class DatabaseUtils {
code = 9;
} else {
reply.writeException(e);
+ Log.e(TAG, "Writing exception to parcel", e);
return;
}
reply.writeInt(code);
diff --git a/core/java/android/inputmethodservice/ExtractEditText.java b/core/java/android/inputmethodservice/ExtractEditText.java
index d9f10a96aac0f..52f8209289002 100644
--- a/core/java/android/inputmethodservice/ExtractEditText.java
+++ b/core/java/android/inputmethodservice/ExtractEditText.java
@@ -102,7 +102,7 @@ public class ExtractEditText extends EditText {
* highlight and cursor will be displayed.
*/
@Override public boolean hasWindowFocus() {
- return true;
+ return this.isEnabled() ? true : false;
}
/**
@@ -110,7 +110,7 @@ public class ExtractEditText extends EditText {
* highlight and cursor will be displayed.
*/
@Override public boolean isFocused() {
- return true;
+ return this.isEnabled() ? true : false;
}
/**
@@ -118,7 +118,6 @@ public class ExtractEditText extends EditText {
* highlight and cursor will be displayed.
*/
@Override public boolean hasFocus() {
- return true;
+ return this.isEnabled() ? true : false;
}
-
}
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index c8841201f11b6..4be1fc798f883 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -229,9 +229,11 @@ public class InputMethodService extends AbstractInputMethodService {
InputConnection mStartedInputConnection;
EditorInfo mInputEditorInfo;
+ int mShowInputFlags;
boolean mShowInputRequested;
boolean mLastShowInputRequested;
int mCandidatesVisibility;
+ CompletionInfo[] mCurCompletions;
boolean mShowInputForced;
@@ -328,6 +330,7 @@ public class InputMethodService extends AbstractInputMethodService {
*/
public void hideSoftInput() {
if (DEBUG) Log.v(TAG, "hideSoftInput()");
+ mShowInputFlags = 0;
mShowInputRequested = false;
mShowInputForced = false;
hideWindow();
@@ -338,7 +341,10 @@ public class InputMethodService extends AbstractInputMethodService {
*/
public void showSoftInput(int flags) {
if (DEBUG) Log.v(TAG, "showSoftInput()");
- onShowRequested(flags);
+ mShowInputFlags = 0;
+ if (onShowInputRequested(flags, false)) {
+ showWindow(true);
+ }
}
}
@@ -364,6 +370,7 @@ public class InputMethodService extends AbstractInputMethodService {
if (!isEnabled()) {
return;
}
+ mCurCompletions = completions;
onDisplayCompletions(completions);
}
@@ -557,8 +564,9 @@ public class InputMethodService extends AbstractInputMethodService {
super.onConfigurationChanged(newConfig);
boolean visible = mWindowVisible;
+ int showFlags = mShowInputFlags;
boolean showingInput = mShowInputRequested;
- boolean showingForced = mShowInputForced;
+ CompletionInfo[] completions = mCurCompletions;
initViews();
mInputViewStarted = false;
mCandidatesViewStarted = false;
@@ -567,19 +575,24 @@ public class InputMethodService extends AbstractInputMethodService {
getCurrentInputEditorInfo(), true);
}
if (visible) {
- if (showingForced) {
- // If we are showing the full soft keyboard, then go through
- // this path to take care of current decisions about fullscreen
- // etc.
- onShowRequested(InputMethod.SHOW_FORCED|InputMethod.SHOW_EXPLICIT);
- } else if (showingInput) {
- // If we are showing the full soft keyboard, then go through
- // this path to take care of current decisions about fullscreen
- // etc.
- onShowRequested(InputMethod.SHOW_EXPLICIT);
- } else {
- // Otherwise just put it back for its candidates.
+ if (showingInput) {
+ // If we were last showing the soft keyboard, try to do so again.
+ if (onShowInputRequested(showFlags, true)) {
+ showWindow(true);
+ if (completions != null) {
+ mCurCompletions = completions;
+ onDisplayCompletions(completions);
+ }
+ } else {
+ hideWindow();
+ }
+ } else if (mCandidatesVisibility == View.VISIBLE) {
+ // If the candidates are currently visible, make sure the
+ // window is shown for them.
showWindow(false);
+ } else {
+ // Otherwise hide the window.
+ hideWindow();
}
}
}
@@ -1065,36 +1078,42 @@ public class InputMethodService extends AbstractInputMethodService {
* The system has decided that it may be time to show your input method.
* This is called due to a corresponding call to your
* {@link InputMethod#showSoftInput(int) InputMethod.showSoftInput(int)}
- * method. The default implementation simply calls
- * {@link #showWindow(boolean)}, except if the
- * {@link InputMethod#SHOW_EXPLICIT InputMethod.SHOW_EXPLICIT} flag is
- * not set and the input method is running in fullscreen mode.
+ * method. The default implementation uses
+ * {@link #onEvaluateInputViewShown()}, {@link #onEvaluateFullscreenMode()},
+ * and the current configuration to decide whether the input view should
+ * be shown at this point.
*
* @param flags Provides additional information about the show request,
* as per {@link InputMethod#showSoftInput(int) InputMethod.showSoftInput(int)}.
+ * @param configChange This is true if we are re-showing due to a
+ * configuration change.
+ * @return Returns true to indicate that the window should be shown.
*/
- public void onShowRequested(int flags) {
+ public boolean onShowInputRequested(int flags, boolean configChange) {
if (!onEvaluateInputViewShown()) {
- return;
+ return false;
}
if ((flags&InputMethod.SHOW_EXPLICIT) == 0) {
- if (onEvaluateFullscreenMode()) {
+ if (!configChange && onEvaluateFullscreenMode()) {
// Don't show if this is not explicitly requested by the user and
// the input method is fullscreen. That would be too disruptive.
- return;
+ // However, we skip this change for a config change, since if
+ // the IME is already shown we do want to go into fullscreen
+ // mode at this point.
+ return false;
}
Configuration config = getResources().getConfiguration();
if (config.keyboard != Configuration.KEYBOARD_NOKEYS) {
// And if the device has a hard keyboard, even if it is
// currently hidden, don't show the input method implicitly.
// These kinds of devices don't need it that much.
- return;
+ return false;
}
}
if ((flags&InputMethod.SHOW_FORCED) != 0) {
mShowInputForced = true;
}
- showWindow(true);
+ return true;
}
public void showWindow(boolean showInput) {
@@ -1106,7 +1125,6 @@ public class InputMethodService extends AbstractInputMethodService {
+ " mInputStarted=" + mInputStarted);
boolean doShowInput = false;
boolean wasVisible = mWindowVisible;
- boolean wasCreated = mWindowCreated;
mWindowVisible = true;
if (!mShowInputRequested) {
if (mInputStarted) {
@@ -1240,6 +1258,7 @@ public class InputMethodService extends AbstractInputMethodService {
}
mInputStarted = false;
mStartedInputConnection = null;
+ mCurCompletions = null;
}
void doStartInput(InputConnection ic, EditorInfo attribute, boolean restarting) {
@@ -1550,7 +1569,11 @@ public class InputMethodService extends AbstractInputMethodService {
eet.setInputType(inputType);
eet.setHint(mInputEditorInfo.hintText);
if (mExtractedText != null) {
+ eet.setEnabled(true);
eet.setExtractedText(mExtractedText);
+ } else {
+ eet.setEnabled(false);
+ eet.setText("");
}
} finally {
eet.finishInternalChanges();
@@ -1586,7 +1609,8 @@ public class InputMethodService extends AbstractInputMethodService {
p.println(" mShowInputRequested=" + mShowInputRequested
+ " mLastShowInputRequested=" + mLastShowInputRequested
- + " mShowInputForced=" + mShowInputForced);
+ + " mShowInputForced=" + mShowInputForced
+ + " mShowInputFlags=0x" + Integer.toHexString(mShowInputFlags));
p.println(" mCandidatesVisibility=" + mCandidatesVisibility
+ " mFullscreenApplied=" + mFullscreenApplied
+ " mIsFullscreen=" + mIsFullscreen);
diff --git a/core/java/android/inputmethodservice/Keyboard.java b/core/java/android/inputmethodservice/Keyboard.java
index 228acbee97e0f..6a560ce0150be 100755
--- a/core/java/android/inputmethodservice/Keyboard.java
+++ b/core/java/android/inputmethodservice/Keyboard.java
@@ -132,7 +132,19 @@ public class Keyboard {
/** Keyboard mode, or zero, if none. */
private int mKeyboardMode;
+
+ // Variables for pre-computing nearest keys.
+ private static final int GRID_WIDTH = 10;
+ private static final int GRID_HEIGHT = 5;
+ private static final int GRID_SIZE = GRID_WIDTH * GRID_HEIGHT;
+ private int mCellWidth;
+ private int mCellHeight;
+ private int[][] mGridNeighbors;
+ private int mProximityThreshold;
+ /** Number of key widths from current touch point to search for nearest keys. */
+ private static float SEARCH_DISTANCE = 1.4f;
+
/**
* Container for keys in the keyboard. All keys in a row are at the same Y-coordinate.
* Some of the key size defaults can be overridden per row from what the {@link Keyboard}
@@ -637,6 +649,52 @@ public class Keyboard {
public int getShiftKeyIndex() {
return mShiftKeyIndex;
}
+
+ private void computeNearestNeighbors() {
+ // Round-up so we don't have any pixels outside the grid
+ mCellWidth = (getMinWidth() + GRID_WIDTH - 1) / GRID_WIDTH;
+ mCellHeight = (getHeight() + GRID_HEIGHT - 1) / GRID_HEIGHT;
+ mGridNeighbors = new int[GRID_SIZE][];
+ int[] indices = new int[mKeys.size()];
+ final int gridWidth = GRID_WIDTH * mCellWidth;
+ final int gridHeight = GRID_HEIGHT * mCellHeight;
+ for (int x = 0; x < gridWidth; x += mCellWidth) {
+ for (int y = 0; y < gridHeight; y += mCellHeight) {
+ int count = 0;
+ for (int i = 0; i < mKeys.size(); i++) {
+ final Key key = mKeys.get(i);
+ if (key.squaredDistanceFrom(x, y) < mProximityThreshold ||
+ key.squaredDistanceFrom(x + mCellWidth - 1, y) < mProximityThreshold ||
+ key.squaredDistanceFrom(x + mCellWidth - 1, y + mCellHeight - 1)
+ < mProximityThreshold ||
+ key.squaredDistanceFrom(x, y + mCellHeight - 1) < mProximityThreshold) {
+ indices[count++] = i;
+ }
+ }
+ int [] cell = new int[count];
+ System.arraycopy(indices, 0, cell, 0, count);
+ mGridNeighbors[(y / mCellHeight) * GRID_WIDTH + (x / mCellWidth)] = cell;
+ }
+ }
+ }
+
+ /**
+ * Returns the indices of the keys that are closest to the given point.
+ * @param x the x-coordinate of the point
+ * @param y the y-coordinate of the point
+ * @return the array of integer indices for the nearest keys to the given point. If the given
+ * point is out of range, then an array of size zero is returned.
+ */
+ public int[] getNearestKeys(int x, int y) {
+ if (mGridNeighbors == null) computeNearestNeighbors();
+ if (x >= 0 && x < getMinWidth() && y >= 0 && y < getHeight()) {
+ int index = (y / mCellHeight) * GRID_WIDTH + (x / mCellWidth);
+ if (index < GRID_SIZE) {
+ return mGridNeighbors[index];
+ }
+ }
+ return new int[0];
+ }
protected Row createRowFromXml(Resources res, XmlResourceParser parser) {
return new Row(res, this, parser);
@@ -738,6 +796,8 @@ public class Keyboard {
mDefaultVerticalGap = getDimensionOrFraction(a,
com.android.internal.R.styleable.Keyboard_verticalGap,
mDisplayHeight, 0);
+ mProximityThreshold = (int) (mDefaultWidth * SEARCH_DISTANCE);
+ mProximityThreshold = mProximityThreshold * mProximityThreshold; // Square it for comparison
a.recycle();
}
diff --git a/core/java/android/inputmethodservice/KeyboardView.java b/core/java/android/inputmethodservice/KeyboardView.java
index b8bd10dc44de2..886e68829e1de 100755
--- a/core/java/android/inputmethodservice/KeyboardView.java
+++ b/core/java/android/inputmethodservice/KeyboardView.java
@@ -159,6 +159,9 @@ public class KeyboardView extends View implements View.OnClickListener {
private static final int MSG_REPEAT = 3;
private static final int MSG_LONGPRESS = 4;
+ private static final int DELAY_BEFORE_PREVIEW = 70;
+ private static final int DELAY_AFTER_PREVIEW = 60;
+
private int mVerticalCorrection;
private int mProximityThreshold;
@@ -219,7 +222,7 @@ public class KeyboardView extends View implements View.OnClickListener {
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SHOW_PREVIEW:
- mPreviewText.setVisibility(VISIBLE);
+ showKey(msg.arg1);
break;
case MSG_REMOVE_PREVIEW:
mPreviewText.setVisibility(INVISIBLE);
@@ -234,7 +237,6 @@ public class KeyboardView extends View implements View.OnClickListener {
openPopupIfRequired((MotionEvent) msg.obj);
break;
}
-
}
};
@@ -533,10 +535,10 @@ public class KeyboardView extends View implements View.OnClickListener {
dimensionSum += Math.min(key.width, key.height) + key.gap;
}
if (dimensionSum < 0 || length == 0) return;
- mProximityThreshold = (int) (dimensionSum * 1.5f / length);
+ mProximityThreshold = (int) (dimensionSum * 1.4f / length);
mProximityThreshold *= mProximityThreshold; // Square it
}
-
+
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
@@ -647,9 +649,10 @@ public class KeyboardView extends View implements View.OnClickListener {
int closestKey = NOT_A_KEY;
int closestKeyDist = mProximityThreshold + 1;
java.util.Arrays.fill(mDistances, Integer.MAX_VALUE);
- final int keyCount = keys.length;
+ int [] nearestKeyIndices = mKeyboard.getNearestKeys(x, y);
+ final int keyCount = nearestKeyIndices.length;
for (int i = 0; i < keyCount; i++) {
- final Key key = keys[i];
+ final Key key = keys[nearestKeyIndices[i]];
int dist = 0;
boolean isInside = key.isInside(x,y);
if (((mProximityCorrectOn
@@ -660,7 +663,7 @@ public class KeyboardView extends View implements View.OnClickListener {
final int nCodes = key.codes.length;
if (dist < closestKeyDist) {
closestKeyDist = dist;
- closestKey = i;
+ closestKey = nearestKeyIndices[i];
}
if (allKeys == null) continue;
@@ -674,9 +677,6 @@ public class KeyboardView extends View implements View.OnClickListener {
allKeys.length - j - nCodes);
for (int c = 0; c < nCodes; c++) {
allKeys[j + c] = key.codes[c];
- if (shifted) {
- //allKeys[j + c] = Character.toUpperCase(key.codes[c]);
- }
mDistances[j + c] = dist;
}
break;
@@ -685,7 +685,7 @@ public class KeyboardView extends View implements View.OnClickListener {
}
if (isInside) {
- primaryIndex = i;
+ primaryIndex = nearestKeyIndices[i];
}
}
if (primaryIndex == NOT_A_KEY) {
@@ -696,7 +696,7 @@ public class KeyboardView extends View implements View.OnClickListener {
private void detectAndSendKey(int x, int y, long eventTime) {
int index = mCurrentKey;
- if (index != NOT_A_KEY) {
+ if (index != NOT_A_KEY && index < mKeys.length) {
final Key key = mKeys[index];
if (key.text != null) {
for (int i = 0; i < key.text.length(); i++) {
@@ -763,70 +763,83 @@ public class KeyboardView extends View implements View.OnClickListener {
if (previewPopup.isShowing()) {
if (keyIndex == NOT_A_KEY) {
mHandler.sendMessageDelayed(mHandler
- .obtainMessage(MSG_REMOVE_PREVIEW), 60);
+ .obtainMessage(MSG_REMOVE_PREVIEW),
+ DELAY_AFTER_PREVIEW);
}
}
if (keyIndex != NOT_A_KEY) {
- Key key = keys[keyIndex];
- if (key.icon != null) {
- mPreviewText.setCompoundDrawables(null, null, null,
- key.iconPreview != null ? key.iconPreview : key.icon);
- mPreviewText.setText(null);
+ if (previewPopup.isShowing() && mPreviewText.getVisibility() == VISIBLE) {
+ // Show right away, if it's already visible and finger is moving around
+ showKey(keyIndex);
} else {
- mPreviewText.setCompoundDrawables(null, null, null, null);
- mPreviewText.setText(getPreviewText(key));
- if (key.label.length() > 1 && key.codes.length < 2) {
- mPreviewText.setTextSize(mLabelTextSize);
- mPreviewText.setTypeface(Typeface.DEFAULT_BOLD);
- } else {
- mPreviewText.setTextSize(mPreviewTextSizeLarge);
- mPreviewText.setTypeface(Typeface.DEFAULT);
- }
+ mHandler.sendMessageDelayed(
+ mHandler.obtainMessage(MSG_SHOW_PREVIEW, keyIndex, 0),
+ DELAY_BEFORE_PREVIEW);
}
- mPreviewText.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
- MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
- int popupWidth = Math.max(mPreviewText.getMeasuredWidth(), key.width
- + mPreviewText.getPaddingLeft() + mPreviewText.getPaddingRight());
- final int popupHeight = mPreviewHeight;
- LayoutParams lp = mPreviewText.getLayoutParams();
- if (lp != null) {
- lp.width = popupWidth;
- lp.height = popupHeight;
- }
- if (!mPreviewCentered) {
- mPopupPreviewX = key.x - mPreviewText.getPaddingLeft() + mPaddingLeft;
- mPopupPreviewY = key.y - popupHeight + mPreviewOffset;
- } else {
- // TODO: Fix this if centering is brought back
- mPopupPreviewX = 160 - mPreviewText.getMeasuredWidth() / 2;
- mPopupPreviewY = - mPreviewText.getMeasuredHeight();
- }
- mHandler.removeMessages(MSG_REMOVE_PREVIEW);
- if (mOffsetInWindow == null) {
- mOffsetInWindow = new int[2];
- getLocationInWindow(mOffsetInWindow);
- mOffsetInWindow[0] += mMiniKeyboardOffsetX; // Offset may be zero
- mOffsetInWindow[1] += mMiniKeyboardOffsetY; // Offset may be zero
- }
- // Set the preview background state
- mPreviewText.getBackground().setState(
- key.popupResId != 0 ? LONG_PRESSABLE_STATE_SET : EMPTY_STATE_SET);
- if (previewPopup.isShowing()) {
- previewPopup.update(mPopupPreviewX + mOffsetInWindow[0],
- mPopupPreviewY + mOffsetInWindow[1],
- popupWidth, popupHeight);
- } else {
- previewPopup.setWidth(popupWidth);
- previewPopup.setHeight(popupHeight);
- previewPopup.showAtLocation(mPopupParent, Gravity.NO_GRAVITY,
- mPopupPreviewX + mOffsetInWindow[0],
- mPopupPreviewY + mOffsetInWindow[1]);
- }
- mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SHOW_PREVIEW, keyIndex, 0),
- ViewConfiguration.getTapTimeout());
}
}
}
+
+ private void showKey(final int keyIndex) {
+ final PopupWindow previewPopup = mPreviewPopup;
+ final Key[] keys = mKeys;
+ Key key = keys[keyIndex];
+ if (key.icon != null) {
+ mPreviewText.setCompoundDrawables(null, null, null,
+ key.iconPreview != null ? key.iconPreview : key.icon);
+ mPreviewText.setText(null);
+ } else {
+ mPreviewText.setCompoundDrawables(null, null, null, null);
+ mPreviewText.setText(getPreviewText(key));
+ if (key.label.length() > 1 && key.codes.length < 2) {
+ mPreviewText.setTextSize(mLabelTextSize);
+ mPreviewText.setTypeface(Typeface.DEFAULT_BOLD);
+ } else {
+ mPreviewText.setTextSize(mPreviewTextSizeLarge);
+ mPreviewText.setTypeface(Typeface.DEFAULT);
+ }
+ }
+ mPreviewText.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
+ MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
+ int popupWidth = Math.max(mPreviewText.getMeasuredWidth(), key.width
+ + mPreviewText.getPaddingLeft() + mPreviewText.getPaddingRight());
+ final int popupHeight = mPreviewHeight;
+ LayoutParams lp = mPreviewText.getLayoutParams();
+ if (lp != null) {
+ lp.width = popupWidth;
+ lp.height = popupHeight;
+ }
+ if (!mPreviewCentered) {
+ mPopupPreviewX = key.x - mPreviewText.getPaddingLeft() + mPaddingLeft;
+ mPopupPreviewY = key.y - popupHeight + mPreviewOffset;
+ } else {
+ // TODO: Fix this if centering is brought back
+ mPopupPreviewX = 160 - mPreviewText.getMeasuredWidth() / 2;
+ mPopupPreviewY = - mPreviewText.getMeasuredHeight();
+ }
+ mHandler.removeMessages(MSG_REMOVE_PREVIEW);
+ if (mOffsetInWindow == null) {
+ mOffsetInWindow = new int[2];
+ getLocationInWindow(mOffsetInWindow);
+ mOffsetInWindow[0] += mMiniKeyboardOffsetX; // Offset may be zero
+ mOffsetInWindow[1] += mMiniKeyboardOffsetY; // Offset may be zero
+ }
+ // Set the preview background state
+ mPreviewText.getBackground().setState(
+ key.popupResId != 0 ? LONG_PRESSABLE_STATE_SET : EMPTY_STATE_SET);
+ if (previewPopup.isShowing()) {
+ previewPopup.update(mPopupPreviewX + mOffsetInWindow[0],
+ mPopupPreviewY + mOffsetInWindow[1],
+ popupWidth, popupHeight);
+ } else {
+ previewPopup.setWidth(popupWidth);
+ previewPopup.setHeight(popupHeight);
+ previewPopup.showAtLocation(mPopupParent, Gravity.NO_GRAVITY,
+ mPopupPreviewX + mOffsetInWindow[0],
+ mPopupPreviewY + mOffsetInWindow[1]);
+ }
+ mPreviewText.setVisibility(VISIBLE);
+ }
private void invalidateKey(int keyIndex) {
if (keyIndex < 0 || keyIndex >= mKeys.length) {
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 017b14da98a0e..6f9d6c674d015 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1,18 +1,20 @@
package android.os;
-import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Formatter;
import java.util.Map;
+import android.util.Log;
+import android.util.Printer;
import android.util.SparseArray;
/**
* A class providing access to battery usage statistics, including information on
* wakelocks, processes, packages, and services. All times are represented in microseconds
* except where indicated otherwise.
+ * @hide
*/
-public abstract class BatteryStats {
+public abstract class BatteryStats implements Parcelable {
/**
* A constant indicating a partial wake lock timer.
@@ -96,6 +98,11 @@ public abstract class BatteryStats {
* @return a time in microseconds
*/
public abstract long getTotalTime(long now, int which);
+
+ /**
+ * Temporary for debugging.
+ */
+ public abstract void logState();
}
/**
@@ -154,10 +161,10 @@ public abstract class BatteryStats {
public abstract long getTcpBytesSent(int which);
public static abstract class Sensor {
- /**
- * {@hide}
- */
- public abstract String getName();
+ // Magic sensor number for the GPS.
+ public static final int GPS = -10000;
+
+ public abstract int getHandle();
public abstract Timer getSensorTime();
}
@@ -259,6 +266,11 @@ public abstract class BatteryStats {
*/
public abstract long getPluggedScreenOnTime();
+ /**
+ * Return whether we are currently running on battery.
+ */
+ public abstract boolean getIsOnBattery();
+
/**
* Returns a SparseArray containing the statistics for each uid.
*/
@@ -457,7 +469,7 @@ public abstract class BatteryStats {
* @param pw
* @param which
*/
- private final void dumpCheckinLocked(FileDescriptor fd, PrintWriter pw, int which) {
+ private final void dumpCheckinLocked(PrintWriter pw, int which) {
long uSecTime = SystemClock.elapsedRealtime() * 1000;
final long uSecNow = getBatteryUptime(uSecTime);
@@ -578,35 +590,18 @@ public abstract class BatteryStats {
}
@SuppressWarnings("unused")
- private final void dumpLocked(FileDescriptor fd, PrintWriter pw, String prefix, int which) {
+ private final void dumpLocked(Printer pw, String prefix, int which) {
long uSecTime = SystemClock.elapsedRealtime() * 1000;
final long uSecNow = getBatteryUptime(uSecTime);
StringBuilder sb = new StringBuilder(128);
- switch (which) {
- case STATS_TOTAL:
- pw.println(prefix + "Current and Historic Battery Usage Statistics:");
- pw.println(prefix + " System starts: " + getStartCount());
- break;
- case STATS_LAST:
- pw.println(prefix + "Last Battery Usage Statistics:");
- break;
- case STATS_UNPLUGGED:
- pw.println(prefix + "Last Unplugged Battery Usage Statistics:");
- break;
- case STATS_CURRENT:
- pw.println(prefix + "Current Battery Usage Statistics:");
- break;
- default:
- throw new IllegalArgumentException("which = " + which);
- }
long batteryUptime = computeBatteryUptime(uSecNow, which);
long batteryRealtime = computeBatteryRealtime(getBatteryRealtime(uSecTime), which);
long elapsedRealtime = computeRealtime(uSecTime, which);
long uptime = computeUptime(SystemClock.uptimeMillis() * 1000, which);
pw.println(prefix
- + " On battery: " + formatTimeMs(batteryUptime / 1000) + "("
+ + " Time on battery: " + formatTimeMs(batteryUptime / 1000) + "("
+ formatRatioLocked(batteryUptime, elapsedRealtime)
+ ") uptime, "
+ formatTimeMs(batteryRealtime / 1000) + "("
@@ -618,7 +613,7 @@ public abstract class BatteryStats {
+ "uptime, "
+ formatTimeMs(elapsedRealtime / 1000)
+ "realtime");
-
+
pw.println(" ");
SparseArray extends Uid> uidStats = getUidStats();
@@ -629,8 +624,12 @@ public abstract class BatteryStats {
pw.println(prefix + " #" + uid + ":");
boolean uidActivity = false;
- pw.println(prefix + " Network: " + u.getTcpBytesReceived(which) + " bytes received, "
- + u.getTcpBytesSent(which) + " bytes sent");
+ long tcpReceived = u.getTcpBytesReceived(which);
+ long tcpSent = u.getTcpBytesSent(which);
+ if (tcpReceived != 0 || tcpSent != 0) {
+ pw.println(prefix + " Network: " + tcpReceived + " bytes received, "
+ + tcpSent + " bytes sent");
+ }
Map wakelocks = u.getWakelockStats();
if (wakelocks.size() > 0) {
@@ -648,7 +647,9 @@ public abstract class BatteryStats {
"partial", which, linePrefix);
linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), uSecNow,
"window", which, linePrefix);
- if (linePrefix.equals(": ")) {
+ if (!linePrefix.equals(": ")) {
+ sb.append(" realtime");
+ } else {
sb.append(": (nothing executed)");
}
pw.println(sb.toString());
@@ -665,23 +666,30 @@ public abstract class BatteryStats {
sb.setLength(0);
sb.append(prefix);
sb.append(" Sensor ");
- sb.append(sensorNumber);
+ int handle = se.getHandle();
+ if (handle == Uid.Sensor.GPS) {
+ sb.append("GPS");
+ } else {
+ sb.append(handle);
+ }
+ sb.append(": ");
Timer timer = se.getSensorTime();
if (timer != null) {
// Convert from microseconds to milliseconds with rounding
long totalTime = (timer.getTotalTime(uSecNow, which) + 500) / 1000;
int count = timer.getCount(which);
+ //timer.logState();
if (totalTime != 0) {
- sb.append(": ");
sb.append(formatTimeMs(totalTime));
- sb.append(' ');
- sb.append('(');
+ sb.append("realtime (");
sb.append(count);
sb.append(" times)");
+ } else {
+ sb.append("(not used)");
}
} else {
- sb.append(": (none used)");
+ sb.append("(not used)");
}
pw.println(sb.toString());
@@ -734,8 +742,9 @@ public abstract class BatteryStats {
int launches = ss.getLaunches(which);
if (startTime != 0 || starts != 0 || launches != 0) {
pw.println(prefix + " Service " + sent.getKey() + ":");
- pw.println(prefix + " Time spent started: "
- + formatTimeMs(startTime / 1000));
+ pw.println(prefix + " Created for: "
+ + formatTimeMs(startTime / 1000)
+ + " uptime");
pw.println(prefix + " Starts: " + starts
+ ", launches: " + launches);
apkActivity = true;
@@ -757,36 +766,30 @@ public abstract class BatteryStats {
/**
* Dumps a human-readable summary of the battery statistics to the given PrintWriter.
*
- * @param fd a FileDescriptor, currently unused.
- * @param pw a PrintWriter to receive the dump output.
- * @param args an array of Strings, currently unused.
+ * @param pw a Printer to receive the dump output.
*/
@SuppressWarnings("unused")
- public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args) {
- boolean isCheckin = false;
- if (args != null) {
- for (String arg : args) {
- if ("-c".equals(arg)) {
- isCheckin = true;
- break;
- }
- }
- }
- synchronized (this) {
- if (isCheckin) {
- dumpCheckinLocked(fd, pw, STATS_TOTAL);
- dumpCheckinLocked(fd, pw, STATS_LAST);
- dumpCheckinLocked(fd, pw, STATS_UNPLUGGED);
- dumpCheckinLocked(fd, pw, STATS_CURRENT);
- } else {
- dumpLocked(fd, pw, "", STATS_TOTAL);
- pw.println("");
- dumpLocked(fd, pw, "", STATS_LAST);
- pw.println("");
- dumpLocked(fd, pw, "", STATS_UNPLUGGED);
- pw.println("");
- dumpLocked(fd, pw, "", STATS_CURRENT);
- }
- }
+ public void dumpLocked(Printer pw) {
+ pw.println("Total Statistics (Current and Historic):");
+ pw.println(" System starts: " + getStartCount()
+ + ", currently on battery: " + getIsOnBattery());
+ dumpLocked(pw, "", STATS_TOTAL);
+ pw.println("");
+ pw.println("Last Run Statistics (Previous run of system):");
+ dumpLocked(pw, "", STATS_LAST);
+ pw.println("");
+ pw.println("Current Battery Statistics (Currently running system):");
+ dumpLocked(pw, "", STATS_CURRENT);
+ pw.println("");
+ pw.println("Unplugged Statistics (Since last unplugged from power):");
+ dumpLocked(pw, "", STATS_UNPLUGGED);
+ }
+
+ @SuppressWarnings("unused")
+ public void dumpCheckinLocked(PrintWriter pw, String[] args) {
+ dumpCheckinLocked(pw, STATS_TOTAL);
+ dumpCheckinLocked(pw, STATS_LAST);
+ dumpCheckinLocked(pw, STATS_UNPLUGGED);
+ dumpCheckinLocked(pw, STATS_CURRENT);
}
}
diff --git a/core/java/android/os/ICheckinService.aidl b/core/java/android/os/ICheckinService.aidl
index 11becc4869c7f..e56b55d78cd51 100644
--- a/core/java/android/os/ICheckinService.aidl
+++ b/core/java/android/os/ICheckinService.aidl
@@ -26,7 +26,13 @@ import android.os.IParentalControlCallback;
* {@hide}
*/
interface ICheckinService {
- /** Synchronously attempt a checkin with the server, return true on success. */
+ /** Synchronously attempt a checkin with the server, return true
+ * on success.
+ * @throws IllegalStateException whenever an error occurs. The
+ * cause of the exception will be the real exception:
+ * IOException for network errors, JSONException for invalid
+ * server responses, etc.
+ */
boolean checkin();
/** Direct submission of crash data; returns after writing the crash. */
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index e48f1523a6beb..5486920249cfa 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -29,4 +29,5 @@ interface IPowerManager
void setStayOnSetting(int val);
long getScreenOnTime();
void preventScreenOn(boolean prevent);
+ void setScreenBrightnessOverride(int brightness);
}
diff --git a/core/java/android/preference/PreferenceGroupAdapter.java b/core/java/android/preference/PreferenceGroupAdapter.java
index 02ab1da35fda1..14c0054b868be 100644
--- a/core/java/android/preference/PreferenceGroupAdapter.java
+++ b/core/java/android/preference/PreferenceGroupAdapter.java
@@ -242,7 +242,7 @@ class PreferenceGroupAdapter extends BaseAdapter implements OnPreferenceChangeIn
mHasReturnedViewTypeCount = true;
}
- return mPreferenceClassNames.size();
+ return Math.max(1, mPreferenceClassNames.size());
}
}
diff --git a/core/java/android/provider/Checkin.java b/core/java/android/provider/Checkin.java
index 5767c65bb7574..688e19a83c76d 100644
--- a/core/java/android/provider/Checkin.java
+++ b/core/java/android/provider/Checkin.java
@@ -97,6 +97,7 @@ public final class Checkin {
SETUP_RETRIES_EXHAUSTED,
SETUP_SERVER_ERROR,
SETUP_SERVER_TIMEOUT,
+ SETUP_NO_DATA_NETWORK,
SYSTEM_APP_NOT_RESPONDING,
SYSTEM_BOOT,
SYSTEM_LAST_KMSG,
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index c6a7b407101ce..4a784c8bd210d 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2320,6 +2320,13 @@ public final class Settings {
*/
public static final String GMAIL_SEND_IMMEDIATELY = "gmail_send_immediately";
+ /**
+ * Controls whether gmail buffers server responses. Possible values are "memory", for a
+ * memory-based buffer, or "file", for a temp-file-based buffer. All other values
+ * (including not set) disable buffering.
+ */
+ public static final String GMAIL_BUFFER_SERVER_RESPONSE = "gmail_buffer_server_response";
+
/**
* Hostname of the GTalk server.
*/
diff --git a/core/java/android/server/BluetoothDeviceService.java b/core/java/android/server/BluetoothDeviceService.java
index 7c15045dbfb4a..86d5a1e73bd35 100644
--- a/core/java/android/server/BluetoothDeviceService.java
+++ b/core/java/android/server/BluetoothDeviceService.java
@@ -111,9 +111,19 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub {
private native int isEnabledNative();
/**
- * Disable bluetooth. Returns true on success.
+ * Bring down bluetooth and disable BT in settings. Returns true on success.
*/
- public synchronized boolean disable() {
+ public boolean disable() {
+ return disable(true);
+ }
+
+ /**
+ * Bring down bluetooth. Returns true on success.
+ *
+ * @param saveSetting If true, disable BT in settings
+ *
+ */
+ public synchronized boolean disable(boolean saveSetting) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH_ADMIN permission");
@@ -137,21 +147,37 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub {
mContext.sendBroadcast(intent, BLUETOOTH_PERM);
mIsEnabled = false;
- persistBluetoothOnSetting(false);
+ if (saveSetting) {
+ persistBluetoothOnSetting(false);
+ }
mIsDiscovering = false;
intent = new Intent(BluetoothIntent.DISABLED_ACTION);
mContext.sendBroadcast(intent, BLUETOOTH_PERM);
return true;
}
+ /**
+ * Bring up bluetooth, asynchronously, and enable BT in settings.
+ * This turns on/off the underlying hardware.
+ *
+ * @return True on success (so far), guaranteeing the callback with be
+ * notified when complete.
+ */
+ public boolean enable(IBluetoothDeviceCallback callback) {
+ return enable(callback, true);
+ }
+
/**
* Enable this Bluetooth device, asynchronously.
* This turns on/off the underlying hardware.
*
- * @return True on success (so far), guarenteeing the callback with be
+ * @param saveSetting If true, enable BT in settings
+ *
+ * @return True on success (so far), guaranteeing the callback with be
* notified when complete.
*/
- public synchronized boolean enable(IBluetoothDeviceCallback callback) {
+ public synchronized boolean enable(IBluetoothDeviceCallback callback,
+ boolean saveSetting) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH_ADMIN permission");
@@ -165,7 +191,7 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub {
if (mEnableThread != null && mEnableThread.isAlive()) {
return false;
}
- mEnableThread = new EnableThread(callback);
+ mEnableThread = new EnableThread(callback, saveSetting);
mEnableThread.start();
return true;
}
@@ -189,8 +215,10 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub {
private class EnableThread extends Thread {
private final IBluetoothDeviceCallback mEnableCallback;
- public EnableThread(IBluetoothDeviceCallback callback) {
+ private final boolean mSaveSetting;
+ public EnableThread(IBluetoothDeviceCallback callback, boolean saveSetting) {
mEnableCallback = callback;
+ mSaveSetting = saveSetting;
}
public void run() {
boolean res = (enableNative() == 0);
@@ -208,7 +236,9 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub {
if (res) {
mIsEnabled = true;
- persistBluetoothOnSetting(true);
+ if (mSaveSetting) {
+ persistBluetoothOnSetting(true);
+ }
mIsDiscovering = false;
Intent intent = new Intent(BluetoothIntent.ENABLED_ACTION);
mBondState.loadBondState();
@@ -952,9 +982,9 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub {
// If bluetooth is currently expected to be on, then enable or disable bluetooth
if (Settings.Secure.getInt(resolver, Settings.Secure.BLUETOOTH_ON, 0) > 0) {
if (enabled) {
- enable(null);
+ enable(null, false);
} else {
- disable();
+ disable(false);
}
}
}
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index b5e409027ce99..187ec2cf3a0b3 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -359,10 +359,10 @@ class BluetoothEventLoop {
private void onGetRemoteServiceChannelResult(String address, int channel) {
IBluetoothDeviceCallback callback = mGetRemoteServiceChannelCallbacks.get(address);
if (callback != null) {
+ mGetRemoteServiceChannelCallbacks.remove(address);
try {
callback.onGetRemoteServiceChannelResult(address, channel);
} catch (RemoteException e) {}
- mGetRemoteServiceChannelCallbacks.remove(address);
}
}
diff --git a/core/java/android/speech/srec/MicrophoneInputStream.java b/core/java/android/speech/srec/MicrophoneInputStream.java
index 160a0034a5dda..fab77a9b8a0a4 100644
--- a/core/java/android/speech/srec/MicrophoneInputStream.java
+++ b/core/java/android/speech/srec/MicrophoneInputStream.java
@@ -1,5 +1,5 @@
/*---------------------------------------------------------------------------*
- * MicrophoneInputStream.java *
+ * MicrophoneInputStream.java *
* *
* Copyright 2007 Nuance Communciations, Inc. *
* *
@@ -45,8 +45,12 @@ public final class MicrophoneInputStream extends InputStream {
*/
public MicrophoneInputStream(int sampleRate, int fifoDepth) throws IOException {
mAudioRecord = AudioRecordNew(sampleRate, fifoDepth);
- if (mAudioRecord == 0) throw new IllegalStateException("not open");
- AudioRecordStart(mAudioRecord);
+ if (mAudioRecord == 0) throw new IOException("AudioRecord constructor failed - busy?");
+ int status = AudioRecordStart(mAudioRecord);
+ if (status != 0) {
+ close();
+ throw new IOException("AudioRecord start failed: " + status);
+ }
}
@Override
@@ -99,7 +103,7 @@ public final class MicrophoneInputStream extends InputStream {
// AudioRecord JNI interface
//
private static native int AudioRecordNew(int sampleRate, int fifoDepth);
- private static native void AudioRecordStart(int audioRecord);
+ private static native int AudioRecordStart(int audioRecord);
private static native int AudioRecordRead(int audioRecord, byte[] b, int offset, int length) throws IOException;
private static native void AudioRecordStop(int audioRecord) throws IOException;
private static native void AudioRecordDelete(int audioRecord) throws IOException;
diff --git a/core/java/android/text/format/Time.java b/core/java/android/text/format/Time.java
index 5bf9b205a6c68..daa99c250bfa4 100644
--- a/core/java/android/text/format/Time.java
+++ b/core/java/android/text/format/Time.java
@@ -394,6 +394,7 @@ public class Time {
*
* @param s the string to parse
* @return true if the resulting time value is in UTC time
+ * @throws android.util.TimeFormatException if s cannot be parsed.
*/
public boolean parse(String s) {
if (nativeParse(s)) {
diff --git a/core/java/android/text/style/ImageSpan.java b/core/java/android/text/style/ImageSpan.java
index 2eebc0deb80e6..efb88a0eb9939 100644
--- a/core/java/android/text/style/ImageSpan.java
+++ b/core/java/android/text/style/ImageSpan.java
@@ -44,8 +44,9 @@ public class ImageSpan extends DynamicDrawableSpan {
public ImageSpan(Bitmap b, int verticalAlignment) {
super(verticalAlignment);
mDrawable = new BitmapDrawable(b);
- mDrawable.setBounds(0, 0, mDrawable.getIntrinsicWidth(),
- mDrawable.getIntrinsicHeight());
+ int width = mDrawable.getIntrinsicWidth();
+ int height = mDrawable.getIntrinsicHeight();
+ mDrawable.setBounds(0, 0, width > 0 ? width : 0, height > 0 ? height : 0);
}
public ImageSpan(Drawable d) {
diff --git a/core/java/android/util/SparseIntArray.java b/core/java/android/util/SparseIntArray.java
index 610cfd4a461aa..9ab3b53169e38 100644
--- a/core/java/android/util/SparseIntArray.java
+++ b/core/java/android/util/SparseIntArray.java
@@ -73,12 +73,19 @@ public class SparseIntArray {
int i = binarySearch(mKeys, 0, mSize, key);
if (i >= 0) {
- System.arraycopy(mKeys, i + 1, mKeys, i, mSize - (i + 1));
- System.arraycopy(mValues, i + 1, mValues, i, mSize - (i + 1));
- mSize--;
+ removeAt(i);
}
}
+ /**
+ * Removes the mapping at the given index.
+ */
+ public void removeAt(int index) {
+ System.arraycopy(mKeys, index + 1, mKeys, index, mSize - (index + 1));
+ System.arraycopy(mValues, index + 1, mValues, index, mSize - (index + 1));
+ mSize--;
+ }
+
/**
* Adds a mapping from the specified key to the specified value,
* replacing the previous mapping from the specified key if there
diff --git a/core/java/android/view/GestureDetector.java b/core/java/android/view/GestureDetector.java
index a4726894c0cd1..679c683cfeea2 100644
--- a/core/java/android/view/GestureDetector.java
+++ b/core/java/android/view/GestureDetector.java
@@ -163,7 +163,7 @@ public class GestureDetector {
private static final int TAP_TIMEOUT = ViewConfiguration.getTapTimeout();
// TODO make new double-tap timeout, and define its events (i.e. either time
// between down-down or time between up-down)
- private static final int DOUBLE_TAP_TIMEOUT = ViewConfiguration.getJumpTapTimeout();
+ private static final int DOUBLE_TAP_TIMEOUT = ViewConfiguration.getDoubleTapTimeout();
// constants for Message.what used by GestureHandler below
private static final int SHOW_PRESS = 1;
@@ -174,11 +174,13 @@ public class GestureDetector {
private final OnGestureListener mListener;
private OnDoubleTapListener mDoubleTapListener;
+ private boolean mStillDown;
private boolean mInLongPress;
private boolean mAlwaysInTapRegion;
private boolean mAlwaysInBiggerTapRegion;
private MotionEvent mCurrentDownEvent;
+ private MotionEvent mPreviousUpEvent;
/**
* True when the user is still touching for the second tap (down, move, and
@@ -217,7 +219,8 @@ public class GestureDetector {
break;
case TAP:
- if (mDoubleTapListener != null) {
+ // If the user's finger is still down, do not count it as a tap
+ if (mDoubleTapListener != null && !mStillDown) {
mDoubleTapListener.onSingleTapConfirmed(mCurrentDownEvent);
}
break;
@@ -378,8 +381,10 @@ public class GestureDetector {
switch (action) {
case MotionEvent.ACTION_DOWN:
if (mDoubleTapListener != null) {
- mHandler.removeMessages(TAP);
- if (mCurrentDownEvent != null && isConsideredDoubleTap(mCurrentDownEvent, ev)) {
+ boolean hadTapMessage = mHandler.hasMessages(TAP);
+ if (hadTapMessage) mHandler.removeMessages(TAP);
+ if ((mCurrentDownEvent != null) && (mPreviousUpEvent != null) && hadTapMessage &&
+ isConsideredDoubleTap(mCurrentDownEvent, mPreviousUpEvent, ev)) {
// This is a second tap
mIsDoubleTapping = true;
handled = mDoubleTapListener.onDoubleTapEvent(ev);
@@ -394,6 +399,7 @@ public class GestureDetector {
mCurrentDownEvent = MotionEvent.obtain(ev);
mAlwaysInTapRegion = true;
mAlwaysInBiggerTapRegion = true;
+ mStillDown = true;
mInLongPress = false;
if (mIsLongpressEnabled) {
@@ -422,6 +428,7 @@ public class GestureDetector {
mLastMotionX = x;
mLastMotionY = y;
mAlwaysInTapRegion = false;
+ mHandler.removeMessages(TAP);
mHandler.removeMessages(SHOW_PRESS);
mHandler.removeMessages(LONG_PRESS);
}
@@ -436,6 +443,7 @@ public class GestureDetector {
break;
case MotionEvent.ACTION_UP:
+ mStillDown = false;
MotionEvent currentUpEvent = MotionEvent.obtain(ev);
if (mIsDoubleTapping) {
handled = mDoubleTapListener.onDoubleTapEvent(ev);
@@ -461,6 +469,7 @@ public class GestureDetector {
handled = mListener.onFling(mCurrentDownEvent, currentUpEvent, velocityX, velocityY);
}
}
+ mPreviousUpEvent = MotionEvent.obtain(ev);
mVelocityTracker.recycle();
mVelocityTracker = null;
mHandler.removeMessages(SHOW_PRESS);
@@ -472,6 +481,7 @@ public class GestureDetector {
mHandler.removeMessages(TAP);
mVelocityTracker.recycle();
mVelocityTracker = null;
+ mStillDown = false;
if (mInLongPress) {
mInLongPress = false;
break;
@@ -480,12 +490,13 @@ public class GestureDetector {
return handled;
}
- private boolean isConsideredDoubleTap(MotionEvent firstDown, MotionEvent secondDown) {
+ private boolean isConsideredDoubleTap(MotionEvent firstDown, MotionEvent firstUp,
+ MotionEvent secondDown) {
if (!mAlwaysInBiggerTapRegion) {
return false;
}
- if (secondDown.getEventTime() - firstDown.getEventTime() > DOUBLE_TAP_TIMEOUT) {
+ if (secondDown.getEventTime() - firstUp.getEventTime() > DOUBLE_TAP_TIMEOUT) {
return false;
}
@@ -495,6 +506,7 @@ public class GestureDetector {
}
private void dispatchLongPress() {
+ mHandler.removeMessages(TAP);
mInLongPress = true;
mListener.onLongPress(mCurrentDownEvent);
}
diff --git a/core/java/android/view/OrientationEventListener.java b/core/java/android/view/OrientationEventListener.java
new file mode 100755
index 0000000000000..cddec11a35638
--- /dev/null
+++ b/core/java/android/view/OrientationEventListener.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.util.Config;
+import android.util.Log;
+
+/**
+ * Helper class for receiving notifications from the SensorManager when
+ * the orientation of the device has changed.
+ */
+public abstract class OrientationEventListener {
+ private static final String TAG = "OrientationEventListener";
+ private static final boolean DEBUG = false;
+ private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
+ private int mOrientation = ORIENTATION_UNKNOWN;
+ private SensorManager mSensorManager;
+ private boolean mEnabled = false;
+ private int mRate;
+ private Sensor mSensor;
+ private SensorEventListener mSensorEventListener;
+ private OrientationListener mOldListener;
+
+ /**
+ * Returned from onOrientationChanged when the device orientation cannot be determined
+ * (typically when the device is in a close to flat position).
+ *
+ * @see #onOrientationChanged
+ */
+ public static final int ORIENTATION_UNKNOWN = -1;
+
+ /**
+ * Creates a new OrientationEventListener.
+ *
+ * @param context for the OrientationEventListener.
+ */
+ public OrientationEventListener(Context context) {
+ this(context, SensorManager.SENSOR_DELAY_NORMAL);
+ }
+
+ /**
+ * Creates a new OrientationEventListener.
+ *
+ * @param context for the OrientationEventListener.
+ * @param rate at which sensor events are processed (see also
+ * {@link android.hardware.SensorManager SensorManager}). Use the default
+ * value of {@link android.hardware.SensorManager#SENSOR_DELAY_NORMAL
+ * SENSOR_DELAY_NORMAL} for simple screen orientation change detection.
+ */
+ public OrientationEventListener(Context context, int rate) {
+ mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
+ mRate = rate;
+ mSensorEventListener = new SensorEventListenerImpl();
+ mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
+ }
+
+ void registerListener(OrientationListener lis) {
+ mOldListener = lis;
+ }
+
+ /**
+ * Enables the OrientationEventListener so it will monitor the sensor and call
+ * {@link #onOrientationChanged} when the device orientation changes.
+ */
+ public void enable() {
+ if (mEnabled == false) {
+ if (localLOGV) Log.d(TAG, "OrientationEventListener enabled");
+ mSensorManager.registerListener(mSensorEventListener, mSensor, mRate);
+ mEnabled = true;
+ }
+ }
+
+ /**
+ * Disables the OrientationEventListener.
+ */
+ public void disable() {
+ if (mEnabled == true) {
+ if (localLOGV) Log.d(TAG, "OrientationEventListener disabled");
+ mSensorManager.unregisterListener(mSensorEventListener);
+ mEnabled = false;
+ }
+ }
+
+ class SensorEventListenerImpl implements SensorEventListener {
+ private static final int _DATA_X = 0;
+ private static final int _DATA_Y = 1;
+ private static final int _DATA_Z = 2;
+
+ public void onSensorChanged(SensorEvent event) {
+ float[] values = event.values;
+ int orientation = ORIENTATION_UNKNOWN;
+ float X = -values[_DATA_X];
+ float Y = -values[_DATA_Y];
+ float Z = -values[_DATA_Z];
+ float magnitude = X*X + Y*Y;
+ // Don't trust the angle if the magnitude is small compared to the y value
+ if (magnitude * 4 >= Z*Z) {
+ float OneEightyOverPi = 57.29577957855f;
+ float angle = (float)Math.atan2(-Y, X) * OneEightyOverPi;
+ orientation = 90 - (int)Math.round(angle);
+ // normalize to 0 - 359 range
+ while (orientation >= 360) {
+ orientation -= 360;
+ }
+ while (orientation < 0) {
+ orientation += 360;
+ }
+ }
+ if (mOldListener != null) {
+ mOldListener.onSensorChanged(Sensor.TYPE_ACCELEROMETER, event.values);
+ }
+ if (orientation != mOrientation) {
+ mOrientation = orientation;
+ onOrientationChanged(orientation);
+ }
+ }
+
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+
+ }
+ }
+
+ /**
+ * Called when the orientation of the device has changed.
+ * orientation parameter is in degrees, ranging from 0 to 359.
+ * orientation is 0 degrees when the device is oriented in its natural position,
+ * 90 degrees when its left side is at the top, 180 degrees when it is upside down,
+ * and 270 degrees when its right side is to the top.
+ * {@link #ORIENTATION_UNKNOWN} is returned when the device is close to flat
+ * and the orientation cannot be determined.
+ *
+ * @param orientation The new orientation of the device.
+ *
+ * @see #ORIENTATION_UNKNOWN
+ */
+ abstract public void onOrientationChanged(int orientation);
+}
diff --git a/core/java/android/view/OrientationListener.java b/core/java/android/view/OrientationListener.java
index 974c2e83565a3..ce8074e2ad6f9 100644
--- a/core/java/android/view/OrientationListener.java
+++ b/core/java/android/view/OrientationListener.java
@@ -18,23 +18,16 @@ package android.view;
import android.content.Context;
import android.hardware.SensorListener;
-import android.hardware.SensorManager;
-import android.util.Config;
-import android.util.Log;
/**
* Helper class for receiving notifications from the SensorManager when
* the orientation of the device has changed.
+ * @deprecated use {@link android.view.OrientationEventListener} instead.
+ * This class internally uses the OrientationEventListener.
*/
+@Deprecated
public abstract class OrientationListener implements SensorListener {
-
- private static final String TAG = "OrientationListener";
- private static final boolean DEBUG = false;
- private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
- private SensorManager mSensorManager;
- private int mOrientation = ORIENTATION_UNKNOWN;
- private boolean mEnabled = false;
- private int mRate;
+ private OrientationEventListener mOrientationEventLis;
/**
* Returned from onOrientationChanged when the device orientation cannot be determined
@@ -42,7 +35,7 @@ public abstract class OrientationListener implements SensorListener {
*
* @see #onOrientationChanged
*/
- public static final int ORIENTATION_UNKNOWN = -1;
+ public static final int ORIENTATION_UNKNOWN = OrientationEventListener.ORIENTATION_UNKNOWN;
/**
* Creates a new OrientationListener.
@@ -50,8 +43,7 @@ public abstract class OrientationListener implements SensorListener {
* @param context for the OrientationListener.
*/
public OrientationListener(Context context) {
- mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
- mRate = SensorManager.SENSOR_DELAY_NORMAL;
+ mOrientationEventLis = new OrientationEventListenerInternal(context);
}
/**
@@ -64,78 +56,55 @@ public abstract class OrientationListener implements SensorListener {
* SENSOR_DELAY_NORMAL} for simple screen orientation change detection.
*/
public OrientationListener(Context context, int rate) {
- mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
- mRate = rate;
+ mOrientationEventLis = new OrientationEventListenerInternal(context, rate);
}
-
+
+ class OrientationEventListenerInternal extends OrientationEventListener {
+ OrientationEventListenerInternal(Context context) {
+ super(context);
+ }
+
+ OrientationEventListenerInternal(Context context, int rate) {
+ super(context, rate);
+ // register so that onSensorChanged gets invoked
+ registerListener(OrientationListener.this);
+ }
+
+ public void onOrientationChanged(int orientation) {
+ OrientationListener.this.onOrientationChanged(orientation);
+ }
+ }
+
/**
* Enables the OrientationListener so it will monitor the sensor and call
* {@link #onOrientationChanged} when the device orientation changes.
*/
public void enable() {
- if (mEnabled == false) {
- if (localLOGV) Log.d(TAG, "OrientationListener enabled");
- mSensorManager.registerListener(this, SensorManager.SENSOR_ACCELEROMETER, mRate);
- mEnabled = true;
- }
+ mOrientationEventLis.enable();
}
/**
* Disables the OrientationListener.
*/
public void disable() {
- if (mEnabled == true) {
- if (localLOGV) Log.d(TAG, "OrientationListener disabled");
- mSensorManager.unregisterListener(this);
- mEnabled = false;
- }
+ mOrientationEventLis.disable();
}
-
- /**
- *
- */
- public void onSensorChanged(int sensor, float[] values) {
- int orientation = ORIENTATION_UNKNOWN;
- float X = values[SensorManager.RAW_DATA_X];
- float Y = values[SensorManager.RAW_DATA_Y];
- float Z = values[SensorManager.RAW_DATA_Z];
- float magnitude = X*X + Y*Y;
- // Don't trust the angle if the magnitude is small compared to the y value
- if (magnitude * 4 >= Z*Z) {
- float OneEightyOverPi = 57.29577957855f;
- float angle = (float)Math.atan2(-Y, X) * OneEightyOverPi;
- orientation = 90 - (int)Math.round(angle);
- // normalize to 0 - 359 range
- while (orientation >= 360) {
- orientation -= 360;
- }
- while (orientation < 0) {
- orientation += 360;
- }
- }
-
- if (orientation != mOrientation) {
- mOrientation = orientation;
- onOrientationChanged(orientation);
- }
- }
-
+
public void onAccuracyChanged(int sensor, int accuracy) {
- // TODO Auto-generated method stub
+ }
+
+ public void onSensorChanged(int sensor, float[] values) {
+ // just ignore the call here onOrientationChanged is invoked anyway
}
+
/**
- * Called when the orientation of the device has changed.
- * orientation parameter is in degrees, ranging from 0 to 359.
- * orientation is 0 degrees when the device is oriented in its natural position,
- * 90 degrees when its left side is at the top, 180 degrees when it is upside down,
- * and 270 degrees when its right side is to the top.
- * {@link #ORIENTATION_UNKNOWN} is returned when the device is close to flat
- * and the orientation cannot be determined.
- *
+ * Look at {@link android.view.OrientationEventListener#onOrientationChanged}
+ * for method description and usage
* @param orientation The new orientation of the device.
*
* @see #ORIENTATION_UNKNOWN
*/
abstract public void onOrientationChanged(int orientation);
+
}
diff --git a/core/java/android/os/HandlerInterface.java b/core/java/android/view/RemotableViewMethod.java
similarity index 53%
rename from core/java/android/os/HandlerInterface.java
rename to core/java/android/view/RemotableViewMethod.java
index 62dc273e32c2e..4318290affc47 100644
--- a/core/java/android/os/HandlerInterface.java
+++ b/core/java/android/view/RemotableViewMethod.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 The Android Open Source Project
+ * Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,14 +14,22 @@
* limitations under the License.
*/
-package android.os;
+package android.view;
-/**
- * @hide
- * @deprecated
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @hide
+ * This annotation indicates that a method on a subclass of View
+ * is alllowed to be used with the {@link android.widget.RemoteViews} mechanism.
*/
-public interface HandlerInterface
-{
- void handleMessage(Message msg);
+@Target({ ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface RemotableViewMethod {
}
+
+
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 1d5e7cd49ca53..5ed3a7ea6471f 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2674,6 +2674,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback {
* @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
* @attr ref android.R.styleable#View_visibility
*/
+ @RemotableViewMethod
public void setVisibility(int visibility) {
setFlags(visibility, VISIBILITY_MASK);
if (mBGDrawable != null) mBGDrawable.setVisible(visibility == VISIBLE, false);
@@ -4016,6 +4017,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback {
*/
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
mBackgroundSizeChanged = true;
+
+ final AttachInfo ai = mAttachInfo;
+ if (ai != null) {
+ ai.mViewScrollChanged = true;
+ }
}
/**
@@ -7947,6 +7953,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback {
*/
boolean mViewVisibilityChanged;
+ /**
+ * Set to true if a view has been scrolled.
+ */
+ boolean mViewScrollChanged;
+
/**
* Global to the view hierarchy used as a temporary for dealing with
* x/y points in the transparent region computations.
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 7153ea1985c8b..2f7b0d1a00688 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -67,6 +67,13 @@ public class ViewConfiguration {
* considered to be a tap.
*/
private static final int JUMP_TAP_TIMEOUT = 500;
+
+ /**
+ * Defines the duration in milliseconds between the first tap's up event and
+ * the second tap's down event for an interaction to be considered a
+ * double-tap.
+ */
+ private static final int DOUBLE_TAP_TIMEOUT = 300;
/**
* Defines the duration in milliseconds we want to display zoom controls in response
@@ -82,7 +89,7 @@ public class ViewConfiguration {
/**
* Distance a touch can wander before we think the user is scrolling in pixels
*/
- private static final int TOUCH_SLOP = 12;
+ private static final int TOUCH_SLOP = 25;
/**
* Distance between the first touch and second touch to still be considered a double tap
@@ -256,6 +263,16 @@ public class ViewConfiguration {
return JUMP_TAP_TIMEOUT;
}
+ /**
+ * @return Defines the duration in milliseconds between the first tap's up event and
+ * the second tap's down event for an interaction to be considered a
+ * double-tap.
+ * @hide pending API council
+ */
+ public static int getDoubleTapTimeout() {
+ return DOUBLE_TAP_TIMEOUT;
+ }
+
/**
* @return Inset in pixels to look for touchable content when the user touches the edge of the
* screen
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index c75866245215f..70cc2a9c3390b 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -27,6 +27,7 @@ import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.RectF;
import android.os.Parcelable;
+import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.EventLog;
import android.util.Log;
@@ -1023,6 +1024,20 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
*/
@Override
void dispatchDetachedFromWindow() {
+ // If we still have a motion target, we are still in the process of
+ // dispatching motion events to a child; we need to get rid of that
+ // child to avoid dispatching events to it after the window is torn
+ // down. To make sure we keep the child in a consistent state, we
+ // first send it an ACTION_CANCEL motion event.
+ if (mMotionTarget != null) {
+ final long now = SystemClock.uptimeMillis();
+ final MotionEvent event = MotionEvent.obtain(now, now,
+ MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
+ mMotionTarget.dispatchTouchEvent(event);
+ event.recycle();
+ mMotionTarget = null;
+ }
+
final int count = mChildrenCount;
final View[] children = mChildren;
for (int i = 0; i < count; i++) {
@@ -1331,6 +1346,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
final Animation a = child.getAnimation();
boolean concatMatrix = false;
+ final int childWidth = cr - cl;
+ final int childHeight = cb - ct;
+
if (a != null) {
if (mInvalidateRegion == null) {
mInvalidateRegion = new RectF();
@@ -1339,8 +1357,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
final boolean initialized = a.isInitialized();
if (!initialized) {
- a.initialize(cr - cl, cb - ct, getWidth(), getHeight());
- a.initializeInvalidateRegion(cl, ct, cr, cb);
+ a.initialize(childWidth, childHeight, getWidth(), getHeight());
+ a.initializeInvalidateRegion(0, 0, childWidth, childHeight);
child.onAnimationStart();
}
@@ -1364,7 +1382,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
invalidate(cl, ct, cr, cb);
}
} else {
- a.getInvalidateRegion(cl, ct, cr, cb, region, transformToApply);
+ a.getInvalidateRegion(0, 0, childWidth, childHeight, region, transformToApply);
// The child need to draw an animation, potentially offscreen, so
// make sure we do not cancel invalidate requests
@@ -1372,8 +1390,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
// Enlarge the invalidate region to account for rounding errors
// in Animation#getInvalidateRegion(); Using 0.5f is unfortunately
// not enough for some types of animations (e.g. scale down.)
- invalidate((int) (region.left - 1.0f), (int) (region.top - 1.0f),
- (int) (region.right + 1.0f), (int) (region.bottom + 1.0f));
+ final int left = cl + (int) (region.left - 1.0f);
+ final int top = ct + (int) (region.top - 1.0f);
+ invalidate(left, top,
+ left + (int) (region.width() + 1.0f),
+ top + (int) (region.height() + 1.0f));
}
}
} else if ((flags & FLAG_SUPPORT_STATIC_TRANSFORMATIONS) ==
@@ -1453,9 +1474,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
if ((flags & FLAG_CLIP_CHILDREN) == FLAG_CLIP_CHILDREN) {
if (hasNoCache) {
- canvas.clipRect(sx, sy, sx + cr - cl, sy + cb - ct);
+ canvas.clipRect(sx, sy, sx + childWidth, sy + childHeight);
} else {
- canvas.clipRect(0, 0, cr - cl, cb - ct);
+ canvas.clipRect(0, 0, childWidth, childHeight);
}
}
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index ccfa6bf97fcf7..db8829f9bc027 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -33,6 +33,7 @@ import android.util.Config;
import android.util.Log;
import android.util.EventLog;
import android.util.SparseArray;
+import android.util.DisplayMetrics;
import android.view.View.MeasureSpec;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
@@ -184,6 +185,7 @@ public final class ViewRoot extends Handler implements ViewParent,
*/
AudioManager mAudioManager;
+ private final float mDensity;
public ViewRoot(Context context) {
super();
@@ -226,6 +228,7 @@ public final class ViewRoot extends Handler implements ViewParent,
mAdded = false;
mAttachInfo = new View.AttachInfo(sWindowSession, mWindow, this, this);
mViewConfiguration = ViewConfiguration.get(context);
+ mDensity = context.getResources().getDisplayMetrics().density;
}
@Override
@@ -1077,6 +1080,11 @@ public final class ViewRoot extends Handler implements ViewParent,
}
scrollToRectOrFocus(null, false);
+
+ if (mAttachInfo.mViewScrollChanged) {
+ mAttachInfo.mViewScrollChanged = false;
+ mAttachInfo.mTreeObserver.dispatchOnScrollChanged();
+ }
int yoff;
final boolean scrolling = mScroller != null
@@ -1090,7 +1098,7 @@ public final class ViewRoot extends Handler implements ViewParent,
mCurScrollY = yoff;
fullRedrawNeeded = true;
}
-
+
Rect dirty = mDirty;
if (mUseGL) {
if (!dirty.isEmpty()) {
@@ -1126,7 +1134,6 @@ public final class ViewRoot extends Handler implements ViewParent,
return;
}
-
if (fullRedrawNeeded)
dirty.union(0, 0, mWidth, mHeight);
@@ -1138,22 +1145,22 @@ public final class ViewRoot extends Handler implements ViewParent,
+ surface + " surface.isValid()=" + surface.isValid());
}
- if (!dirty.isEmpty()) {
- Canvas canvas;
- try {
- canvas = surface.lockCanvas(dirty);
- // TODO: Do this in native
- canvas.setDensityScale(mView.getResources().getDisplayMetrics().density);
- } catch (Surface.OutOfResourcesException e) {
- Log.e("ViewRoot", "OutOfResourcesException locking surface", e);
- // TODO: we should ask the window manager to do something!
- // for now we just do nothing
- return;
- }
+ Canvas canvas;
+ try {
+ canvas = surface.lockCanvas(dirty);
+ // TODO: Do this in native
+ canvas.setDensityScale(mDensity);
+ } catch (Surface.OutOfResourcesException e) {
+ Log.e("ViewRoot", "OutOfResourcesException locking surface", e);
+ // TODO: we should ask the window manager to do something!
+ // for now we just do nothing
+ return;
+ }
- long startTime;
+ try {
+ if (!dirty.isEmpty()) {
+ long startTime;
- try {
if (DEBUG_ORIENTATION || DEBUG_DRAW) {
Log.v("ViewRoot", "Surface " + surface + " drawing to bitmap w="
+ canvas.getWidth() + ", h=" + canvas.getHeight());
@@ -1169,7 +1176,7 @@ public final class ViewRoot extends Handler implements ViewParent,
// properly re-composite its drawing on a transparent
// background. This automatically respects the clip/dirty region
if (!canvas.isOpaque()) {
- canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+ canvas.drawColor(0xff0000ff, PorterDuff.Mode.CLEAR);
} else if (yoff != 0) {
// If we are applying an offset, we need to clear the area
// where the offset doesn't appear to avoid having garbage
@@ -1192,35 +1199,18 @@ public final class ViewRoot extends Handler implements ViewParent,
sDrawTime = now;
}
- } finally {
- surface.unlockCanvasAndPost(canvas);
- }
-
- if (PROFILE_DRAWING) {
- EventLog.writeEvent(60000, SystemClock.elapsedRealtime() - startTime);
- }
-
- if (LOCAL_LOGV) {
- Log.v("ViewRoot", "Surface " + surface + " unlockCanvasAndPost");
+ if (PROFILE_DRAWING) {
+ EventLog.writeEvent(60000, SystemClock.elapsedRealtime() - startTime);
+ }
}
- } else if (mWidth == 0 || mHeight == 0) {
- // This is a special case where a window dimension is 0 -- we
- // normally wouldn't draw anything because we have an empty
- // dirty rect, but the surface flinger may be waiting for us to
- // draw the window before it stops freezing the screen, so we
- // need to diddle it like this to keep it from getting stuck.
- Canvas canvas;
- try {
- canvas = surface.lockCanvas(dirty);
- } catch (Surface.OutOfResourcesException e) {
- Log.e("ViewRoot", "OutOfResourcesException locking surface", e);
- // TODO: we should ask the window manager to do something!
- // for now we just do nothing
- return;
- }
+ } finally {
surface.unlockCanvasAndPost(canvas);
}
+
+ if (LOCAL_LOGV) {
+ Log.v("ViewRoot", "Surface " + surface + " unlockCanvasAndPost");
+ }
if (scrolling) {
mFullRedrawNeeded = true;
@@ -1401,14 +1391,22 @@ public final class ViewRoot extends Handler implements ViewParent,
void dispatchDetachedFromWindow() {
if (Config.LOGV) Log.v("ViewRoot", "Detaching in " + this + " of " + mSurface);
+
if (mView != null) {
mView.dispatchDetachedFromWindow();
}
+
mView = null;
mAttachInfo.mRootView = null;
+
if (mUseGL) {
destroyGL();
}
+
+ try {
+ sWindowSession.remove(mWindow);
+ } catch (RemoteException e) {
+ }
}
/**
@@ -1609,16 +1607,20 @@ public final class ViewRoot extends Handler implements ViewParent,
}
}
}
+
+ InputMethodManager imm = InputMethodManager.peekInstance();
if (mView != null) {
+ if (hasWindowFocus && imm != null) {
+ imm.startGettingWindowFocus();
+ }
mView.dispatchWindowFocusChanged(hasWindowFocus);
}
// Note: must be done after the focus change callbacks,
// so all of the view state is set up correctly.
if (hasWindowFocus) {
- InputMethodManager imm = InputMethodManager.peekInstance();
if (imm != null) {
- imm.onWindowFocus(mView.findFocus(),
+ imm.onWindowFocus(mView, mView.findFocus(),
mWindowAttributes.softInputMode,
!mHasHadWindowFocus, mWindowAttributes.flags);
}
@@ -2289,10 +2291,6 @@ public final class ViewRoot extends Handler implements ViewParent,
}
if (mAdded) {
mAdded = false;
- try {
- sWindowSession.remove(mWindow);
- } catch (RemoteException e) {
- }
if (immediate) {
dispatchDetachedFromWindow();
} else if (mView != null) {
diff --git a/core/java/android/view/ViewTreeObserver.java b/core/java/android/view/ViewTreeObserver.java
index 05f5fa2a15325..47b52e4a9ad7e 100644
--- a/core/java/android/view/ViewTreeObserver.java
+++ b/core/java/android/view/ViewTreeObserver.java
@@ -35,6 +35,7 @@ public final class ViewTreeObserver {
private ArrayList mOnPreDrawListeners;
private ArrayList mOnTouchModeChangeListeners;
private ArrayList mOnComputeInternalInsetsListeners;
+ private ArrayList mOnScrollChangedListeners;
private boolean mAlive = true;
@@ -98,6 +99,20 @@ public final class ViewTreeObserver {
public void onTouchModeChanged(boolean isInTouchMode);
}
+ /**
+ * Interface definition for a callback to be invoked when
+ * something in the view tree has been scrolled.
+ *
+ * @hide pending API council approval
+ */
+ public interface OnScrollChangedListener {
+ /**
+ * Callback method to be invoked when something in the view tree
+ * has been scrolled.
+ */
+ public void onScrollChanged();
+ }
+
/**
* Parameters used with OnComputeInternalInsetsListener.
* {@hide pending API Council approval}
@@ -360,6 +375,44 @@ public final class ViewTreeObserver {
mOnPreDrawListeners.remove(victim);
}
+ /**
+ * Register a callback to be invoked when a view has been scrolled.
+ *
+ * @param listener The callback to add
+ *
+ * @throws IllegalStateException If {@link #isAlive()} returns false
+ *
+ * @hide pending API council approval
+ */
+ public void addOnScrollChangedListener(OnScrollChangedListener listener) {
+ checkIsAlive();
+
+ if (mOnScrollChangedListeners == null) {
+ mOnScrollChangedListeners = new ArrayList();
+ }
+
+ mOnScrollChangedListeners.add(listener);
+ }
+
+ /**
+ * Remove a previously installed scroll-changed callback
+ *
+ * @param victim The callback to remove
+ *
+ * @throws IllegalStateException If {@link #isAlive()} returns false
+ *
+ * @see #addOnScrollChangedListener(OnScrollChangedListener)
+ *
+ * @hide pending API council approval
+ */
+ public void removeOnScrollChangedListener(OnScrollChangedListener victim) {
+ checkIsAlive();
+ if (mOnScrollChangedListeners == null) {
+ return;
+ }
+ mOnScrollChangedListeners.remove(victim);
+ }
+
/**
* Register a callback to be invoked when the invoked when the touch mode changes.
*
@@ -524,6 +577,19 @@ public final class ViewTreeObserver {
}
}
+ /**
+ * Notifies registered listeners that something has scrolled.
+ */
+ final void dispatchOnScrollChanged() {
+ final ArrayList listeners = mOnScrollChangedListeners;
+
+ if (listeners != null) {
+ for (OnScrollChangedListener scl : mOnScrollChangedListeners) {
+ scl.onScrollChanged();
+ }
+ }
+ }
+
/**
* Returns whether there are listeners for computing internal insets.
*/
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 406af3e3d3846..b87cc42f0e058 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -513,26 +513,33 @@ public interface WindowManager extends ViewManager {
/**
* Visibility state for {@link #softInputMode}: please hide any soft input
- * area.
+ * area when normally appropriate (when the user is navigating
+ * forward to your window).
*/
public static final int SOFT_INPUT_STATE_HIDDEN = 2;
+ /**
+ * Visibility state for {@link #softInputMode}: please always hide any
+ * soft input area when this window receives focus.
+ */
+ public static final int SOFT_INPUT_STATE_ALWAYS_HIDDEN = 3;
+
/**
* Visibility state for {@link #softInputMode}: please show the soft
* input area when normally appropriate (when the user is navigating
* forward to your window).
*/
- public static final int SOFT_INPUT_STATE_VISIBLE = 3;
+ public static final int SOFT_INPUT_STATE_VISIBLE = 4;
/**
* Visibility state for {@link #softInputMode}: please always make the
* soft input area visible when this window receives input focus.
*/
- public static final int SOFT_INPUT_STATE_ALWAYS_VISIBLE = 4;
+ public static final int SOFT_INPUT_STATE_ALWAYS_VISIBLE = 5;
/**
* Mask for {@link #softInputMode} of the bits that determine the
- * way that the window should be adjusted to accomodate the soft
+ * way that the window should be adjusted to accommodate the soft
* input window.
*/
public static final int SOFT_INPUT_MASK_ADJUST = 0xf0;
@@ -633,6 +640,14 @@ public interface WindowManager extends ViewManager {
*/
public float dimAmount = 1.0f;
+ /**
+ * This can be used to override the user's preferred brightness of
+ * the screen. A value of less than 0, the default, means to use the
+ * preferred screen brightness. 0 to 1 adjusts the brightness from
+ * dark to full bright.
+ */
+ public float screenBrightness = -1.0f;
+
/**
* Identifier for this window. This will usually be filled in for
* you.
@@ -729,6 +744,7 @@ public interface WindowManager extends ViewManager {
out.writeInt(windowAnimations);
out.writeFloat(alpha);
out.writeFloat(dimAmount);
+ out.writeFloat(screenBrightness);
out.writeStrongBinder(token);
out.writeString(packageName);
TextUtils.writeToParcel(mTitle, out, parcelableFlags);
@@ -763,6 +779,7 @@ public interface WindowManager extends ViewManager {
windowAnimations = in.readInt();
alpha = in.readFloat();
dimAmount = in.readFloat();
+ screenBrightness = in.readFloat();
token = in.readStrongBinder();
packageName = in.readString();
mTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
@@ -780,6 +797,7 @@ public interface WindowManager extends ViewManager {
public static final int MEMORY_TYPE_CHANGED = 1<<8;
public static final int SOFT_INPUT_MODE_CHANGED = 1<<9;
public static final int SCREEN_ORIENTATION_CHANGED = 1<<10;
+ public static final int SCREEN_BRIGHTNESS_CHANGED = 1<<11;
public final int copyFrom(LayoutParams o) {
int changes = 0;
@@ -874,6 +892,10 @@ public interface WindowManager extends ViewManager {
dimAmount = o.dimAmount;
changes |= DIM_AMOUNT_CHANGED;
}
+ if (screenBrightness != o.screenBrightness) {
+ screenBrightness = o.screenBrightness;
+ changes |= SCREEN_BRIGHTNESS_CHANGED;
+ }
if (screenOrientation != o.screenOrientation) {
screenOrientation = o.screenOrientation;
diff --git a/core/java/android/view/WindowOrientationListener.java b/core/java/android/view/WindowOrientationListener.java
new file mode 100755
index 0000000000000..4aa3f7aa783bc
--- /dev/null
+++ b/core/java/android/view/WindowOrientationListener.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.util.Config;
+import android.util.Log;
+
+/**
+ * A special helper class used by the WindowManager
+ * for receiving notifications from the SensorManager when
+ * the orientation of the device has changed.
+ * @hide
+ */
+public abstract class WindowOrientationListener {
+ private static final String TAG = "WindowOrientationListener";
+ private static final boolean DEBUG = false;
+ private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
+ private int mOrientation = ORIENTATION_UNKNOWN;
+ private SensorManager mSensorManager;
+ private boolean mEnabled = false;
+ private int mRate;
+ private Sensor mSensor;
+ private SensorEventListener mSensorEventListener;
+
+ /**
+ * Returned from onOrientationChanged when the device orientation cannot be determined
+ * (typically when the device is in a close to flat position).
+ *
+ * @see #onOrientationChanged
+ */
+ public static final int ORIENTATION_UNKNOWN = -1;
+ /*
+ * Returned when the device is almost lying flat on a surface
+ */
+ public static final int ORIENTATION_FLAT = -2;
+
+ /**
+ * Creates a new WindowOrientationListener.
+ *
+ * @param context for the WindowOrientationListener.
+ */
+ public WindowOrientationListener(Context context) {
+ this(context, SensorManager.SENSOR_DELAY_NORMAL);
+ }
+
+ /**
+ * Creates a new WindowOrientationListener.
+ *
+ * @param context for the WindowOrientationListener.
+ * @param rate at which sensor events are processed (see also
+ * {@link android.hardware.SensorManager SensorManager}). Use the default
+ * value of {@link android.hardware.SensorManager#SENSOR_DELAY_NORMAL
+ * SENSOR_DELAY_NORMAL} for simple screen orientation change detection.
+ */
+ public WindowOrientationListener(Context context, int rate) {
+ mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
+ mRate = rate;
+ mSensorEventListener = new SensorEventListenerImpl();
+ mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
+ }
+
+ /**
+ * Enables the WindowOrientationListener so it will monitor the sensor and call
+ * {@link #onOrientationChanged} when the device orientation changes.
+ */
+ public void enable() {
+ if (mEnabled == false) {
+ if (localLOGV) Log.d(TAG, "WindowOrientationListener enabled");
+ mSensorManager.registerListener(mSensorEventListener, mSensor, mRate);
+ mEnabled = true;
+ }
+ }
+
+ /**
+ * Disables the WindowOrientationListener.
+ */
+ public void disable() {
+ if (mEnabled == true) {
+ if (localLOGV) Log.d(TAG, "WindowOrientationListener disabled");
+ mSensorManager.unregisterListener(mSensorEventListener);
+ mEnabled = false;
+ }
+ }
+
+ class SensorEventListenerImpl implements SensorEventListener {
+ private static final int _DATA_X = 0;
+ private static final int _DATA_Y = 1;
+ private static final int _DATA_Z = 2;
+
+ public void onSensorChanged(SensorEvent event) {
+ float[] values = event.values;
+ int orientation = ORIENTATION_UNKNOWN;
+ float X = values[_DATA_X];
+ float Y = values[_DATA_Y];
+ float Z = values[_DATA_Z];
+ float OneEightyOverPi = 57.29577957855f;
+ float gravity = (float) Math.sqrt(X*X+Y*Y+Z*Z);
+ float zyangle = Math.abs((float)Math.asin(Z/gravity)*OneEightyOverPi);
+ // The device is considered flat if the angle is more than 75
+ // if the angle is less than 40, its considered too flat to switch
+ // orientation. if the angle is between 40 - 75, the orientation is unknown
+ if (zyangle < 40) {
+ // Check orientation only if the phone is flat enough
+ // Don't trust the angle if the magnitude is small compared to the y value
+ float angle = (float)Math.atan2(Y, -X) * OneEightyOverPi;
+ orientation = 90 - (int)Math.round(angle);
+ // normalize to 0 - 359 range
+ while (orientation >= 360) {
+ orientation -= 360;
+ }
+ while (orientation < 0) {
+ orientation += 360;
+ }
+ } else if (zyangle >= 75){
+ orientation = ORIENTATION_FLAT;
+ }
+
+ if (orientation != mOrientation) {
+ mOrientation = orientation;
+ onOrientationChanged(orientation);
+ }
+ }
+
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+
+ }
+ }
+
+ /**
+ * Called when the orientation of the device has changed.
+ * orientation parameter is in degrees, ranging from 0 to 359.
+ * orientation is 0 degrees when the device is oriented in its natural position,
+ * 90 degrees when its left side is at the top, 180 degrees when it is upside down,
+ * and 270 degrees when its right side is to the top.
+ * {@link #ORIENTATION_UNKNOWN} is returned when the device is close to flat
+ * and the orientation cannot be determined.
+ *
+ * @param orientation The new orientation of the device.
+ *
+ * @see #ORIENTATION_UNKNOWN
+ */
+ abstract public void onOrientationChanged(int orientation);
+}
diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java
index c96b3e5e91948..b9c8ec35637f2 100644
--- a/core/java/android/view/animation/Animation.java
+++ b/core/java/android/view/animation/Animation.java
@@ -179,6 +179,7 @@ public abstract class Animation implements Cloneable {
private boolean mOneMoreTime = true;
RectF mPreviousRegion = new RectF();
+ RectF mRegion = new RectF();
Transformation mTransformation = new Transformation();
Transformation mPreviousTransformation = new Transformation();
@@ -226,6 +227,7 @@ public abstract class Animation implements Cloneable {
protected Animation clone() throws CloneNotSupportedException {
final Animation animation = (Animation) super.clone();
animation.mPreviousRegion = new RectF();
+ animation.mRegion = new RectF();
animation.mTransformation = new Transformation();
animation.mPreviousTransformation = new Transformation();
return animation;
@@ -799,14 +801,15 @@ public abstract class Animation implements Cloneable {
public void getInvalidateRegion(int left, int top, int right, int bottom,
RectF invalidate, Transformation transformation) {
+ final RectF tempRegion = mRegion;
final RectF previousRegion = mPreviousRegion;
invalidate.set(left, top, right, bottom);
transformation.getMatrix().mapRect(invalidate);
+ tempRegion.set(invalidate);
invalidate.union(previousRegion);
- previousRegion.set(left, top, right, bottom);
- transformation.getMatrix().mapRect(previousRegion);
+ previousRegion.set(tempRegion);
final Transformation tempTransformation = mTransformation;
final Transformation previousTransformation = mPreviousTransformation;
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index 9509b15317ebe..6fbc174bab49d 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -525,9 +525,6 @@ public class BaseInputConnection implements InputConnection {
setComposingSpans(sp);
}
- // Adjust newCursorPosition to be relative the start of the text.
- newCursorPosition += a;
-
if (DEBUG) Log.v(TAG, "Replacing from " + a + " to " + b + " with \""
+ text + "\", composing=" + composing
+ ", type=" + text.getClass().getCanonicalName());
@@ -540,11 +537,21 @@ public class BaseInputConnection implements InputConnection {
TextUtils.dumpSpans(text, lp, " ");
}
- content.replace(a, b, text);
+ // Position the cursor appropriately, so that after replacing the
+ // desired range of text it will be located in the correct spot.
+ // This allows us to deal with filters performing edits on the text
+ // we are providing here.
+ if (newCursorPosition > 0) {
+ newCursorPosition += b - 1;
+ } else {
+ newCursorPosition += a;
+ }
if (newCursorPosition < 0) newCursorPosition = 0;
if (newCursorPosition > content.length())
newCursorPosition = content.length();
Selection.setSelection(content, newCursorPosition);
+
+ content.replace(a, b, text);
if (DEBUG) {
LogPrinter lp = new LogPrinter(Log.VERBOSE, TAG);
diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
index 13173f656397f..530127d1eceee 100644
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ b/core/java/android/view/inputmethod/InputConnection.java
@@ -148,8 +148,14 @@ public interface InputConnection {
* object to the text. {#link android.text.SpannableString} and
* {#link android.text.SpannableStringBuilder} are two
* implementations of the interface {#link android.text.Spanned}.
- * @param newCursorPosition The new cursor position within the
- * text.
+ * @param newCursorPosition The new cursor position around the text. If
+ * > 0, this is relative to the end of the text - 1; if <= 0, this
+ * is relative to the start of the text. So a value of 1 will
+ * always advance you to the position after the full text being
+ * inserted. Note that this means you can't position the cursor
+ * within the text, because the editor can make modifications to
+ * the text you are providing so it is not possible to correctly
+ * specify locations there.
*
* @return Returns true on success, false if the input connection is no longer
* valid.
@@ -170,8 +176,14 @@ public interface InputConnection {
* automatically.
*
* @param text The committed text.
- * @param newCursorPosition The new cursor position within the
- * text.
+ * @param newCursorPosition The new cursor position around the text. If
+ * > 0, this is relative to the end of the text - 1; if <= 0, this
+ * is relative to the start of the text. So a value of 1 will
+ * always advance you to the position after the full text being
+ * inserted. Note that this means you can't position the cursor
+ * within the text, because the editor can make modifications to
+ * the text you are providing so it is not possible to correctly
+ * specify locations there.
*
*
* @return Returns true on success, false if the input connection is no longer
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index fe1416680620d..91fa2115d272a 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -226,6 +226,10 @@ public final class InputMethodManager {
* regardless of the state of setting that up.
*/
View mServedView;
+ /*
+ * Keep track of the view that was set when our window gained focus.
+ */
+ View mWindowFocusedView;
/**
* For evaluating the state after a focus change, this is the view that
* had focus.
@@ -466,8 +470,8 @@ public final class InputMethodManager {
}
/** @hide */
- public void setFullscreenMode(boolean enabled) {
- mFullscreenMode = true;
+ public void setFullscreenMode(boolean fullScreen) {
+ mFullscreenMode = fullScreen;
}
/**
@@ -828,19 +832,23 @@ public final class InputMethodManager {
*/
public void focusIn(View view) {
synchronized (mH) {
- if (DEBUG) Log.v(TAG, "focusIn: " + view);
- // Okay we have a new view that is being served.
- if (mServedView != view) {
- mCurrentTextBoxAttribute = null;
- }
- mServedView = view;
- mCompletions = null;
- mServedConnecting = true;
+ focusInLocked(view);
}
startInputInner();
}
+ void focusInLocked(View view) {
+ if (DEBUG) Log.v(TAG, "focusIn: " + view);
+ // Okay we have a new view that is being served.
+ if (mServedView != view) {
+ mCurrentTextBoxAttribute = null;
+ }
+ mServedView = view;
+ mCompletions = null;
+ mServedConnecting = true;
+ }
+
/**
* Call this when a view loses focus.
* @hide
@@ -908,16 +916,28 @@ public final class InputMethodManager {
* Called by ViewRoot the first time it gets window focus.
* @hide
*/
- public void onWindowFocus(View focusedView, int softInputMode,
+ public void onWindowFocus(View rootView, View focusedView, int softInputMode,
boolean first, int windowFlags) {
+ boolean needStartInput = false;
synchronized (mH) {
if (DEBUG) Log.v(TAG, "onWindowFocus: " + focusedView
+ " softInputMode=" + softInputMode
+ " first=" + first + " flags=#"
+ Integer.toHexString(windowFlags));
+ if (mWindowFocusedView == null) {
+ focusInLocked(focusedView != null ? focusedView : rootView);
+ needStartInput = true;
+ }
+ }
+
+ if (needStartInput) {
+ startInputInner();
+ }
+
+ synchronized (mH) {
try {
final boolean isTextEditor = focusedView != null &&
- focusedView.onCheckIsTextEditor();
+ focusedView.onCheckIsTextEditor();
mService.windowGainedFocus(mClient, focusedView != null,
isTextEditor, softInputMode, first, windowFlags);
} catch (RemoteException e) {
@@ -925,6 +945,13 @@ public final class InputMethodManager {
}
}
+ /** @hide */
+ public void startGettingWindowFocus() {
+ synchronized (mH) {
+ mWindowFocusedView = null;
+ }
+ }
+
/**
* Report the current selection range.
*/
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 1dd37be06493f..451af6d047cf9 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -51,7 +51,7 @@ class BrowserFrame extends Handler {
private final Context mContext;
private final WebViewDatabase mDatabase;
private final WebViewCore mWebViewCore;
- private boolean mLoadInitFromJava;
+ /* package */ boolean mLoadInitFromJava;
private int mLoadType;
private boolean mFirstLayoutDone = true;
private boolean mCommitted = true;
diff --git a/core/java/android/webkit/LoadListener.java b/core/java/android/webkit/LoadListener.java
index 36949695b50ae..dfae17da6da14 100644
--- a/core/java/android/webkit/LoadListener.java
+++ b/core/java/android/webkit/LoadListener.java
@@ -575,7 +575,7 @@ class LoadListener extends Handler implements EventHandler {
mRequestHandle.getMethod().equals("POST")) {
sendMessageInternal(obtainMessage(
MSG_LOCATION_CHANGED_REQUEST));
- } else if (mMethod.equals("POST")) {
+ } else if (mMethod != null && mMethod.equals("POST")) {
sendMessageInternal(obtainMessage(
MSG_LOCATION_CHANGED_REQUEST));
} else {
diff --git a/core/java/android/webkit/TextDialog.java b/core/java/android/webkit/TextDialog.java
index 9af30c5b740c1..c2620a512e4f2 100644
--- a/core/java/android/webkit/TextDialog.java
+++ b/core/java/android/webkit/TextDialog.java
@@ -290,6 +290,25 @@ import java.util.ArrayList;
return false;
}
+ /**
+ * Create a fake touch up event at (x,y) with respect to this TextDialog.
+ * This is used by WebView to act as though a touch event which happened
+ * before we placed the TextDialog actually hit it, so that it can place
+ * the cursor accordingly.
+ */
+ /* package */ void fakeTouchEvent(float x, float y) {
+ // We need to ensure that there is a Layout, since the Layout is used
+ // in determining where to place the cursor.
+ if (getLayout() == null) {
+ measure(mWidthSpec, mHeightSpec);
+ }
+ // Create a fake touch up, which is used to place the cursor.
+ MotionEvent ev = MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP,
+ x, y, 0);
+ onTouchEvent(ev);
+ ev.recycle();
+ }
+
/**
* Determine whether this TextDialog currently represents the node
* represented by ptr.
@@ -461,9 +480,8 @@ import java.util.ArrayList;
*/
public void setAdapterCustom(AutoCompleteAdapter adapter) {
if (adapter != null) {
- adapter.setTextView(this);
- } else {
setInputType(EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE);
+ adapter.setTextView(this);
}
super.setAdapter(adapter);
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index bdbf38a703693..4d9a8fbafda55 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -45,6 +45,8 @@ import android.util.AttributeSet;
import android.util.Config;
import android.util.Log;
import android.view.animation.AlphaAnimation;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -234,6 +236,9 @@ public class WebView extends AbsoluteLayout
*/
VelocityTracker mVelocityTracker;
+ private static boolean mShowZoomRingTutorial = true;
+ private static final int ZOOM_RING_TUTORIAL_DURATION = 3000;
+
/**
* Touch mode
*/
@@ -284,9 +289,7 @@ public class WebView extends AbsoluteLayout
// In the browser, if it switches out of tap too soon, jump tap won't work.
private static final int TAP_TIMEOUT = 200;
// The duration in milliseconds we will wait to see if it is a double tap.
- // With a limited survey, the time between the first tap up and the second
- // tap down in the double tap case is around 70ms - 120ms.
- private static final int DOUBLE_TAP_TIMEOUT = 200;
+ private static final int DOUBLE_TAP_TIMEOUT = 250;
// This should be ViewConfiguration.getLongPressTimeout()
// But system time out is 500ms, which is too short for the browser.
// With a short timeout, it's difficult to treat trigger a short press.
@@ -315,6 +318,9 @@ public class WebView extends AbsoluteLayout
private int mContentWidth; // cache of value from WebViewCore
private int mContentHeight; // cache of value from WebViewCore
+ static int MAX_FLOAT_CONTENT_WIDTH = 480;
+ private int mMinContentWidth;
+
// Need to have the separate control for horizontal and vertical scrollbar
// style than the View's single scrollbar style
private boolean mOverlayHorizontalScrollbar = true;
@@ -348,6 +354,7 @@ public class WebView extends AbsoluteLayout
private static final int UPDATE_TEXT_ENTRY_ADAPTER = 6;
private static final int SWITCH_TO_ENTER = 7;
private static final int RESUME_WEBCORE_UPDATE = 8;
+ private static final int DISMISS_ZOOM_RING_TUTORIAL = 9;
//! arg1=x, arg2=y
static final int SCROLL_TO_MSG_ID = 10;
@@ -370,12 +377,46 @@ public class WebView extends AbsoluteLayout
static final int WEBCORE_NEED_TOUCH_EVENTS = 25;
// obj=Rect in doc coordinates
static final int INVAL_RECT_MSG_ID = 26;
+
+ static final String[] HandlerDebugString = {
+ "REMEMBER_PASSWORD", // = 1;
+ "NEVER_REMEMBER_PASSWORD", // = 2;
+ "SWITCH_TO_SHORTPRESS", // = 3;
+ "SWITCH_TO_LONGPRESS", // = 4;
+ "RELEASE_SINGLE_TAP", // = 5;
+ "UPDATE_TEXT_ENTRY_ADAPTER", // = 6;
+ "SWITCH_TO_ENTER", // = 7;
+ "RESUME_WEBCORE_UPDATE", // = 8;
+ "9",
+ "SCROLL_TO_MSG_ID", // = 10;
+ "SCROLL_BY_MSG_ID", // = 11;
+ "SPAWN_SCROLL_TO_MSG_ID", // = 12;
+ "SYNC_SCROLL_TO_MSG_ID", // = 13;
+ "NEW_PICTURE_MSG_ID", // = 14;
+ "UPDATE_TEXT_ENTRY_MSG_ID", // = 15;
+ "WEBCORE_INITIALIZED_MSG_ID", // = 16;
+ "UPDATE_TEXTFIELD_TEXT_MSG_ID", // = 17;
+ "DID_FIRST_LAYOUT_MSG_ID", // = 18;
+ "RECOMPUTE_FOCUS_MSG_ID", // = 19;
+ "NOTIFY_FOCUS_SET_MSG_ID", // = 20;
+ "MARK_NODE_INVALID_ID", // = 21;
+ "UPDATE_CLIPBOARD", // = 22;
+ "LONG_PRESS_ENTER", // = 23;
+ "PREVENT_TOUCH_ID", // = 24;
+ "WEBCORE_NEED_TOUCH_EVENTS", // = 25;
+ "INVAL_RECT_MSG_ID" // = 26;
+ };
// width which view is considered to be fully zoomed out
static final int ZOOM_OUT_WIDTH = 1024;
- private static final float DEFAULT_MAX_ZOOM_SCALE = 4;
- private static final float DEFAULT_MIN_ZOOM_SCALE = 0.25f;
+ private static final float MAX_ZOOM_RING_ANGLE = (float) (Math.PI * 2 / 3);
+ private static final int ZOOM_RING_STEPS = 4;
+ private static final float ZOOM_RING_ANGLE_UNIT = MAX_ZOOM_RING_ANGLE
+ / ZOOM_RING_STEPS;
+
+ private static final float DEFAULT_MAX_ZOOM_SCALE = 2;
+ private static final float DEFAULT_MIN_ZOOM_SCALE = (float) 1/3;
// scale limit, which can be set through viewport meta tag in the web page
private float mMaxZoomScale = DEFAULT_MAX_ZOOM_SCALE;
private float mMinZoomScale = DEFAULT_MIN_ZOOM_SCALE;
@@ -505,6 +546,8 @@ public class WebView extends AbsoluteLayout
}
private ZoomRingController mZoomRingController;
+ private ImageView mZoomRingOverview;
+ private Animation mZoomRingOverviewExitAnimation;
// These keep track of the center point of the zoom ring. They are used to
// determine the point around which we should zoom.
@@ -519,51 +562,83 @@ public class WebView extends AbsoluteLayout
// in this callback
}
+ public void onBeginPan() {
+ setZoomOverviewVisible(false);
+ }
+
public boolean onPan(int deltaX, int deltaY) {
return pinScrollBy(deltaX, deltaY, false, 0);
}
+ public void onEndPan() {
+ }
+
public void onVisibilityChanged(boolean visible) {
if (visible) {
- mZoomControls.show(false, canZoomScrollOut());
- } else {
- mZoomControls.hide();
+ switchOutDrawHistory();
+ float angle = 0f;
+ if (mActualScale > 1) {
+ angle = -(float) Math.round(ZOOM_RING_STEPS
+ * (mActualScale - 1) / (mMaxZoomScale - 1))
+ / ZOOM_RING_STEPS;
+ } else if (mActualScale < 1) {
+ angle = (float) Math.round(ZOOM_RING_STEPS
+ * (1 - mActualScale) / (1 - mMinZoomScale))
+ / ZOOM_RING_STEPS;
+ }
+ mZoomRingController.setThumbAngle(angle * MAX_ZOOM_RING_ANGLE);
+
+ // Show the zoom overview tab on the ring
+ setZoomOverviewVisible(true);
}
}
-
- public void onBeginDrag(float startAngle) {
+
+ public void onBeginDrag() {
mPreviewZoomOnly = true;
+ setZoomOverviewVisible(false);
}
- public void onEndDrag(float endAngle) {
+ public void onEndDrag() {
mPreviewZoomOnly = false;
setNewZoomScale(mActualScale, true);
}
public boolean onDragZoom(int deltaZoomLevel, int centerX,
int centerY, float startAngle, float curAngle) {
-
- if (mZoomScale == mMinZoomScale && deltaZoomLevel < 0 ||
- mZoomScale == mMaxZoomScale && deltaZoomLevel > 0 ||
- deltaZoomLevel == 0) {
+ if (deltaZoomLevel < 0
+ && Math.abs(mActualScale - mMinZoomScale) < 0.01f
+ || deltaZoomLevel > 0
+ && Math.abs(mActualScale - mMaxZoomScale) < 0.01f
+ || deltaZoomLevel == 0) {
return false;
}
mZoomCenterX = (float) centerX;
mZoomCenterY = (float) centerY;
- while (deltaZoomLevel != 0) {
- if (deltaZoomLevel > 0) {
- if (!zoomIn()) return false;
- deltaZoomLevel--;
+ float scale = 1.0f;
+ if (curAngle > (float) Math.PI)
+ curAngle -= (float) 2 * Math.PI;
+ if (curAngle > 0) {
+ if (curAngle >= MAX_ZOOM_RING_ANGLE) {
+ scale = mMinZoomScale;
} else {
- if (!zoomOut()) return false;
- deltaZoomLevel++;
+ scale = 1 - (float) Math.round(curAngle
+ / ZOOM_RING_ANGLE_UNIT) / ZOOM_RING_STEPS
+ * (1 - mMinZoomScale);
+ }
+ } else if (curAngle < 0) {
+ if (curAngle <= -MAX_ZOOM_RING_ANGLE) {
+ scale = mMaxZoomScale;
+ } else {
+ scale = 1 + (float) Math.round(-curAngle
+ / ZOOM_RING_ANGLE_UNIT) / ZOOM_RING_STEPS
+ * (mMaxZoomScale - 1);
}
}
-
+ zoomWithPreview(scale);
return true;
}
-
+
public void onSimpleZoom(boolean zoomIn) {
if (zoomIn) {
zoomIn();
@@ -571,6 +646,7 @@ public class WebView extends AbsoluteLayout
zoomOut();
}
}
+
};
/**
@@ -610,7 +686,14 @@ public class WebView extends AbsoluteLayout
mFocusData.mY = 0;
mScroller = new Scroller(context);
mZoomRingController = new ZoomRingController(context, this);
+ mZoomRingController.setResetThumbAutomatically(false);
+ mZoomRingController.setThumbClockwiseBound(
+ (float) (2 * Math.PI - MAX_ZOOM_RING_ANGLE));
+ mZoomRingController.setThumbCounterclockwiseBound(MAX_ZOOM_RING_ANGLE);
mZoomRingController.setCallback(mZoomListener);
+ mZoomRingController.setZoomRingTrack(
+ com.android.internal.R.drawable.zoom_ring_track_absolute);
+ createZoomRingOverviewTab();
}
private void init() {
@@ -625,6 +708,63 @@ public class WebView extends AbsoluteLayout
mMinLockSnapReverseDistance = slop;
}
+ private void createZoomRingOverviewTab() {
+ Context context = getContext();
+
+ mZoomRingOverviewExitAnimation = AnimationUtils.loadAnimation(context,
+ com.android.internal.R.anim.fade_out);
+
+ mZoomRingOverview = new ImageView(context);
+ mZoomRingOverview.setBackgroundResource(
+ com.android.internal.R.drawable.zoom_ring_overview_tab);
+ mZoomRingOverview.setImageResource(com.android.internal.R.drawable.btn_zoom_page);
+
+ FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
+ FrameLayout.LayoutParams.WRAP_CONTENT,
+ FrameLayout.LayoutParams.WRAP_CONTENT,
+ Gravity.CENTER);
+ // TODO: magic constant that's based on the zoom ring radius + some offset
+ lp.topMargin = 208;
+ mZoomRingOverview.setLayoutParams(lp);
+ mZoomRingOverview.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ // Hide the zoom ring
+ mZoomRingController.setVisible(false);
+ zoomScrollOut();
+ }});
+
+ // Measure the overview View to figure out its height
+ mZoomRingOverview.forceLayout();
+ mZoomRingOverview.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
+ MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
+
+ ViewGroup container = mZoomRingController.getContainer();
+ // Find the index of the zoom ring in the container
+ View zoomRing = container.findViewById(mZoomRingController.getZoomRingId());
+ int zoomRingIndex;
+ for (zoomRingIndex = container.getChildCount() - 1; zoomRingIndex >= 0; zoomRingIndex--) {
+ if (container.getChildAt(zoomRingIndex) == zoomRing) break;
+ }
+ // Add the overview tab below the zoom ring (so we don't steal its events)
+ container.addView(mZoomRingOverview, zoomRingIndex);
+ // Since we use margins to adjust the vertical placement of the tab, the widget
+ // ends up getting clipped off. Ensure the container is big enough for
+ // us.
+ int myHeight = mZoomRingOverview.getMeasuredHeight() + lp.topMargin / 2;
+ // Multiplied by 2 b/c the zoom ring needs to be centered on the screen
+ container.setMinimumHeight(myHeight * 2);
+ }
+
+ private void setZoomOverviewVisible(boolean visible) {
+ int newVisibility = visible ? View.VISIBLE : View.INVISIBLE;
+ if (mZoomRingOverview.getVisibility() == newVisibility) return;
+
+ if (!visible) {
+ mZoomRingOverview.startAnimation(mZoomRingOverviewExitAnimation);
+ }
+ mZoomRingOverview.setVisibility(newVisibility);
+ }
+
/* package */ boolean onSavePassword(String schemePlusHost, String username,
String password, final Message resumeMsg) {
boolean rVal = false;
@@ -1653,7 +1793,8 @@ public class WebView extends AbsoluteLayout
* @return true if new values were sent
*/
private boolean sendViewSizeZoom() {
- int newWidth = Math.round(getViewWidth() * mInvActualScale);
+ int viewWidth = getViewWidth();
+ int newWidth = Math.round(viewWidth * mInvActualScale);
int newHeight = Math.round(getViewHeight() * mInvActualScale);
/*
* Because the native side may have already done a layout before the
@@ -1669,7 +1810,7 @@ public class WebView extends AbsoluteLayout
// Avoid sending another message if the dimensions have not changed.
if (newWidth != mLastWidthSent || newHeight != mLastHeightSent) {
mWebViewCore.sendMessage(EventHub.VIEW_SIZE_CHANGED,
- newWidth, newHeight, new Float(mActualScale));
+ newWidth, newHeight, new Integer(viewWidth));
mLastWidthSent = newWidth;
mLastHeightSent = newHeight;
return true;
@@ -1968,7 +2109,7 @@ public class WebView extends AbsoluteLayout
// Scale from content to view coordinates, and pin.
// Also called by jni webview.cpp
- private void setContentScrollBy(int cx, int cy) {
+ private void setContentScrollBy(int cx, int cy, boolean animate) {
if (mDrawHistory) {
// disallow WebView to change the scroll position as History Picture
// is used in the view system.
@@ -1992,10 +2133,10 @@ public class WebView extends AbsoluteLayout
// vertical scroll?
// Log.d(LOGTAG, "setContentScrollBy cy=" + cy);
if (cy == 0 && cx != 0) {
- pinScrollBy(cx, 0, true, 0);
+ pinScrollBy(cx, 0, animate, 0);
}
} else {
- pinScrollBy(cx, cy, true, 0);
+ pinScrollBy(cx, cy, animate, 0);
}
}
@@ -2205,7 +2346,8 @@ public class WebView extends AbsoluteLayout
// state.
// If mNativeClass is 0, we should not reach here, so we do not
// need to check it again.
- nativeRecordButtons(mTouchMode == TOUCH_SHORTPRESS_START_MODE
+ nativeRecordButtons(hasFocus() && hasWindowFocus(),
+ mTouchMode == TOUCH_SHORTPRESS_START_MODE
|| mTrackballDown || mGotEnterDown, false);
drawCoreAndFocusRing(canvas, mBackgroundColor, mDrawFocusRing);
}
@@ -2254,6 +2396,8 @@ public class WebView extends AbsoluteLayout
invalidate();
} else {
zoomScale = mZoomScale;
+ // set mZoomScale to be 0 as we have done animation
+ mZoomScale = 0;
}
float scale = (mActualScale - zoomScale) * mInvActualScale;
float tx = scale * (mZoomCenterX + mScrollX);
@@ -2775,6 +2919,17 @@ public class WebView extends AbsoluteLayout
getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(mTextEntry, 0);
mTextEntry.enableScrollOnScreen(true);
+ // Now we need to fake a touch event to place the cursor where the
+ // user touched.
+ AbsoluteLayout.LayoutParams lp = (AbsoluteLayout.LayoutParams)
+ mTextEntry.getLayoutParams();
+ if (lp != null) {
+ // Take the last touch and adjust for the location of the
+ // TextDialog.
+ float x = mLastTouchX - lp.x;
+ float y = mLastTouchY - lp.y;
+ mTextEntry.fakeTouchEvent(x, y);
+ }
}
private void updateTextEntry() {
@@ -2987,7 +3142,9 @@ public class WebView extends AbsoluteLayout
mGotEnterDown = true;
mPrivateHandler.sendMessageDelayed(mPrivateHandler
.obtainMessage(LONG_PRESS_ENTER), LONG_PRESS_TIMEOUT);
- nativeRecordButtons(true, true);
+ // Already checked mNativeClass, so we do not need to check it
+ // again.
+ nativeRecordButtons(hasFocus() && hasWindowFocus(), true, true);
return true;
}
// Bubble up the key event as WebView doesn't handle it
@@ -3198,6 +3355,9 @@ public class WebView extends AbsoluteLayout
ViewGroup p = (ViewGroup) parent;
p.setOnHierarchyChangeListener(null);
}
+
+ // Clean up the zoom ring
+ mZoomRingController.setVisible(false);
}
// Implementation for OnHierarchyChangeListener
@@ -3234,16 +3394,25 @@ public class WebView extends AbsoluteLayout
if (mNeedsUpdateTextEntry) {
updateTextEntry();
}
+ if (mNativeClass != 0) {
+ nativeRecordButtons(true, false, true);
+ }
} else {
// If our window gained focus, but we do not have it, do not
// draw the focus ring.
mDrawFocusRing = false;
+ // We do not call nativeRecordButtons here because we assume
+ // that when we lost focus, or window focus, it got called with
+ // false for the first parameter
}
} else {
// If our window has lost focus, stop drawing the focus ring
mDrawFocusRing = false;
mGotKeyDown = false;
mShiftIsPressed = false;
+ if (mNativeClass != 0) {
+ nativeRecordButtons(false, false, true);
+ }
}
invalidate();
super.onWindowFocusChanged(hasWindowFocus);
@@ -3264,12 +3433,22 @@ public class WebView extends AbsoluteLayout
updateTextEntry();
mNeedsUpdateTextEntry = false;
}
+ if (mNativeClass != 0) {
+ nativeRecordButtons(true, false, true);
+ }
+ //} else {
+ // The WebView has gained focus while we do not have
+ // windowfocus. When our window lost focus, we should have
+ // called nativeRecordButtons(false...)
}
} else {
// When we lost focus, unless focus went to the TextView (which is
// true if we are in editing mode), stop drawing the focus ring.
if (!inEditingMode()) {
mDrawFocusRing = false;
+ if (mNativeClass != 0) {
+ nativeRecordButtons(false, false, true);
+ }
}
mGotKeyDown = false;
}
@@ -3285,6 +3464,22 @@ public class WebView extends AbsoluteLayout
// the new zoom ring controller
mZoomCenterX = getViewWidth() * .5f;
mZoomCenterY = getViewHeight() * .5f;
+
+ // update mMinZoomScale
+ if (mMinContentWidth > MAX_FLOAT_CONTENT_WIDTH) {
+ boolean atMin = Math.abs(mActualScale - mMinZoomScale) < 0.01f;
+ mMinZoomScale = (float) getViewWidth() / mMinContentWidth;
+ if (atMin) {
+ // if the WebView was at the minimum zoom scale, keep it. e,g.,
+ // the WebView was at the minimum zoom scale at the portrait
+ // mode, rotate it to the landscape modifying the scale to the
+ // new minimum zoom scale, when rotating back, we would like to
+ // keep the minimum zoom scale instead of keeping the same scale
+ // as normally we do.
+ mActualScale = mMinZoomScale;
+ }
+ }
+
// we always force, in case our height changed, in which case we still
// want to send the notification over to webkit
setNewZoomScale(mActualScale, true);
@@ -3340,6 +3535,14 @@ public class WebView extends AbsoluteLayout
return false;
}
+ if (mShowZoomRingTutorial && mMinZoomScale < mMaxZoomScale) {
+ ZoomRingController.showZoomTutorialOnce(mContext);
+ mShowZoomRingTutorial = false;
+ mPrivateHandler.sendMessageDelayed(mPrivateHandler
+ .obtainMessage(DISMISS_ZOOM_RING_TUTORIAL),
+ ZOOM_RING_TUTORIAL_DURATION);
+ }
+
if (LOGV_ENABLED) {
Log.v(LOGTAG, ev + " at " + ev.getEventTime() + " mTouchMode="
+ mTouchMode);
@@ -3749,7 +3952,7 @@ public class WebView extends AbsoluteLayout
mPrivateHandler.removeMessages(SWITCH_TO_ENTER);
mTrackballDown = true;
if (mNativeClass != 0) {
- nativeRecordButtons(true, true);
+ nativeRecordButtons(hasFocus() && hasWindowFocus(), true, true);
}
if (time - mLastFocusTime <= TRACKBALL_TIMEOUT
&& !mLastFocusBounds.equals(nativeGetFocusRingBounds())) {
@@ -4148,6 +4351,9 @@ public class WebView extends AbsoluteLayout
});
zoomControls.setOnZoomMagnifyClickListener(new OnClickListener() {
public void onClick(View v) {
+ // Hide the zoom ring
+ mZoomRingController.setVisible(false);
+
mPrivateHandler.removeCallbacks(mZoomControlRunnable);
mPrivateHandler.postDelayed(mZoomControlRunnable,
ZOOM_CONTROLS_TIMEOUT);
@@ -4200,6 +4406,12 @@ public class WebView extends AbsoluteLayout
}
}
+ // Called by JNI to handle a touch on a node representing an email address,
+ // address, or phone number
+ private void overrideLoading(String url) {
+ mCallbackProxy.uiOverrideUrlLoading(url);
+ }
+
@Override
public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
boolean result = false;
@@ -4372,6 +4584,11 @@ public class WebView extends AbsoluteLayout
class PrivateHandler extends Handler {
@Override
public void handleMessage(Message msg) {
+ if (LOGV_ENABLED) {
+ Log.v(LOGTAG, msg.what < REMEMBER_PASSWORD || msg.what
+ > INVAL_RECT_MSG_ID ? Integer.toString(msg.what)
+ : HandlerDebugString[msg.what - REMEMBER_PASSWORD]);
+ }
switch (msg.what) {
case REMEMBER_PASSWORD: {
mDatabase.setUsernamePassword(
@@ -4413,7 +4630,7 @@ public class WebView extends AbsoluteLayout
, KeyEvent.KEYCODE_ENTER));
break;
case SCROLL_BY_MSG_ID:
- setContentScrollBy(msg.arg1, msg.arg2);
+ setContentScrollBy(msg.arg1, msg.arg2, (Boolean) msg.obj);
break;
case SYNC_SCROLL_TO_MSG_ID:
if (mUserScroll) {
@@ -4451,6 +4668,11 @@ public class WebView extends AbsoluteLayout
0, 0);
}
}
+ mMinContentWidth = msg.arg1;
+ if (mMinContentWidth > MAX_FLOAT_CONTENT_WIDTH) {
+ mMinZoomScale = (float) getViewWidth()
+ / mMinContentWidth;
+ }
// We update the layout (i.e. request a layout from the
// view system) if the last view size that we sent to
// WebCore matches the view size of the picture we just
@@ -4638,6 +4860,10 @@ public class WebView extends AbsoluteLayout
}
break;
+ case DISMISS_ZOOM_RING_TUTORIAL:
+ mZoomRingController.finishZoomTutorial();
+ break;
+
default:
super.handleMessage(msg);
break;
@@ -5018,8 +5244,8 @@ public class WebView extends AbsoluteLayout
private native void nativeRecomputeFocus();
// Like many other of our native methods, you must make sure that
// mNativeClass is not null before calling this method.
- private native void nativeRecordButtons(boolean pressed,
- boolean invalidate);
+ private native void nativeRecordButtons(boolean focused,
+ boolean pressed, boolean invalidate);
private native void nativeResetFocus();
private native void nativeResetNavClipBounds();
private native void nativeSelectBestAt(Rect rect);
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index b979032f55dea..45113ab000b7f 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -270,6 +270,11 @@ final class WebViewCore {
static native String nativeFindAddress(String addr);
+ /**
+ * Rebuild the nav cache if the dom changed.
+ */
+ private native void nativeCheckNavCache();
+
/**
* Empty the picture set.
*/
@@ -317,7 +322,7 @@ final class WebViewCore {
should this be called nativeSetViewPortSize?
*/
private native void nativeSetSize(int width, int height, int screenWidth,
- float scale);
+ float scale, int realScreenWidth, int screenHeight);
private native int nativeGetContentMinPrefWidth();
@@ -501,6 +506,51 @@ final class WebViewCore {
int mY;
}
+ static final String[] HandlerDebugString = {
+ "LOAD_URL", // = 100;
+ "STOP_LOADING", // = 101;
+ "RELOAD", // = 102;
+ "KEY_DOWN", // = 103;
+ "KEY_UP", // = 104;
+ "VIEW_SIZE_CHANGED", // = 105;
+ "GO_BACK_FORWARD", // = 106;
+ "SET_SCROLL_OFFSET", // = 107;
+ "RESTORE_STATE", // = 108;
+ "PAUSE_TIMERS", // = 109;
+ "RESUME_TIMERS", // = 110;
+ "CLEAR_CACHE", // = 111;
+ "CLEAR_HISTORY", // = 112;
+ "SET_SELECTION", // = 113;
+ "REPLACE_TEXT", // = 114;
+ "PASS_TO_JS", // = 115;
+ "SET_GLOBAL_BOUNDS", // = 116;
+ "UPDATE_CACHE_AND_TEXT_ENTRY", // = 117;
+ "CLICK", // = 118;
+ "119",
+ "DOC_HAS_IMAGES", // = 120;
+ "SET_SNAP_ANCHOR", // = 121;
+ "DELETE_SELECTION", // = 122;
+ "LISTBOX_CHOICES", // = 123;
+ "SINGLE_LISTBOX_CHOICE", // = 124;
+ "125",
+ "SET_BACKGROUND_COLOR", // = 126;
+ "UNBLOCK_FOCUS", // = 127;
+ "SAVE_DOCUMENT_STATE", // = 128;
+ "GET_SELECTION", // = 129;
+ "WEBKIT_DRAW", // = 130;
+ "SYNC_SCROLL", // = 131;
+ "REFRESH_PLUGINS", // = 132;
+ "SPLIT_PICTURE_SET", // = 133;
+ "CLEAR_CONTENT", // = 134;
+ "SET_FINAL_FOCUS", // = 135;
+ "SET_KIT_FOCUS", // = 136;
+ "REQUEST_FOCUS_HREF", // = 137;
+ "ADD_JS_INTERFACE", // = 138;
+ "LOAD_DATA", // = 139;
+ "TOUCH_UP", // = 140;
+ "TOUCH_EVENT", // = 141;
+ };
+
class EventHub {
// Message Ids
static final int LOAD_URL = 100;
@@ -595,6 +645,11 @@ final class WebViewCore {
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
+ if (LOGV_ENABLED) {
+ Log.v(LOGTAG, msg.what < LOAD_URL || msg.what
+ > TOUCH_EVENT ? Integer.toString(msg.what)
+ : HandlerDebugString[msg.what - LOAD_URL]);
+ }
switch (msg.what) {
case WEBKIT_DRAW:
webkitDraw();
@@ -675,7 +730,7 @@ final class WebViewCore {
case VIEW_SIZE_CHANGED:
viewSizeChanged(msg.arg1, msg.arg2,
- ((Float) msg.obj).floatValue());
+ ((Integer) msg.obj).intValue());
break;
case SET_SCROLL_OFFSET:
@@ -1131,12 +1186,22 @@ final class WebViewCore {
private int mCurrentViewWidth = 0;
private int mCurrentViewHeight = 0;
+ // Define a minimum screen width so that we won't wrap the paragraph to one
+ // word per line during zoom-in.
+ private static final int MIN_SCREEN_WIDTH = 160;
+
// notify webkit that our virtual view size changed size (after inv-zoom)
- private void viewSizeChanged(int w, int h, float scale) {
+ private void viewSizeChanged(int w, int h, int viewWidth) {
if (LOGV_ENABLED) Log.v(LOGTAG, "CORE onSizeChanged");
+ if (w == 0) {
+ Log.w(LOGTAG, "skip viewSizeChanged as w is 0");
+ return;
+ }
+ float scale = (float) viewWidth / w;
if (mSettings.getUseWideViewPort()
&& (w < mViewportWidth || mViewportWidth == -1)) {
int width = mViewportWidth;
+ int screenWidth = Math.max(w, MIN_SCREEN_WIDTH);
if (mViewportWidth == -1) {
if (mSettings.getLayoutAlgorithm() ==
WebSettings.LayoutAlgorithm.NORMAL) {
@@ -1154,12 +1219,21 @@ final class WebViewCore {
* In the worse case, the native width will be adjusted when
* next zoom or screen orientation change happens.
*/
- width = Math.max(w, nativeGetContentMinPrefWidth());
+ int minContentWidth = nativeGetContentMinPrefWidth();
+ if (minContentWidth > WebView.MAX_FLOAT_CONTENT_WIDTH) {
+ // keep the same width and screen width so that there is
+ // no reflow when zoom-out
+ width = minContentWidth;
+ screenWidth = Math.min(screenWidth, viewWidth);
+ } else {
+ width = Math.max(w, minContentWidth);
+ }
}
}
- nativeSetSize(width, Math.round((float) width * h / w), w, scale);
+ nativeSetSize(width, Math.round((float) width * h / w),
+ screenWidth, scale, w, h);
} else {
- nativeSetSize(w, h, w, scale);
+ nativeSetSize(w, h, w, scale, w, h);
}
// Remember the current width and height
boolean needInvalidate = (mCurrentViewWidth == 0);
@@ -1219,7 +1293,9 @@ final class WebViewCore {
draw.mViewPoint = new Point(mCurrentViewWidth, mCurrentViewHeight);
if (LOGV_ENABLED) Log.v(LOGTAG, "webkitDraw NEW_PICTURE_MSG_ID");
Message.obtain(mWebView.mPrivateHandler,
- WebView.NEW_PICTURE_MSG_ID, draw).sendToTarget();
+ WebView.NEW_PICTURE_MSG_ID, nativeGetContentMinPrefWidth(),
+ 0, draw).sendToTarget();
+ nativeCheckNavCache();
if (mWebkitScrollX != 0 || mWebkitScrollY != 0) {
// as we have the new picture, try to sync the scroll position
Message.obtain(mWebView.mPrivateHandler,
@@ -1324,7 +1400,9 @@ final class WebViewCore {
for (int i = 0; i < size; i++) {
list.getItemAtIndex(i).inflate(mBrowserFrame.mNativeFrame);
}
+ mBrowserFrame.mLoadInitFromJava = true;
list.restoreIndex(mBrowserFrame.mNativeFrame, index);
+ mBrowserFrame.mLoadInitFromJava = false;
}
//-------------------------------------------------------------------------
@@ -1349,14 +1427,15 @@ final class WebViewCore {
}
// called by JNI
- private void contentScrollBy(int dx, int dy) {
+ private void contentScrollBy(int dx, int dy, boolean animate) {
if (!mBrowserFrame.firstLayoutDone()) {
// Will this happen? If yes, we need to do something here.
return;
}
if (mWebView != null) {
Message.obtain(mWebView.mPrivateHandler,
- WebView.SCROLL_BY_MSG_ID, dx, dy).sendToTarget();
+ WebView.SCROLL_BY_MSG_ID, dx, dy,
+ new Boolean(animate)).sendToTarget();
}
}
@@ -1461,7 +1540,7 @@ final class WebViewCore {
// current scale
mEventHub.sendMessage(Message.obtain(null,
EventHub.VIEW_SIZE_CHANGED, mWebView.mLastWidthSent,
- mWebView.mLastHeightSent, -1.0f));
+ mWebView.mLastHeightSent, new Integer(-1)));
}
mBrowserFrame.didFirstLayout();
diff --git a/core/java/android/webkit/gears/HttpRequestAndroid.java b/core/java/android/webkit/gears/HttpRequestAndroid.java
deleted file mode 100644
index 30f855f0c892b..0000000000000
--- a/core/java/android/webkit/gears/HttpRequestAndroid.java
+++ /dev/null
@@ -1,745 +0,0 @@
-// Copyright 2008, The Android Open Source Project
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// 2. 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.
-// 3. Neither the name of Google Inc. nor the names of its contributors may be
-// used to endorse or promote products derived from this software without
-// specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
-
-package android.webkit.gears;
-
-import android.net.http.Headers;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.util.Log;
-import android.webkit.CacheManager;
-import android.webkit.CacheManager.CacheResult;
-import android.webkit.CookieManager;
-
-import org.apache.http.conn.ssl.StrictHostnameVerifier;
-import org.apache.http.impl.cookie.DateUtils;
-import org.apache.http.util.CharArrayBuffer;
-
-import java.io.*;
-import java.net.*;
-import java.util.*;
-import javax.net.ssl.*;
-
-/**
- * Performs the underlying HTTP/HTTPS GET and POST requests.
- *
These are performed synchronously (blocking). The caller should
- * ensure that it is in a background thread if asynchronous behavior
- * is required. All data is pushed, so there is no need for JNI native
- * callbacks.
- *
This uses the java.net.HttpURLConnection class to perform most
- * of the underlying network activity. The Android brower's cache,
- * android.webkit.CacheManager, is also used when caching is enabled,
- * and updated with new data. The android.webkit.CookieManager is also
- * queried and updated as necessary.
- *
The public interface is designed to be called by native code
- * through JNI, and to simplify coding none of the public methods will
- * surface a checked exception. Unchecked exceptions may still be
- * raised but only if the system is in an ill state, such as out of
- * memory.
- *
TODO: This isn't plumbed into LocalServer yet. Mutually
- * dependent on LocalServer - will attach the two together once both
- * are submitted.
- */
-public final class HttpRequestAndroid {
- /** Debug logging tag. */
- private static final String LOG_TAG = "Gears-J";
- /** HTTP response header line endings are CR-LF style. */
- private static final String HTTP_LINE_ENDING = "\r\n";
- /** Safe MIME type to use whenever it isn't specified. */
- private static final String DEFAULT_MIME_TYPE = "text/plain";
- /** Case-sensitive header keys */
- public static final String KEY_CONTENT_LENGTH = "Content-Length";
- public static final String KEY_EXPIRES = "Expires";
- public static final String KEY_LAST_MODIFIED = "Last-Modified";
- public static final String KEY_ETAG = "ETag";
- public static final String KEY_LOCATION = "Location";
- public static final String KEY_CONTENT_TYPE = "Content-Type";
- /** Number of bytes to send and receive on the HTTP connection in
- * one go. */
- private static final int BUFFER_SIZE = 4096;
- /** The first element of the String[] value in a headers map is the
- * unmodified (case-sensitive) key. */
- public static final int HEADERS_MAP_INDEX_KEY = 0;
- /** The second element of the String[] value in a headers map is the
- * associated value. */
- public static final int HEADERS_MAP_INDEX_VALUE = 1;
-
- /** Enable/disable all logging in this class. */
- private static boolean logEnabled = false;
- /** The underlying HTTP or HTTPS network connection. */
- private HttpURLConnection connection;
- /** HTTP body stream, setup after connection. */
- private InputStream inputStream;
- /** The complete response line e.g "HTTP/1.0 200 OK" */
- private String responseLine;
- /** Request headers, as a lowercase key -> [ unmodified key, value ] map. */
- private Map requestHeaders =
- new HashMap();
- /** Response headers, as a lowercase key -> [ unmodified key, value ] map. */
- private Map responseHeaders;
- /** True if the child thread is in performing blocking IO. */
- private boolean inBlockingOperation = false;
- /** True when the thread acknowledges the abort. */
- private boolean abortReceived = false;
- /** The URL used for createCacheResult() */
- private String cacheResultUrl;
- /** CacheResult being saved into, if inserting a new cache entry. */
- private CacheResult cacheResult;
- /** Initialized by initChildThread(). Used to target abort(). */
- private Thread childThread;
-
- /**
- * Convenience debug function. Calls Android logging mechanism.
- * @param str String to log to the Android console.
- */
- private static void log(String str) {
- if (logEnabled) {
- Log.i(LOG_TAG, str);
- }
- }
-
- /**
- * Turn on/off logging in this class.
- * @param on Logging enable state.
- */
- public static void enableLogging(boolean on) {
- logEnabled = on;
- }
-
- /**
- * Initialize childThread using the TLS value of
- * Thread.currentThread(). Called on start up of the native child
- * thread.
- */
- public synchronized void initChildThread() {
- childThread = Thread.currentThread();
- }
-
- /**
- * Analagous to the native-side HttpRequest::open() function. This
- * initializes an underlying java.net.HttpURLConnection, but does
- * not go to the wire. On success, this enables a call to send() to
- * initiate the transaction.
- *
- * @param method The HTTP method, e.g GET or POST.
- * @param url The URL to open.
- * @return True on success with a complete HTTP response.
- * False on failure.
- */
- public synchronized boolean open(String method, String url) {
- if (logEnabled)
- log("open " + method + " " + url);
- // Reset the response between calls to open().
- inputStream = null;
- responseLine = null;
- responseHeaders = null;
- if (!method.equals("GET") && !method.equals("POST")) {
- log("Method " + method + " not supported");
- return false;
- }
- // Setup the connection. This doesn't go to the wire yet - it
- // doesn't block.
- try {
- URL url_object = new URL(url);
- // Check that the protocol is indeed HTTP(S).
- String protocol = url_object.getProtocol();
- if (protocol == null) {
- log("null protocol for URL " + url);
- return false;
- }
- protocol = protocol.toLowerCase();
- if (!"http".equals(protocol) && !"https".equals(protocol)) {
- log("Url has wrong protocol: " + url);
- return false;
- }
-
- connection = (HttpURLConnection) url_object.openConnection();
- connection.setRequestMethod(method);
- // Manually follow redirects.
- connection.setInstanceFollowRedirects(false);
- // Manually cache.
- connection.setUseCaches(false);
- // Enable data output in POST method requests.
- connection.setDoOutput(method.equals("POST"));
- // Enable data input in non-HEAD method requests.
- // TODO: HEAD requests not tested.
- connection.setDoInput(!method.equals("HEAD"));
- if (connection instanceof javax.net.ssl.HttpsURLConnection) {
- // Verify the certificate matches the origin.
- ((HttpsURLConnection) connection).setHostnameVerifier(
- new StrictHostnameVerifier());
- }
- return true;
- } catch (IOException e) {
- log("Got IOException in open: " + e.toString());
- return false;
- }
- }
-
- /**
- * Interrupt a blocking IO operation. This will cause the child
- * thread to expediently return from an operation if it was stuck at
- * the time. Note that this inherently races, and unfortunately
- * requires the caller to loop.
- */
- public synchronized void interrupt() {
- if (childThread == null) {
- log("interrupt() called but no child thread");
- return;
- }
- synchronized (this) {
- if (inBlockingOperation) {
- log("Interrupting blocking operation");
- childThread.interrupt();
- } else {
- log("Nothing to interrupt");
- }
- }
- }
-
- /**
- * Set a header to send with the HTTP request. Will not take effect
- * on a transaction already in progress. The key is associated
- * case-insensitive, but stored case-sensitive.
- * @param name The name of the header, e.g "Set-Cookie".
- * @param value The value for this header, e.g "text/html".
- */
- public synchronized void setRequestHeader(String name, String value) {
- String[] mapValue = { name, value };
- requestHeaders.put(name.toLowerCase(), mapValue);
- }
-
- /**
- * Returns the value associated with the given request header.
- * @param name The name of the request header, non-null, case-insensitive.
- * @return The value associated with the request header, or null if
- * not set, or error.
- */
- public synchronized String getRequestHeader(String name) {
- String[] value = requestHeaders.get(name.toLowerCase());
- if (value != null) {
- return value[HEADERS_MAP_INDEX_VALUE];
- } else {
- return null;
- }
- }
-
- /**
- * Returns the value associated with the given response header.
- * @param name The name of the response header, non-null, case-insensitive.
- * @return The value associated with the response header, or null if
- * not set or error.
- */
- public synchronized String getResponseHeader(String name) {
- if (responseHeaders != null) {
- String[] value = responseHeaders.get(name.toLowerCase());
- if (value != null) {
- return value[HEADERS_MAP_INDEX_VALUE];
- } else {
- return null;
- }
- } else {
- log("getResponseHeader() called but response not received");
- return null;
- }
- }
-
- /**
- * Set a response header and associated value. The key is associated
- * case-insensitively, but stored case-sensitively.
- * @param name Case sensitive request header key.
- * @param value The associated value.
- */
- private void setResponseHeader(String name, String value) {
- if (logEnabled)
- log("Set response header " + name + ": " + value);
- String mapValue[] = { name, value };
- responseHeaders.put(name.toLowerCase(), mapValue);
- }
-
- /**
- * Apply the contents of the Map requestHeaders to the connection
- * object. Calls to setRequestHeader() after this will not affect
- * the connection.
- */
- private synchronized void applyRequestHeadersToConnection() {
- Iterator it = requestHeaders.values().iterator();
- while (it.hasNext()) {
- // Set the key case-sensitive.
- String[] entry = it.next();
- connection.setRequestProperty(
- entry[HEADERS_MAP_INDEX_KEY],
- entry[HEADERS_MAP_INDEX_VALUE]);
- }
- }
-
- /**
- * Return all response headers, separated by CR-LF line endings, and
- * ending with a trailing blank line. This mimics the format of the
- * raw response header up to but not including the body.
- * @return A string containing the entire response header.
- */
- public synchronized String getAllResponseHeaders() {
- if (responseHeaders == null) {
- log("getAllResponseHeaders() called but response not received");
- return null;
- }
- String result = new String();
- Iterator it = responseHeaders.values().iterator();
- while (it.hasNext()) {
- String[] entry = it.next();
- // Output the "key: value" lines.
- result += entry[HEADERS_MAP_INDEX_KEY] + ": "
- + entry[HEADERS_MAP_INDEX_VALUE] + HTTP_LINE_ENDING;
- }
- result += HTTP_LINE_ENDING;
- return result;
- }
-
- /**
- * Get the complete response line of the HTTP request. Only valid on
- * completion of the transaction.
- * @return The complete HTTP response line, e.g "HTTP/1.0 200 OK".
- */
- public synchronized String getResponseLine() {
- return responseLine;
- }
-
- /**
- * Get the cookie for the given URL.
- * @param url The fully qualified URL.
- * @return A string containing the cookie for the URL if it exists,
- * or null if not.
- */
- public static String getCookieForUrl(String url) {
- // Get the cookie for this URL, set as a header
- return CookieManager.getInstance().getCookie(url);
- }
-
- /**
- * Set the cookie for the given URL.
- * @param url The fully qualified URL.
- * @param cookie The new cookie value.
- * @return A string containing the cookie for the URL if it exists,
- * or null if not.
- */
- public static void setCookieForUrl(String url, String cookie) {
- // Get the cookie for this URL, set as a header
- CookieManager.getInstance().setCookie(url, cookie);
- }
-
- /**
- * Perform a request using LocalServer if possible. Initializes
- * class members so that receive() will obtain data from the stream
- * provided by the response.
- * @param url The fully qualified URL to try in LocalServer.
- * @return True if the url was found and is now setup to receive.
- * False if not found, with no side-effect.
- */
- public synchronized boolean useLocalServerResult(String url) {
- UrlInterceptHandlerGears handler = UrlInterceptHandlerGears.getInstance();
- if (handler == null) {
- return false;
- }
- UrlInterceptHandlerGears.ServiceResponse serviceResponse =
- handler.getServiceResponse(url, requestHeaders);
- if (serviceResponse == null) {
- log("No response in LocalServer");
- return false;
- }
- // LocalServer will handle this URL. Initialize stream and
- // response.
- inputStream = serviceResponse.getInputStream();
- responseLine = serviceResponse.getStatusLine();
- responseHeaders = serviceResponse.getResponseHeaders();
- if (logEnabled)
- log("Got response from LocalServer: " + responseLine);
- return true;
- }
-
- /**
- * Perform a request using the cache result if present. Initializes
- * class members so that receive() will obtain data from the cache.
- * @param url The fully qualified URL to try in the cache.
- * @return True is the url was found and is now setup to receive
- * from cache. False if not found, with no side-effect.
- */
- public synchronized boolean useCacheResult(String url) {
- // Try the browser's cache. CacheManager wants a Map.
- Map cacheRequestHeaders = new HashMap();
- Iterator> it =
- requestHeaders.entrySet().iterator();
- while (it.hasNext()) {
- Map.Entry entry = it.next();
- cacheRequestHeaders.put(
- entry.getKey(),
- entry.getValue()[HEADERS_MAP_INDEX_VALUE]);
- }
- CacheResult cacheResult =
- CacheManager.getCacheFile(url, cacheRequestHeaders);
- if (cacheResult == null) {
- if (logEnabled)
- log("No CacheResult for " + url);
- return false;
- }
- if (logEnabled)
- log("Got CacheResult from browser cache");
- // Check for expiry. -1 is "never", otherwise milliseconds since 1970.
- // Can be compared to System.currentTimeMillis().
- long expires = cacheResult.getExpires();
- if (expires >= 0 && System.currentTimeMillis() >= expires) {
- log("CacheResult expired "
- + (System.currentTimeMillis() - expires)
- + " milliseconds ago");
- // Cache hit has expired. Do not return it.
- return false;
- }
- // Setup the inputStream to come from the cache.
- inputStream = cacheResult.getInputStream();
- if (inputStream == null) {
- // Cache result may have gone away.
- log("No inputStream for CacheResult " + url);
- return false;
- }
- // Cache hit. Parse headers.
- synthesizeHeadersFromCacheResult(cacheResult);
- return true;
- }
-
- /**
- * Take the limited set of headers in a CacheResult and synthesize
- * response headers.
- * @param cacheResult A CacheResult to populate responseHeaders with.
- */
- private void synthesizeHeadersFromCacheResult(CacheResult cacheResult) {
- int statusCode = cacheResult.getHttpStatusCode();
- // The status message is informal, so we can greatly simplify it.
- String statusMessage;
- if (statusCode >= 200 && statusCode < 300) {
- statusMessage = "OK";
- } else if (statusCode >= 300 && statusCode < 400) {
- statusMessage = "MOVED";
- } else {
- statusMessage = "UNAVAILABLE";
- }
- // Synthesize the response line.
- responseLine = "HTTP/1.1 " + statusCode + " " + statusMessage;
- if (logEnabled)
- log("Synthesized " + responseLine);
- // Synthesize the returned headers from cache.
- responseHeaders = new HashMap();
- String contentLength = Long.toString(cacheResult.getContentLength());
- setResponseHeader(KEY_CONTENT_LENGTH, contentLength);
- long expires = cacheResult.getExpires();
- if (expires >= 0) {
- // "Expires" header is valid and finite. Milliseconds since 1970
- // epoch, formatted as RFC-1123.
- String expiresString = DateUtils.formatDate(new Date(expires));
- setResponseHeader(KEY_EXPIRES, expiresString);
- }
- String lastModified = cacheResult.getLastModified();
- if (lastModified != null) {
- // Last modification time of the page. Passed end-to-end, but
- // not used by us.
- setResponseHeader(KEY_LAST_MODIFIED, lastModified);
- }
- String eTag = cacheResult.getETag();
- if (eTag != null) {
- // Entity tag. A kind of GUID to identify identical resources.
- setResponseHeader(KEY_ETAG, eTag);
- }
- String location = cacheResult.getLocation();
- if (location != null) {
- // If valid, refers to the location of a redirect.
- setResponseHeader(KEY_LOCATION, location);
- }
- String mimeType = cacheResult.getMimeType();
- if (mimeType == null) {
- // Use a safe default MIME type when none is
- // specified. "text/plain" is safe to render in the browser
- // window (even if large) and won't be intepreted as anything
- // that would cause execution.
- mimeType = DEFAULT_MIME_TYPE;
- }
- String encoding = cacheResult.getEncoding();
- // Encoding may not be specified. No default.
- String contentType = mimeType;
- if (encoding != null && encoding.length() > 0) {
- contentType += "; charset=" + encoding;
- }
- setResponseHeader(KEY_CONTENT_TYPE, contentType);
- }
-
- /**
- * Create a CacheResult for this URL. This enables the repsonse body
- * to be sent in calls to appendCacheResult().
- * @param url The fully qualified URL to add to the cache.
- * @param responseCode The response code returned for the request, e.g 200.
- * @param mimeType The MIME type of the body, e.g "text/plain".
- * @param encoding The encoding, e.g "utf-8". Use "" for unknown.
- */
- public synchronized boolean createCacheResult(
- String url, int responseCode, String mimeType, String encoding) {
- if (logEnabled)
- log("Making cache entry for " + url);
- // Take the headers and parse them into a format needed by
- // CacheManager.
- Headers cacheHeaders = new Headers();
- Iterator> it =
- responseHeaders.entrySet().iterator();
- while (it.hasNext()) {
- Map.Entry entry = it.next();
- // Headers.parseHeader() expects lowercase keys.
- String keyValue = entry.getKey() + ": "
- + entry.getValue()[HEADERS_MAP_INDEX_VALUE];
- CharArrayBuffer buffer = new CharArrayBuffer(keyValue.length());
- buffer.append(keyValue);
- // Parse it into the header container.
- cacheHeaders.parseHeader(buffer);
- }
- cacheResult = CacheManager.createCacheFile(
- url, responseCode, cacheHeaders, mimeType, true);
- if (cacheResult != null) {
- if (logEnabled)
- log("Saving into cache");
- cacheResult.setEncoding(encoding);
- cacheResultUrl = url;
- return true;
- } else {
- log("Couldn't create cacheResult");
- return false;
- }
- }
-
- /**
- * Add data from the response body to the CacheResult created with
- * createCacheResult().
- * @param data A byte array of the next sequential bytes in the
- * response body.
- * @param bytes The number of bytes to write from the start of
- * the array.
- * @return True if all bytes successfully written, false on failure.
- */
- public synchronized boolean appendCacheResult(byte[] data, int bytes) {
- if (cacheResult == null) {
- log("appendCacheResult() called without a CacheResult initialized");
- return false;
- }
- try {
- cacheResult.getOutputStream().write(data, 0, bytes);
- } catch (IOException ex) {
- log("Got IOException writing cache data: " + ex);
- return false;
- }
- return true;
- }
-
- /**
- * Save the completed CacheResult into the CacheManager. This must
- * have been created first with createCacheResult().
- * @return Returns true if the entry has been successfully saved.
- */
- public synchronized boolean saveCacheResult() {
- if (cacheResult == null || cacheResultUrl == null) {
- log("Tried to save cache result but createCacheResult not called");
- return false;
- }
- if (logEnabled)
- log("Saving cache result");
- CacheManager.saveCacheFile(cacheResultUrl, cacheResult);
- cacheResult = null;
- cacheResultUrl = null;
- return true;
- }
-
- /**
- * Perform an HTTP request on the network. The underlying
- * HttpURLConnection is connected to the remote server and the
- * response headers are received.
- * @return True if the connection succeeded and headers have been
- * received. False on connection failure.
- */
- public boolean connectToRemote() {
- synchronized (this) {
- // Transfer a snapshot of our internally maintained map of request
- // headers to the connection object.
- applyRequestHeadersToConnection();
- // Note blocking I/O so abort() can interrupt us.
- inBlockingOperation = true;
- }
- boolean success;
- try {
- if (logEnabled)
- log("Connecting to remote");
- connection.connect();
- if (logEnabled)
- log("Connected");
- success = true;
- } catch (IOException e) {
- log("Got IOException in connect(): " + e.toString());
- success = false;
- } finally {
- synchronized (this) {
- // No longer blocking.
- inBlockingOperation = false;
- }
- }
- return success;
- }
-
- /**
- * Receive all headers from the server and populate
- * responseHeaders. This converts from the slightly odd format
- * returned by java.net.HttpURLConnection to a simpler
- * java.util.Map.
- * @return True if headers are successfully received, False on
- * connection error.
- */
- public synchronized boolean parseHeaders() {
- responseHeaders = new HashMap();
- /* HttpURLConnection contains a null terminated list of
- * key->value response pairs. If the key is null, then the value
- * contains the complete status line. If both key and value are
- * null for an index, we've reached the end.
- */
- for (int i = 0; ; ++i) {
- String key = connection.getHeaderFieldKey(i);
- String value = connection.getHeaderField(i);
- if (logEnabled)
- log("header " + key + " -> " + value);
- if (key == null && value == null) {
- // End of list.
- break;
- } else if (key == null) {
- // The pair with null key has the complete status line in
- // the value, e.g "HTTP/1.0 200 OK".
- responseLine = value;
- } else if (value != null) {
- // If key and value are non-null, this is a response pair, e.g
- // "Content-Length" -> "5". Use setResponseHeader() to
- // correctly deal with case-insensitivity of the key.
- setResponseHeader(key, value);
- } else {
- // The key is non-null but value is null. Unexpected
- // condition.
- return false;
- }
- }
- return true;
- }
-
- /**
- * Receive the next sequential bytes of the response body after
- * successful connection. This will receive up to the size of the
- * provided byte array. If there is no body, this will return 0
- * bytes on the first call after connection.
- * @param buf A pre-allocated byte array to receive data into.
- * @return The number of bytes from the start of the array which
- * have been filled, 0 on EOF, or negative on error.
- */
- public int receive(byte[] buf) {
- if (inputStream == null) {
- // If this is the first call, setup the InputStream. This may
- // fail if there were headers, but no body returned by the
- // server.
- try {
- inputStream = connection.getInputStream();
- } catch (IOException inputException) {
- log("Failed to connect InputStream: " + inputException);
- // Not unexpected. For example, 404 response return headers,
- // and sometimes a body with a detailed error. Try the error
- // stream.
- inputStream = connection.getErrorStream();
- if (inputStream == null) {
- // No error stream either. Treat as a 0 byte response.
- log("No InputStream");
- return 0; // EOF.
- }
- }
- }
- synchronized (this) {
- // Note blocking I/O so abort() can interrupt us.
- inBlockingOperation = true;
- }
- int ret;
- try {
- int got = inputStream.read(buf);
- if (got > 0) {
- // Got some bytes, not EOF.
- ret = got;
- } else {
- // EOF.
- inputStream.close();
- ret = 0;
- }
- } catch (IOException e) {
- // An abort() interrupts us by calling close() on our stream.
- log("Got IOException in inputStream.read(): " + e.toString());
- ret = -1;
- } finally {
- synchronized (this) {
- // No longer blocking.
- inBlockingOperation = false;
- }
- }
- return ret;
- }
-
- /**
- * For POST method requests, send a stream of data provided by the
- * native side in repeated callbacks.
- * @param data A byte array containing the data to sent, or null
- * if indicating EOF.
- * @param bytes The number of bytes from the start of the array to
- * send, or 0 if indicating EOF.
- * @return True if all bytes were successfully sent, false on error.
- */
- public boolean sendPostData(byte[] data, int bytes) {
- synchronized (this) {
- // Note blocking I/O so abort() can interrupt us.
- inBlockingOperation = true;
- }
- boolean success;
- try {
- OutputStream outputStream = connection.getOutputStream();
- if (data == null && bytes == 0) {
- outputStream.close();
- } else {
- outputStream.write(data, 0, bytes);
- }
- success = true;
- } catch (IOException e) {
- log("Got IOException in post: " + e.toString());
- success = false;
- } finally {
- synchronized (this) {
- // No longer blocking.
- inBlockingOperation = false;
- }
- }
- return success;
- }
-}
diff --git a/core/java/android/webkit/gears/UrlInterceptHandlerGears.java b/core/java/android/webkit/gears/UrlInterceptHandlerGears.java
index 288240ea8e2ac..2a5cbe99e15c0 100644
--- a/core/java/android/webkit/gears/UrlInterceptHandlerGears.java
+++ b/core/java/android/webkit/gears/UrlInterceptHandlerGears.java
@@ -64,11 +64,11 @@ public class UrlInterceptHandlerGears implements UrlInterceptHandler {
/** The unmodified (case-sensitive) key in the headers map is the
* same index as used by HttpRequestAndroid. */
public static final int HEADERS_MAP_INDEX_KEY =
- HttpRequestAndroid.HEADERS_MAP_INDEX_KEY;
+ ApacheHttpRequestAndroid.HEADERS_MAP_INDEX_KEY;
/** The associated value in the headers map is the same index as
* used by HttpRequestAndroid. */
public static final int HEADERS_MAP_INDEX_VALUE =
- HttpRequestAndroid.HEADERS_MAP_INDEX_VALUE;
+ ApacheHttpRequestAndroid.HEADERS_MAP_INDEX_VALUE;
/**
* Object passed to the native side, containing information about
@@ -382,7 +382,7 @@ public class UrlInterceptHandlerGears implements UrlInterceptHandler {
// browser's cache for too long.
long now_ms = System.currentTimeMillis();
String expires = DateUtils.formatDate(new Date(now_ms + CACHE_EXPIRY_MS));
- response.setResponseHeader(HttpRequestAndroid.KEY_EXPIRES, expires);
+ response.setResponseHeader(ApacheHttpRequestAndroid.KEY_EXPIRES, expires);
// The browser is only interested in a small subset of headers,
// contained in a Headers object. Iterate the map of all headers
// and add them to Headers.
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index c012e25cf0c55..f362e2202c5e5 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -41,7 +41,7 @@ import android.view.ViewConfiguration;
import android.view.ViewDebug;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
-import android.view.WindowManagerImpl;
+import android.view.inputmethod.InputMethodManager;
import android.view.ContextMenu.ContextMenuInfo;
import com.android.internal.R;
@@ -425,6 +425,8 @@ public abstract class AbsListView extends AdapterView implements Te
private int mTouchSlop;
+ private float mDensityScale;
+
/**
* Interface definition for a callback to be invoked when the list or grid
* has been scrolled.
@@ -567,7 +569,7 @@ public abstract class AbsListView extends AdapterView implements Te
*/
@Override
protected boolean isVerticalScrollBarHidden() {
- return mFastScroller != null ? mFastScroller.isVisible() : false;
+ return mFastScroller != null && mFastScroller.isVisible();
}
/**
@@ -709,6 +711,7 @@ public abstract class AbsListView extends AdapterView implements Te
setScrollingCacheEnabled(true);
mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
+ mDensityScale = getContext().getResources().getDisplayMetrics().density;
}
private void useDefaultSelector() {
@@ -891,14 +894,26 @@ public abstract class AbsListView extends AdapterView implements Te
}
// Don't restore the type filter window when there is no keyboard
- int keyboardHidden = getContext().getResources().getConfiguration().keyboardHidden;
- if (keyboardHidden != Configuration.KEYBOARDHIDDEN_YES) {
+ if (acceptFilter()) {
String filterText = ss.filter;
setFilterText(filterText);
}
+
requestLayout();
}
+ private boolean acceptFilter() {
+ final Context context = mContext;
+ final Configuration configuration = context.getResources().getConfiguration();
+ final boolean keyboardShowing = configuration.keyboardHidden !=
+ Configuration.KEYBOARDHIDDEN_YES;
+ final boolean hasKeyboard = configuration.keyboard != Configuration.KEYBOARD_NOKEYS;
+ final InputMethodManager inputManager = (InputMethodManager)
+ context.getSystemService(Context.INPUT_METHOD_SERVICE);
+ return (hasKeyboard && keyboardShowing) ||
+ (!hasKeyboard && !inputManager.isFullscreenMode());
+ }
+
/**
* Sets the initial value for the text filter.
* @param filterText The text to use for the filter.
@@ -906,6 +921,7 @@ public abstract class AbsListView extends AdapterView implements Te
* @see #setTextFilterEnabled
*/
public void setFilterText(String filterText) {
+ // TODO: Should we check for acceptFilter()?
if (mTextFilterEnabled && filterText != null && filterText.length() > 0) {
createTextFilter(false);
// This is going to call our listener onTextChanged, but we might not
@@ -1076,6 +1092,24 @@ public abstract class AbsListView extends AdapterView implements Te
mInLayout = false;
}
+ /**
+ * @hide
+ */
+ @Override
+ protected boolean setFrame(int left, int top, int right, int bottom) {
+ final boolean changed = super.setFrame(left, top, right, bottom);
+
+ // Reposition the popup when the frame has changed. This includes
+ // translating the widget, not just changing its dimension. The
+ // filter popup needs to follow the widget.
+ if (mFiltered && changed && getWindowVisibility() == View.VISIBLE && mPopup != null &&
+ mPopup.isShowing()) {
+ positionPopup(true);
+ }
+
+ return changed;
+ }
+
protected void layoutChildren() {
}
@@ -2587,10 +2621,12 @@ public abstract class AbsListView extends AdapterView implements Te
clearScrollingCache();
mSpecificTop = selectedTop;
selectedPos = lookForSelectablePosition(selectedPos, down);
- if (selectedPos >= 0) {
+ if (selectedPos >= firstPosition && selectedPos <= getLastVisiblePosition()) {
mLayoutMode = LAYOUT_SPECIFIC;
setSelectionInt(selectedPos);
invokeOnItemScrollListener();
+ } else {
+ selectedPos = INVALID_POSITION;
}
reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
@@ -2727,19 +2763,27 @@ public abstract class AbsListView extends AdapterView implements Te
private void showPopup() {
// Make sure we have a window before showing the popup
if (getWindowVisibility() == View.VISIBLE) {
- int screenHeight = WindowManagerImpl.getDefault().getDefaultDisplay().getHeight();
- final int[] xy = new int[2];
- getLocationOnScreen(xy);
- // TODO: The 20 below should come from the theme and be expressed in dip
- final float scale = getContext().getResources().getDisplayMetrics().density;
- int bottomGap = screenHeight - xy[1] - getHeight() + (int) (scale * 20);
- mPopup.showAtLocation(this, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL,
- xy[0], bottomGap);
+ positionPopup(false);
// Make sure we get focus if we are showing the popup
checkFocus();
}
}
+ private void positionPopup(boolean update) {
+ int screenHeight = getResources().getDisplayMetrics().heightPixels;
+ final int[] xy = new int[2];
+ getLocationOnScreen(xy);
+ // TODO: The 20 below should come from the theme and be expressed in dip
+ // TODO: And the gravity should be defined in the theme as well
+ final int bottomGap = screenHeight - xy[1] - getHeight() + (int) (mDensityScale * 20);
+ if (!update) {
+ mPopup.showAtLocation(this, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL,
+ xy[0], bottomGap);
+ } else {
+ mPopup.update(xy[0], bottomGap, -1, -1);
+ }
+ }
+
/**
* What is the distance between the source and destination rectangles given the direction of
* focus navigation between them? The direction basically helps figure out more quickly what is
@@ -2831,7 +2875,7 @@ public abstract class AbsListView extends AdapterView implements Te
break;
}
- if (okToSend) {
+ if (okToSend && acceptFilter()) {
createTextFilter(true);
KeyEvent forwardEvent = event;
@@ -2873,6 +2917,7 @@ public abstract class AbsListView extends AdapterView implements Te
mTextFilter.addTextChangedListener(this);
p.setFocusable(false);
p.setTouchable(false);
+ p.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
p.setContentView(mTextFilter);
p.setWidth(LayoutParams.WRAP_CONTENT);
p.setHeight(LayoutParams.WRAP_CONTENT);
diff --git a/core/java/android/widget/Chronometer.java b/core/java/android/widget/Chronometer.java
index 7086ae2510bb1..369221e8789ac 100644
--- a/core/java/android/widget/Chronometer.java
+++ b/core/java/android/widget/Chronometer.java
@@ -46,6 +46,18 @@ import java.util.Locale;
public class Chronometer extends TextView {
private static final String TAG = "Chronometer";
+ /**
+ * A callback that notifies when the chronometer has incremented on its own.
+ */
+ public interface OnChronometerTickListener {
+
+ /**
+ * Notification that the chronometer has changed.
+ */
+ void onChronometerTick(Chronometer chronometer);
+
+ }
+
private long mBase;
private boolean mVisible;
private boolean mStarted;
@@ -56,6 +68,7 @@ public class Chronometer extends TextView {
private Locale mFormatterLocale;
private Object[] mFormatterArgs = new Object[1];
private StringBuilder mFormatBuilder;
+ private OnChronometerTickListener mOnChronometerTickListener;
/**
* Initialize this Chronometer object.
@@ -99,6 +112,7 @@ public class Chronometer extends TextView {
*
* @param base Use the {@link SystemClock#elapsedRealtime} time base.
*/
+ @android.view.RemotableViewMethod
public void setBase(long base) {
mBase = base;
updateText(SystemClock.elapsedRealtime());
@@ -122,6 +136,7 @@ public class Chronometer extends TextView {
*
* @param format the format string.
*/
+ @android.view.RemotableViewMethod
public void setFormat(String format) {
mFormat = format;
if (format != null && mFormatBuilder == null) {
@@ -136,6 +151,23 @@ public class Chronometer extends TextView {
return mFormat;
}
+ /**
+ * Sets the listener to be called when the chronometer changes.
+ *
+ * @param listener The listener.
+ */
+ public void setOnChronometerTickListener(OnChronometerTickListener listener) {
+ mOnChronometerTickListener = listener;
+ }
+
+ /**
+ * @return The listener (may be null) that is listening for chronometer change
+ * events.
+ */
+ public OnChronometerTickListener getOnChronometerTickListener() {
+ return mOnChronometerTickListener;
+ }
+
/**
* Start counting up. This does not affect the base as set from {@link #setBase}, just
* the view display.
@@ -161,6 +193,15 @@ public class Chronometer extends TextView {
updateRunning();
}
+ /**
+ * The same as calling {@link #start} or {@link #stop}.
+ */
+ @android.view.RemotableViewMethod
+ public void setStarted(boolean started) {
+ mStarted = started;
+ updateRunning();
+ }
+
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
@@ -216,8 +257,15 @@ public class Chronometer extends TextView {
public void handleMessage(Message m) {
if (mStarted) {
updateText(SystemClock.elapsedRealtime());
+ dispatchChronometerTick();
sendMessageDelayed(Message.obtain(), 1000);
}
}
};
+
+ void dispatchChronometerTick() {
+ if (mOnChronometerTickListener != null) {
+ mOnChronometerTickListener.onChronometerTick(this);
+ }
+ }
}
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index b4ed3bad9a5a5..8aafee2118f9c 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -93,6 +93,7 @@ public class FrameLayout extends ViewGroup {
*
* @attr ref android.R.styleable#FrameLayout_foregroundGravity
*/
+ @android.view.RemotableViewMethod
public void setForegroundGravity(int foregroundGravity) {
if (mForegroundGravity != foregroundGravity) {
if ((foregroundGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == 0) {
@@ -348,6 +349,7 @@ public class FrameLayout extends ViewGroup {
*
* @attr ref android.R.styleable#FrameLayout_measureAllChildren
*/
+ @android.view.RemotableViewMethod
public void setMeasureAllChildren(boolean measureAll) {
mMeasureAllChildren = measureAll;
}
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 4ae322e1fb012..94d1bd175c7ae 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -193,6 +193,7 @@ public class ImageView extends View {
*
* @attr ref android.R.styleable#ImageView_adjustViewBounds
*/
+ @android.view.RemotableViewMethod
public void setAdjustViewBounds(boolean adjustViewBounds) {
mAdjustViewBounds = adjustViewBounds;
if (adjustViewBounds) {
@@ -217,6 +218,7 @@ public class ImageView extends View {
*
* @attr ref android.R.styleable#ImageView_maxWidth
*/
+ @android.view.RemotableViewMethod
public void setMaxWidth(int maxWidth) {
mMaxWidth = maxWidth;
}
@@ -238,6 +240,7 @@ public class ImageView extends View {
*
* @attr ref android.R.styleable#ImageView_maxHeight
*/
+ @android.view.RemotableViewMethod
public void setMaxHeight(int maxHeight) {
mMaxHeight = maxHeight;
}
@@ -256,6 +259,7 @@ public class ImageView extends View {
*
* @attr ref android.R.styleable#ImageView_src
*/
+ @android.view.RemotableViewMethod
public void setImageResource(int resId) {
if (mUri != null || mResource != resId) {
updateDrawable(null);
@@ -272,6 +276,7 @@ public class ImageView extends View {
*
* @param uri The Uri of an image
*/
+ @android.view.RemotableViewMethod
public void setImageURI(Uri uri) {
if (mResource != 0 ||
(mUri != uri &&
@@ -306,6 +311,7 @@ public class ImageView extends View {
*
* @param bm The bitmap to set
*/
+ @android.view.RemotableViewMethod
public void setImageBitmap(Bitmap bm) {
// if this is used frequently, may handle bitmaps explicitly
// to reduce the intermediate drawable object
@@ -327,6 +333,7 @@ public class ImageView extends View {
resizeFromDrawable();
}
+ @android.view.RemotableViewMethod
public void setImageLevel(int level) {
mLevel = level;
if (mDrawable != null) {
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index 85a7339167316..a9822f8bc2ce6 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -136,6 +136,7 @@ public class LinearLayout extends ViewGroup {
*
* @attr ref android.R.styleable#LinearLayout_baselineAligned
*/
+ @android.view.RemotableViewMethod
public void setBaselineAligned(boolean baselineAligned) {
mBaselineAligned = baselineAligned;
}
@@ -208,6 +209,7 @@ public class LinearLayout extends ViewGroup {
*
* @attr ref android.R.styleable#LinearLayout_baselineAlignedChildIndex
*/
+ @android.view.RemotableViewMethod
public void setBaselineAlignedChildIndex(int i) {
if ((i < 0) || (i >= getChildCount())) {
throw new IllegalArgumentException("base aligned child index out "
@@ -265,6 +267,7 @@ public class LinearLayout extends ViewGroup {
* to 0.0f if the weight sum should be computed from the children's
* layout_weight
*/
+ @android.view.RemotableViewMethod
public void setWeightSum(float weightSum) {
mWeightSum = Math.max(0.0f, weightSum);
}
@@ -1149,6 +1152,7 @@ public class LinearLayout extends ViewGroup {
*
* @attr ref android.R.styleable#LinearLayout_gravity
*/
+ @android.view.RemotableViewMethod
public void setGravity(int gravity) {
if (mGravity != gravity) {
if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == 0) {
@@ -1164,6 +1168,7 @@ public class LinearLayout extends ViewGroup {
}
}
+ @android.view.RemotableViewMethod
public void setHorizontalGravity(int horizontalGravity) {
final int gravity = horizontalGravity & Gravity.HORIZONTAL_GRAVITY_MASK;
if ((mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) != gravity) {
@@ -1172,6 +1177,7 @@ public class LinearLayout extends ViewGroup {
}
}
+ @android.view.RemotableViewMethod
public void setVerticalGravity(int verticalGravity) {
final int gravity = verticalGravity & Gravity.VERTICAL_GRAVITY_MASK;
if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) != gravity) {
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 9c7f600779f0e..4e5989cb69b22 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -2179,6 +2179,10 @@ public class ListView extends AbsListView {
&& !isViewAncestorOf(selectedView, this)) {
selectedView = null;
hideSelector();
+
+ // but we don't want to set the ressurect position (that would make subsequent
+ // unhandled key events bring back the item we just scrolled off!)
+ mResurrectToPosition = INVALID_POSITION;
}
if (needToRedraw) {
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index dada1051632ae..4a5cea1cb0286 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -24,6 +24,8 @@ import android.view.View;
import android.view.WindowManager;
import android.view.Gravity;
import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.view.ViewTreeObserver.OnScrollChangedListener;
import android.view.View.OnTouchListener;
import android.graphics.PixelFormat;
import android.graphics.Rect;
@@ -33,6 +35,8 @@ import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
+import java.lang.ref.WeakReference;
+
/**
*
A popup window that can be used to display an arbitrary view. The popup
* windows is a floating container that appears on top of the current
@@ -109,7 +113,23 @@ public class PopupWindow {
private static final int[] ABOVE_ANCHOR_STATE_SET = new int[] {
com.android.internal.R.attr.state_above_anchor
};
-
+
+ private WeakReference mAnchor;
+ private OnScrollChangedListener mOnScrollChangedListener =
+ new OnScrollChangedListener() {
+ public void onScrollChanged() {
+ View anchor = mAnchor.get();
+ if (anchor != null && mPopupView != null) {
+ WindowManager.LayoutParams p = (WindowManager.LayoutParams)
+ mPopupView.getLayoutParams();
+
+ mAboveAnchor = findDropDownPosition(anchor, p, mAnchorXoff, mAnchorYoff);
+ update(p.x, p.y, -1, -1, true);
+ }
+ }
+ };
+ private int mAnchorXoff, mAnchorYoff;
+
/**
*
Create a new empty, non focusable popup window of dimension (0,0).
*
@@ -579,6 +599,8 @@ public class PopupWindow {
return;
}
+ unregisterForScrollChanged();
+
mIsShowing = true;
mIsDropdown = false;
@@ -617,6 +639,8 @@ public class PopupWindow {
* the popup in its entirety, this method tries to find a parent scroll
* view to scroll. If no parent scroll view can be scrolled, the bottom-left
* corner of the popup is pinned at the top left corner of the anchor view.
+ *
If the view later scrolls to move anchor to a different
+ * location, the popup will be moved correspondingly.
*
* @param anchor the view on which to pin the popup window
*
@@ -627,6 +651,8 @@ public class PopupWindow {
return;
}
+ registerForScrollChanged(anchor, xoff, yoff);
+
mIsShowing = true;
mIsDropdown = true;
@@ -894,6 +920,8 @@ public class PopupWindow {
*/
public void dismiss() {
if (isShowing() && mPopupView != null) {
+ unregisterForScrollChanged();
+
mWindowManager.removeView(mPopupView);
if (mPopupView != mContentView && mPopupView instanceof ViewGroup) {
((ViewGroup) mPopupView).removeView(mContentView);
@@ -962,6 +990,25 @@ public class PopupWindow {
* @param height the new height, can be -1 to ignore
*/
public void update(int x, int y, int width, int height) {
+ update(x, y, width, height, false);
+ }
+
+ /**
+ *
Updates the position and the dimension of the popup window. Width and
+ * height can be set to -1 to update location only. Calling this function
+ * also updates the window with the current popup state as
+ * described for {@link #update()}.
+ *
+ * @param x the new x location
+ * @param y the new y location
+ * @param width the new width, can be -1 to ignore
+ * @param height the new height, can be -1 to ignore
+ * @param force reposition the window even if the specified position
+ * already seems to correspond to the LayoutParams
+ *
+ * @hide pending API council approval
+ */
+ public void update(int x, int y, int width, int height, boolean force) {
if (width != -1) {
mLastWidth = width;
setWidth(width);
@@ -979,7 +1026,7 @@ public class PopupWindow {
WindowManager.LayoutParams p = (WindowManager.LayoutParams)
mPopupView.getLayoutParams();
- boolean update = false;
+ boolean update = force;
final int finalWidth = mWidthMode < 0 ? mWidthMode : mLastWidth;
if (width != -1 && p.width != finalWidth) {
@@ -1039,6 +1086,8 @@ public class PopupWindow {
* height can be set to -1 to update location only. Calling this function
* also updates the window with the current popup state as
* described for {@link #update()}.
+ *
If the view later scrolls to move anchor to a different
+ * location, the popup will be moved correspondingly.
*
* @param anchor the popup's anchor view
* @param xoff x offset from the view's left edge
@@ -1051,6 +1100,12 @@ public class PopupWindow {
return;
}
+ WeakReference oldAnchor = mAnchor;
+ if (oldAnchor == null || oldAnchor.get() != anchor ||
+ mAnchorXoff != xoff || mAnchorYoff != yoff) {
+ registerForScrollChanged(anchor, xoff, yoff);
+ }
+
WindowManager.LayoutParams p = (WindowManager.LayoutParams)
mPopupView.getLayoutParams();
@@ -1065,10 +1120,10 @@ public class PopupWindow {
mPopupHeight = height;
}
- findDropDownPosition(anchor, p, xoff, yoff);
+ mAboveAnchor = findDropDownPosition(anchor, p, xoff, yoff);
update(p.x, p.y, width, height);
}
-
+
/**
* Listener that is called when this popup window is dismissed.
*/
@@ -1078,7 +1133,33 @@ public class PopupWindow {
*/
public void onDismiss();
}
-
+
+ private void unregisterForScrollChanged() {
+ WeakReference anchorRef = mAnchor;
+ View anchor = null;
+ if (anchorRef != null) {
+ anchor = anchorRef.get();
+ }
+ if (anchor != null) {
+ ViewTreeObserver vto = anchor.getViewTreeObserver();
+ vto.removeOnScrollChangedListener(mOnScrollChangedListener);
+ }
+ mAnchor = null;
+ }
+
+ private void registerForScrollChanged(View anchor, int xoff, int yoff) {
+ unregisterForScrollChanged();
+
+ mAnchor = new WeakReference(anchor);
+ ViewTreeObserver vto = anchor.getViewTreeObserver();
+ if (vto != null) {
+ vto.addOnScrollChangedListener(mOnScrollChangedListener);
+ }
+
+ mAnchorXoff = xoff;
+ mAnchorYoff = yoff;
+ }
+
private class PopupViewContainer extends FrameLayout {
public PopupViewContainer(Context context) {
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 434e9f3c3f91f..dd2570afec7b8 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -344,6 +344,7 @@ public class ProgressBar extends View {
*
* @param indeterminate true to enable the indeterminate mode
*/
+ @android.view.RemotableViewMethod
public synchronized void setIndeterminate(boolean indeterminate) {
if ((!mOnlyIndeterminate || !mIndeterminate) && indeterminate != mIndeterminate) {
mIndeterminate = indeterminate;
@@ -529,6 +530,7 @@ public class ProgressBar extends View {
setProgress(progress, false);
}
+ @android.view.RemotableViewMethod
synchronized void setProgress(int progress, boolean fromUser) {
if (mIndeterminate) {
return;
@@ -560,6 +562,7 @@ public class ProgressBar extends View {
* @see #getSecondaryProgress()
* @see #incrementSecondaryProgressBy(int)
*/
+ @android.view.RemotableViewMethod
public synchronized void setSecondaryProgress(int secondaryProgress) {
if (mIndeterminate) {
return;
@@ -633,6 +636,7 @@ public class ProgressBar extends View {
* @see #setProgress(int)
* @see #setSecondaryProgress(int)
*/
+ @android.view.RemotableViewMethod
public synchronized void setMax(int max) {
if (max < 0) {
max = 0;
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index 9ded52be3c51f..ba63ec356b1aa 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -168,6 +168,7 @@ public class RelativeLayout extends ViewGroup {
*
* @attr ref android.R.styleable#RelativeLayout_ignoreGravity
*/
+ @android.view.RemotableViewMethod
public void setIgnoreGravity(int viewId) {
mIgnoreGravity = viewId;
}
@@ -183,6 +184,7 @@ public class RelativeLayout extends ViewGroup {
*
* @attr ref android.R.styleable#RelativeLayout_gravity
*/
+ @android.view.RemotableViewMethod
public void setGravity(int gravity) {
if (mGravity != gravity) {
if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == 0) {
@@ -198,6 +200,7 @@ public class RelativeLayout extends ViewGroup {
}
}
+ @android.view.RemotableViewMethod
public void setHorizontalGravity(int horizontalGravity) {
final int gravity = horizontalGravity & Gravity.HORIZONTAL_GRAVITY_MASK;
if ((mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) != gravity) {
@@ -206,6 +209,7 @@ public class RelativeLayout extends ViewGroup {
}
}
+ @android.view.RemotableViewMethod
public void setVerticalGravity(int verticalGravity) {
final int gravity = verticalGravity & Gravity.VERTICAL_GRAVITY_MASK;
if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) != gravity) {
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 25afee83a548c..e000d2e22781e 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -31,6 +31,7 @@ import android.os.Parcelable;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
+import android.view.RemotableViewMethod;
import android.view.View;
import android.view.ViewGroup;
import android.view.LayoutInflater.Filter;
@@ -38,10 +39,13 @@ import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
+import java.lang.Class;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.util.ArrayList;
@@ -80,19 +84,22 @@ public class RemoteViews implements Parcelable, Filter {
/**
- * This annotation indicates that a subclass of View is alllowed to be used with the
- * {@link android.widget.RemoteViews} mechanism.
+ * This annotation indicates that a subclass of View is alllowed to be used
+ * with the {@link android.widget.RemoteViews} mechanism.
*/
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface RemoteView {
}
-
+
/**
* Exception to send when something goes wrong executing an action
*
*/
public static class ActionException extends RuntimeException {
+ public ActionException(Exception ex) {
+ super(ex);
+ }
public ActionException(String message) {
super(message);
}
@@ -110,274 +117,7 @@ public class RemoteViews implements Parcelable, Filter {
return 0;
}
};
-
- /**
- * Equivalent to calling View.setVisibility
- */
- private class SetViewVisibility extends Action {
- public SetViewVisibility(int id, int vis) {
- viewId = id;
- visibility = vis;
- }
-
- public SetViewVisibility(Parcel parcel) {
- viewId = parcel.readInt();
- visibility = parcel.readInt();
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(TAG);
- dest.writeInt(viewId);
- dest.writeInt(visibility);
- }
-
- @Override
- public void apply(View root) {
- View target = root.findViewById(viewId);
- if (target != null) {
- target.setVisibility(visibility);
- }
- }
-
- private int viewId;
- private int visibility;
- public final static int TAG = 0;
- }
-
- /**
- * Equivalent to calling TextView.setText
- */
- private class SetTextViewText extends Action {
- public SetTextViewText(int id, CharSequence t) {
- viewId = id;
- text = t;
- }
-
- public SetTextViewText(Parcel parcel) {
- viewId = parcel.readInt();
- text = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(TAG);
- dest.writeInt(viewId);
- TextUtils.writeToParcel(text, dest, flags);
- }
-
- @Override
- public void apply(View root) {
- TextView target = (TextView) root.findViewById(viewId);
- if (target != null) {
- target.setText(text);
- }
- }
-
- int viewId;
- CharSequence text;
- public final static int TAG = 1;
- }
- /**
- * Equivalent to calling ImageView.setResource
- */
- private class SetImageViewResource extends Action {
- public SetImageViewResource(int id, int src) {
- viewId = id;
- srcId = src;
- }
-
- public SetImageViewResource(Parcel parcel) {
- viewId = parcel.readInt();
- srcId = parcel.readInt();
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(TAG);
- dest.writeInt(viewId);
- dest.writeInt(srcId);
- }
-
- @Override
- public void apply(View root) {
- ImageView target = (ImageView) root.findViewById(viewId);
- Drawable d = mContext.getResources().getDrawable(srcId);
- if (target != null) {
- target.setImageDrawable(d);
- }
- }
-
- int viewId;
- int srcId;
- public final static int TAG = 2;
- }
-
- /**
- * Equivalent to calling ImageView.setImageURI
- */
- private class SetImageViewUri extends Action {
- public SetImageViewUri(int id, Uri u) {
- viewId = id;
- uri = u;
- }
-
- public SetImageViewUri(Parcel parcel) {
- viewId = parcel.readInt();
- uri = Uri.CREATOR.createFromParcel(parcel);
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(TAG);
- dest.writeInt(viewId);
- Uri.writeToParcel(dest, uri);
- }
-
- @Override
- public void apply(View root) {
- ImageView target = (ImageView) root.findViewById(viewId);
- if (target != null) {
- target.setImageURI(uri);
- }
- }
-
- int viewId;
- Uri uri;
- public final static int TAG = 3;
- }
-
- /**
- * Equivalent to calling ImageView.setImageBitmap
- */
- private class SetImageViewBitmap extends Action {
- public SetImageViewBitmap(int id, Bitmap src) {
- viewId = id;
- bitmap = src;
- }
-
- public SetImageViewBitmap(Parcel parcel) {
- viewId = parcel.readInt();
- bitmap = Bitmap.CREATOR.createFromParcel(parcel);
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(TAG);
- dest.writeInt(viewId);
- if (bitmap != null) {
- bitmap.writeToParcel(dest, flags);
- }
- }
-
- @Override
- public void apply(View root) {
- if (bitmap != null) {
- ImageView target = (ImageView) root.findViewById(viewId);
- Drawable d = new BitmapDrawable(bitmap);
- if (target != null) {
- target.setImageDrawable(d);
- }
- }
- }
-
- int viewId;
- Bitmap bitmap;
- public final static int TAG = 4;
- }
-
- /**
- * Equivalent to calling Chronometer.setBase, Chronometer.setFormat,
- * and Chronometer.start/stop.
- */
- private class SetChronometer extends Action {
- public SetChronometer(int id, long base, String format, boolean running) {
- this.viewId = id;
- this.base = base;
- this.format = format;
- this.running = running;
- }
-
- public SetChronometer(Parcel parcel) {
- viewId = parcel.readInt();
- base = parcel.readLong();
- format = parcel.readString();
- running = parcel.readInt() != 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(TAG);
- dest.writeInt(viewId);
- dest.writeLong(base);
- dest.writeString(format);
- dest.writeInt(running ? 1 : 0);
- }
-
- @Override
- public void apply(View root) {
- Chronometer target = (Chronometer) root.findViewById(viewId);
- if (target != null) {
- target.setBase(base);
- target.setFormat(format);
- if (running) {
- target.start();
- } else {
- target.stop();
- }
- }
- }
-
- int viewId;
- boolean running;
- long base;
- String format;
-
- public final static int TAG = 5;
- }
-
- /**
- * Equivalent to calling ProgressBar.setMax, ProgressBar.setProgress and
- * ProgressBar.setIndeterminate
- */
- private class SetProgressBar extends Action {
- public SetProgressBar(int id, int max, int progress, boolean indeterminate) {
- this.viewId = id;
- this.progress = progress;
- this.max = max;
- this.indeterminate = indeterminate;
- }
-
- public SetProgressBar(Parcel parcel) {
- viewId = parcel.readInt();
- progress = parcel.readInt();
- max = parcel.readInt();
- indeterminate = parcel.readInt() != 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(TAG);
- dest.writeInt(viewId);
- dest.writeInt(progress);
- dest.writeInt(max);
- dest.writeInt(indeterminate ? 1 : 0);
- }
-
- @Override
- public void apply(View root) {
- ProgressBar target = (ProgressBar) root.findViewById(viewId);
- if (target != null) {
- target.setIndeterminate(indeterminate);
- if (!indeterminate) {
- target.setMax(max);
- target.setProgress(progress);
- }
- }
- }
-
- int viewId;
- boolean indeterminate;
- int progress;
- int max;
-
- public final static int TAG = 6;
- }
-
/**
* Equivalent to calling
* {@link android.view.View#setOnClickListener(android.view.View.OnClickListener)}
@@ -421,7 +161,7 @@ public class RemoteViews implements Parcelable, Filter {
int viewId;
PendingIntent pendingIntent;
- public final static int TAG = 7;
+ public final static int TAG = 1;
}
/**
@@ -511,92 +251,215 @@ public class RemoteViews implements Parcelable, Filter {
PorterDuff.Mode filterMode;
int level;
- public final static int TAG = 8;
+ public final static int TAG = 3;
}
/**
- * Equivalent to calling {@link android.widget.TextView#setTextColor(int)}.
+ * Base class for the reflection actions.
*/
- private class SetTextColor extends Action {
- public SetTextColor(int id, int color) {
- this.viewId = id;
- this.color = color;
+ private class ReflectionAction extends Action {
+ static final int TAG = 2;
+
+ static final int BOOLEAN = 1;
+ static final int BYTE = 2;
+ static final int SHORT = 3;
+ static final int INT = 4;
+ static final int LONG = 5;
+ static final int FLOAT = 6;
+ static final int DOUBLE = 7;
+ static final int CHAR = 8;
+ static final int STRING = 9;
+ static final int CHAR_SEQUENCE = 10;
+ static final int URI = 11;
+ static final int BITMAP = 12;
+
+ int viewId;
+ String methodName;
+ int type;
+ Object value;
+
+ ReflectionAction(int viewId, String methodName, int type, Object value) {
+ this.viewId = viewId;
+ this.methodName = methodName;
+ this.type = type;
+ this.value = value;
}
-
- public SetTextColor(Parcel parcel) {
- viewId = parcel.readInt();
- color = parcel.readInt();
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(TAG);
- dest.writeInt(viewId);
- dest.writeInt(color);
- }
-
- @Override
- public void apply(View root) {
- final View target = root.findViewById(viewId);
- if (target instanceof TextView) {
- final TextView textView = (TextView) target;
- textView.setTextColor(color);
+
+ ReflectionAction(Parcel in) {
+ this.viewId = in.readInt();
+ this.methodName = in.readString();
+ this.type = in.readInt();
+ if (false) {
+ Log.d("RemoteViews", "read viewId=0x" + Integer.toHexString(this.viewId)
+ + " methodName=" + this.methodName + " type=" + this.type);
+ }
+ switch (this.type) {
+ case BOOLEAN:
+ this.value = in.readInt() != 0;
+ break;
+ case BYTE:
+ this.value = in.readByte();
+ break;
+ case SHORT:
+ this.value = (short)in.readInt();
+ break;
+ case INT:
+ this.value = in.readInt();
+ break;
+ case LONG:
+ this.value = in.readLong();
+ break;
+ case FLOAT:
+ this.value = in.readFloat();
+ break;
+ case DOUBLE:
+ this.value = in.readDouble();
+ break;
+ case CHAR:
+ this.value = (char)in.readInt();
+ break;
+ case STRING:
+ this.value = in.readString();
+ break;
+ case CHAR_SEQUENCE:
+ this.value = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ break;
+ case URI:
+ this.value = Uri.CREATOR.createFromParcel(in);
+ break;
+ case BITMAP:
+ this.value = Bitmap.CREATOR.createFromParcel(in);
+ break;
+ default:
+ break;
}
}
-
- int viewId;
- int color;
- public final static int TAG = 9;
- }
-
- /**
- * Equivalent to calling {@link android.widget.ViewFlipper#startFlipping()}
- * or {@link android.widget.ViewFlipper#stopFlipping()} along with
- * {@link android.widget.ViewFlipper#setFlipInterval(int)}.
- */
- private class SetFlipping extends Action {
- public SetFlipping(int id, boolean flipping, int milliseconds) {
- this.viewId = id;
- this.flipping = flipping;
- this.milliseconds = milliseconds;
- }
-
- public SetFlipping(Parcel parcel) {
- viewId = parcel.readInt();
- flipping = parcel.readInt() != 0;
- milliseconds = parcel.readInt();
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(TAG);
- dest.writeInt(viewId);
- dest.writeInt(flipping ? 1 : 0);
- dest.writeInt(milliseconds);
- }
-
- @Override
- public void apply(View root) {
- final View target = root.findViewById(viewId);
- if (target instanceof ViewFlipper) {
- final ViewFlipper flipper = (ViewFlipper) target;
- if (milliseconds != -1) {
- flipper.setFlipInterval(milliseconds);
- }
- if (flipping) {
- flipper.startFlipping();
- } else {
- flipper.stopFlipping();
- }
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(TAG);
+ out.writeInt(this.viewId);
+ out.writeString(this.methodName);
+ out.writeInt(this.type);
+ if (false) {
+ Log.d("RemoteViews", "write viewId=0x" + Integer.toHexString(this.viewId)
+ + " methodName=" + this.methodName + " type=" + this.type);
+ }
+ switch (this.type) {
+ case BOOLEAN:
+ out.writeInt(((Boolean)this.value).booleanValue() ? 1 : 0);
+ break;
+ case BYTE:
+ out.writeByte(((Byte)this.value).byteValue());
+ break;
+ case SHORT:
+ out.writeInt(((Short)this.value).shortValue());
+ break;
+ case INT:
+ out.writeInt(((Integer)this.value).intValue());
+ break;
+ case LONG:
+ out.writeLong(((Long)this.value).longValue());
+ break;
+ case FLOAT:
+ out.writeFloat(((Float)this.value).floatValue());
+ break;
+ case DOUBLE:
+ out.writeDouble(((Double)this.value).doubleValue());
+ break;
+ case CHAR:
+ out.writeInt((int)((Character)this.value).charValue());
+ break;
+ case STRING:
+ out.writeString((String)this.value);
+ break;
+ case CHAR_SEQUENCE:
+ TextUtils.writeToParcel((CharSequence)this.value, out, flags);
+ break;
+ case URI:
+ ((Uri)this.value).writeToParcel(out, flags);
+ break;
+ case BITMAP:
+ ((Bitmap)this.value).writeToParcel(out, flags);
+ break;
+ default:
+ break;
}
}
-
- int viewId;
- boolean flipping;
- int milliseconds;
- public final static int TAG = 10;
+ private Class getParameterType() {
+ switch (this.type) {
+ case BOOLEAN:
+ return boolean.class;
+ case BYTE:
+ return byte.class;
+ case SHORT:
+ return short.class;
+ case INT:
+ return int.class;
+ case LONG:
+ return long.class;
+ case FLOAT:
+ return float.class;
+ case DOUBLE:
+ return double.class;
+ case CHAR:
+ return char.class;
+ case STRING:
+ return String.class;
+ case CHAR_SEQUENCE:
+ return CharSequence.class;
+ case URI:
+ return Uri.class;
+ case BITMAP:
+ return Bitmap.class;
+ default:
+ return null;
+ }
+ }
+
+ @Override
+ public void apply(View root) {
+ final View view = root.findViewById(viewId);
+ if (view == null) {
+ throw new ActionException("can't find view: 0x" + Integer.toHexString(viewId));
+ }
+
+ Class param = getParameterType();
+ if (param == null) {
+ throw new ActionException("bad type: " + this.type);
+ }
+
+ Class klass = view.getClass();
+ Method method = null;
+ try {
+ method = klass.getMethod(this.methodName, getParameterType());
+ }
+ catch (NoSuchMethodException ex) {
+ throw new ActionException("view: " + klass.getName() + " doesn't have method: "
+ + this.methodName + "(" + param.getName() + ")");
+ }
+
+ if (!method.isAnnotationPresent(RemotableViewMethod.class)) {
+ throw new ActionException("view: " + klass.getName()
+ + " can't use method with RemoteViews: "
+ + this.methodName + "(" + param.getName() + ")");
+ }
+
+ try {
+ if (false) {
+ Log.d("RemoteViews", "view: " + klass.getName() + " calling method: "
+ + this.methodName + "(" + param.getName() + ") with "
+ + (this.value == null ? "null" : this.value.getClass().getName()));
+ }
+ method.invoke(view, this.value);
+ }
+ catch (Exception ex) {
+ throw new ActionException(ex);
+ }
+ }
}
+
/**
* Create a new RemoteViews object that will display the views contained
* in the specified layout file.
@@ -623,41 +486,17 @@ public class RemoteViews implements Parcelable, Filter {
for (int i=0; ierror is null, the error message and icon
* will be cleared.
*/
+ @android.view.RemotableViewMethod
public void setError(CharSequence error) {
if (error == null) {
setError(null, null);
@@ -2954,10 +2983,28 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (mPopup == null) {
LayoutInflater inflater = LayoutInflater.from(getContext());
- TextView err = (TextView) inflater.inflate(com.android.internal.R.layout.textview_hint,
+ final TextView err = (TextView) inflater.inflate(com.android.internal.R.layout.textview_hint,
null);
- mPopup = new PopupWindow(err, 200, 50);
+ mPopup = new PopupWindow(err, 200, 50) {
+ private boolean mAbove = false;
+
+ @Override
+ public void update(int x, int y, int w, int h, boolean force) {
+ super.update(x, y, w, h, force);
+
+ boolean above = isAboveAnchor();
+ if (above != mAbove) {
+ mAbove = above;
+
+ if (above) {
+ err.setBackgroundResource(com.android.internal.R.drawable.popup_inline_error_above);
+ } else {
+ err.setBackgroundResource(com.android.internal.R.drawable.popup_inline_error);
+ }
+ }
+ }
+ };
mPopup.setFocusable(false);
}
@@ -5094,6 +5141,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
*
* @attr ref android.R.styleable#TextView_singleLine
*/
+ @android.view.RemotableViewMethod
public void setSingleLine(boolean singleLine) {
if ((mInputType&EditorInfo.TYPE_MASK_CLASS)
== EditorInfo.TYPE_CLASS_TEXT) {
@@ -5168,6 +5216,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
*
* @attr ref android.R.styleable#TextView_selectAllOnFocus
*/
+ @android.view.RemotableViewMethod
public void setSelectAllOnFocus(boolean selectAllOnFocus) {
mSelectAllOnFocus = selectAllOnFocus;
@@ -5181,6 +5230,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
*
* @attr ref android.R.styleable#TextView_cursorVisible
*/
+ @android.view.RemotableViewMethod
public void setCursorVisible(boolean visible) {
mCursorVisible = visible;
invalidate();
@@ -5730,6 +5780,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
startStopMarquee(hasWindowFocus);
}
+ /**
+ * Use {@link BaseInputConnection#removeComposingSpans
+ * BaseInputConnection.removeComposingSpans()} to remove any IME composing
+ * state from this text view.
+ */
+ public void clearComposingText() {
+ if (mText instanceof Spannable) {
+ BaseInputConnection.removeComposingSpans((Spannable)mText);
+ }
+ }
+
@Override
public void setSelected(boolean selected) {
boolean wasSelected = isSelected();
diff --git a/core/java/android/widget/ViewFlipper.java b/core/java/android/widget/ViewFlipper.java
index e20bfdf0f52fc..8a7946b951b1a 100644
--- a/core/java/android/widget/ViewFlipper.java
+++ b/core/java/android/widget/ViewFlipper.java
@@ -31,7 +31,6 @@ import android.widget.RemoteViews.RemoteView;
*
* @attr ref android.R.styleable#ViewFlipper_flipInterval
*/
-@RemoteView
public class ViewFlipper extends ViewAnimator {
private int mFlipInterval = 3000;
private boolean mKeepFlipping = false;
@@ -56,6 +55,7 @@ public class ViewFlipper extends ViewAnimator {
* @param milliseconds
* time in milliseconds
*/
+ @android.view.RemotableViewMethod
public void setFlipInterval(int milliseconds) {
mFlipInterval = milliseconds;
}
diff --git a/core/java/android/widget/ZoomRing.java b/core/java/android/widget/ZoomRing.java
index be3b1fbd527fb..22881b3bab49f 100644
--- a/core/java/android/widget/ZoomRing.java
+++ b/core/java/android/widget/ZoomRing.java
@@ -7,7 +7,11 @@ import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.RotateDrawable;
+import android.os.Handler;
+import android.os.Message;
+import android.os.SystemClock;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
@@ -19,10 +23,8 @@ import android.view.ViewConfiguration;
public class ZoomRing extends View {
// TODO: move to ViewConfiguration?
- static final int DOUBLE_TAP_DISMISS_TIMEOUT = ViewConfiguration.getJumpTapTimeout();
+ static final int DOUBLE_TAP_DISMISS_TIMEOUT = ViewConfiguration.getDoubleTapTimeout();
// TODO: get from theme
- private static final int DISABLED_ALPHA = 160;
-
private static final String TAG = "ZoomRing";
// TODO: Temporary until the trail is done
@@ -32,15 +34,26 @@ public class ZoomRing extends View {
private static final int THUMB_DISTANCE = 63;
/** To avoid floating point calculations, we multiply radians by this value. */
- public static final int RADIAN_INT_MULTIPLIER = 100000000;
+ public static final int RADIAN_INT_MULTIPLIER = 10000;
+ public static final int RADIAN_INT_ERROR = 100;
/** PI using our multiplier. */
public static final int PI_INT_MULTIPLIED = (int) (Math.PI * RADIAN_INT_MULTIPLIER);
+ public static final int TWO_PI_INT_MULTIPLIED = PI_INT_MULTIPLIED * 2;
/** PI/2 using our multiplier. */
private static final int HALF_PI_INT_MULTIPLIED = PI_INT_MULTIPLIED / 2;
private int mZeroAngle = HALF_PI_INT_MULTIPLIED * 3;
+
+ private static final int THUMB_GRAB_SLOP = PI_INT_MULTIPLIED / 8;
+ private static final int THUMB_DRAG_SLOP = PI_INT_MULTIPLIED / 12;
- private static final int THUMB_GRAB_SLOP = PI_INT_MULTIPLIED / 4;
+ /**
+ * Includes error because we compare this to the result of
+ * getDelta(getClosestTickeAngle(..), oldAngle) which ends up having some
+ * rounding error.
+ */
+ private static final int MAX_ABS_JUMP_DELTA_ANGLE = (2 * PI_INT_MULTIPLIED / 3) +
+ RADIAN_INT_ERROR;
/** The cached X of our center. */
private int mCenterX;
@@ -49,10 +62,13 @@ public class ZoomRing extends View {
/** The angle of the thumb (in int radians) */
private int mThumbAngle;
- private boolean mIsThumbAngleValid;
private int mThumbHalfWidth;
private int mThumbHalfHeight;
-
+
+ private int mThumbCwBound = Integer.MIN_VALUE;
+ private int mThumbCcwBound = Integer.MIN_VALUE;
+ private boolean mEnforceMaxAbsJump = true;
+
/** The inner radius of the track. */
private int mBoundInnerRadiusSquared = 0;
/** The outer radius of the track. */
@@ -63,8 +79,23 @@ public class ZoomRing extends View {
private boolean mDrawThumb = true;
private Drawable mThumbDrawable;
-
+
+ /** Shown beneath the thumb if we can still zoom in. */
+ private Drawable mThumbPlusArrowDrawable;
+ /** Shown beneath the thumb if we can still zoom out. */
+ private Drawable mThumbMinusArrowDrawable;
+ private static final int THUMB_ARROWS_FADE_DURATION = 300;
+ private long mThumbArrowsFadeStartTime;
+ private int mThumbArrowsAlpha = 255;
+
private static final int MODE_IDLE = 0;
+
+ /**
+ * User has his finger down somewhere on the ring (besides the thumb) and we
+ * are waiting for him to move the slop amount before considering him in the
+ * drag thumb state.
+ */
+ private static final int MODE_WAITING_FOR_DRAG_THUMB = 5;
private static final int MODE_DRAG_THUMB = 1;
/**
* User has his finger down, but we are waiting for him to pass the touch
@@ -74,24 +105,47 @@ public class ZoomRing extends View {
private static final int MODE_WAITING_FOR_MOVE_ZOOM_RING = 4;
private static final int MODE_MOVE_ZOOM_RING = 2;
private static final int MODE_TAP_DRAG = 3;
+ /** Ignore the touch interaction. Reset to MODE_IDLE after up/cancel. */
+ private static final int MODE_IGNORE_UNTIL_UP = 6;
private int mMode;
- private long mPreviousDownTime;
+ private long mPreviousUpTime;
private int mPreviousDownX;
private int mPreviousDownY;
- private Disabler mDisabler = new Disabler();
-
+ private int mWaitingForDragThumbDownAngle;
+
private OnZoomRingCallback mCallback;
private int mPreviousCallbackAngle;
private int mCallbackThreshold = Integer.MAX_VALUE;
private boolean mResetThumbAutomatically = true;
private int mThumbDragStartAngle;
+
private final int mTouchSlop;
+
private Drawable mTrail;
private double mAcculumalatedTrailAngle;
+
+ private Scroller mThumbScroller;
+ private static final int MSG_THUMB_SCROLLER_TICK = 1;
+ private static final int MSG_THUMB_ARROWS_FADE_TICK = 2;
+ private Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_THUMB_SCROLLER_TICK:
+ onThumbScrollerTick();
+ break;
+
+ case MSG_THUMB_ARROWS_FADE_TICK:
+ onThumbArrowsFadeTick();
+ break;
+ }
+ }
+ };
+
public ZoomRing(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
@@ -101,6 +155,10 @@ public class ZoomRing extends View {
// TODO get drawables from style instead
Resources res = context.getResources();
mThumbDrawable = res.getDrawable(R.drawable.zoom_ring_thumb);
+ mThumbPlusArrowDrawable = res.getDrawable(R.drawable.zoom_ring_thumb_plus_arrow_rotatable).
+ mutate();
+ mThumbMinusArrowDrawable = res.getDrawable(R.drawable.zoom_ring_thumb_minus_arrow_rotatable).
+ mutate();
if (DRAW_TRAIL) {
mTrail = res.getDrawable(R.drawable.zoom_ring_trail).mutate();
}
@@ -108,7 +166,7 @@ public class ZoomRing extends View {
// TODO: add padding to drawable
setBackgroundResource(R.drawable.zoom_ring_track);
// TODO get from style
- setBounds(30, Integer.MAX_VALUE);
+ setRingBounds(30, Integer.MAX_VALUE);
mThumbHalfHeight = mThumbDrawable.getIntrinsicHeight() / 2;
mThumbHalfWidth = mThumbDrawable.getIntrinsicWidth() / 2;
@@ -134,7 +192,7 @@ public class ZoomRing extends View {
}
// TODO: from XML too
- public void setBounds(int innerRadius, int outerRadius) {
+ public void setRingBounds(int innerRadius, int outerRadius) {
mBoundInnerRadiusSquared = innerRadius * innerRadius;
if (mBoundInnerRadiusSquared < innerRadius) {
// Prevent overflow
@@ -148,7 +206,64 @@ public class ZoomRing extends View {
}
}
+ public void setThumbClockwiseBound(int angle) {
+ if (angle < 0) {
+ mThumbCwBound = Integer.MIN_VALUE;
+ } else {
+ mThumbCwBound = getClosestTickAngle(angle);
+ }
+ setEnforceMaxAbsJump();
+ }
+
+ public void setThumbCounterclockwiseBound(int angle) {
+ if (angle < 0) {
+ mThumbCcwBound = Integer.MIN_VALUE;
+ } else {
+ mThumbCcwBound = getClosestTickAngle(angle);
+ }
+ setEnforceMaxAbsJump();
+ }
+
+ private void setEnforceMaxAbsJump() {
+ // If there are bounds in both direction, there is no reason to restrict
+ // the amount that a user can absolute jump to
+ mEnforceMaxAbsJump =
+ mThumbCcwBound == Integer.MIN_VALUE || mThumbCwBound == Integer.MIN_VALUE;
+ }
+
+ public int getThumbAngle() {
+ return mThumbAngle;
+ }
+
public void setThumbAngle(int angle) {
+ angle = getValidAngle(angle);
+ mPreviousCallbackAngle = getClosestTickAngle(angle);
+ setThumbAngleAuto(angle, false, false);
+ }
+
+ /**
+ * Sets the thumb angle. If already animating, will continue the animation,
+ * otherwise it will do a direct jump.
+ *
+ * @param angle
+ * @param useDirection Whether to use the ccw parameter
+ * @param ccw Whether going counterclockwise (only used if useDirection is true)
+ */
+ private void setThumbAngleAuto(int angle, boolean useDirection, boolean ccw) {
+ if (mThumbScroller == null
+ || mThumbScroller.isFinished()
+ || Math.abs(getDelta(angle, getThumbScrollerAngle())) < THUMB_GRAB_SLOP) {
+ setThumbAngleInt(angle);
+ } else {
+ if (useDirection) {
+ setThumbAngleAnimated(angle, 0, ccw);
+ } else {
+ setThumbAngleAnimated(angle, 0);
+ }
+ }
+ }
+
+ private void setThumbAngleInt(int angle) {
mThumbAngle = angle;
int unoffsetAngle = angle + mZeroAngle;
int thumbCenterX = (int) (Math.cos(1f * unoffsetAngle / RADIAN_INT_MULTIPLIER) *
@@ -161,6 +276,10 @@ public class ZoomRing extends View {
thumbCenterX + mThumbHalfWidth,
thumbCenterY + mThumbHalfHeight);
+ if (mThumbArrowsAlpha > 0) {
+ setThumbArrowsAngle(angle);
+ }
+
if (DRAW_TRAIL) {
double degrees;
degrees = Math.min(359.0, Math.abs(mAcculumalatedTrailAngle));
@@ -174,10 +293,66 @@ public class ZoomRing extends View {
invalidate();
}
+
+ /**
+ *
+ * @param angle
+ * @param duration The animation duration, or 0 for the default duration.
+ */
+ public void setThumbAngleAnimated(int angle, int duration) {
+ // The angle when going from the current angle to the new angle
+ int deltaAngle = getDelta(mThumbAngle, angle);
+ // Counter clockwise if the new angle is more the current angle
+ boolean counterClockwise = deltaAngle > 0;
+
+ if (deltaAngle > PI_INT_MULTIPLIED || deltaAngle < -PI_INT_MULTIPLIED) {
+ // It's quicker to go the other direction
+ counterClockwise = !counterClockwise;
+ }
+
+ setThumbAngleAnimated(angle, duration, counterClockwise);
+ }
+
+ public void setThumbAngleAnimated(int angle, int duration, boolean counterClockwise) {
+ if (mThumbScroller == null) {
+ mThumbScroller = new Scroller(mContext);
+ }
+
+ int startAngle = mThumbAngle;
+ int endAngle = getValidAngle(angle);
+ int deltaAngle = getDelta(startAngle, endAngle, counterClockwise);
+ if (startAngle + deltaAngle < 0) {
+ // Keep our angles positive
+ startAngle += TWO_PI_INT_MULTIPLIED;
+ }
+
+ if (!mThumbScroller.isFinished()) {
+ duration = mThumbScroller.getDuration() - mThumbScroller.timePassed();
+ } else if (duration == 0) {
+ duration = getAnimationDuration(deltaAngle);
+ }
+ mThumbScroller.startScroll(startAngle, 0, deltaAngle, 0, duration);
+ onThumbScrollerTick();
+ }
+
+ private int getAnimationDuration(int deltaAngle) {
+ if (deltaAngle < 0) deltaAngle *= -1;
+ return 300 + deltaAngle * 300 / RADIAN_INT_MULTIPLIER;
+ }
+
+ private void onThumbScrollerTick() {
+ if (!mThumbScroller.computeScrollOffset()) return;
+ setThumbAngleInt(getThumbScrollerAngle());
+ mHandler.sendEmptyMessage(MSG_THUMB_SCROLLER_TICK);
+ }
+ private int getThumbScrollerAngle() {
+ return mThumbScroller.getCurrX() % TWO_PI_INT_MULTIPLIED;
+ }
+
public void resetThumbAngle(int angle) {
mPreviousCallbackAngle = angle;
- setThumbAngle(angle);
+ setThumbAngleInt(angle);
}
public void resetThumbAngle() {
@@ -185,7 +360,7 @@ public class ZoomRing extends View {
resetThumbAngle(0);
}
}
-
+
public void setResetThumbAutomatically(boolean resetThumbAutomatically) {
mResetThumbAutomatically = resetThumbAutomatically;
}
@@ -214,6 +389,9 @@ public class ZoomRing extends View {
if (DRAW_TRAIL) {
mTrail.setBounds(0, 0, right - left, bottom - top);
}
+
+ mThumbPlusArrowDrawable.setBounds(0, 0, right - left, bottom - top);
+ mThumbMinusArrowDrawable.setBounds(0, 0, right - left, bottom - top);
}
@Override
@@ -227,15 +405,13 @@ public class ZoomRing extends View {
mMode = MODE_IDLE;
mPreviousWidgetDragX = mPreviousWidgetDragY = Integer.MIN_VALUE;
mAcculumalatedTrailAngle = 0.0;
- mIsThumbAngleValid = false;
}
public void setTapDragMode(boolean tapDragMode, int x, int y) {
resetState();
mMode = tapDragMode ? MODE_TAP_DRAG : MODE_IDLE;
- mIsThumbAngleValid = false;
- if (tapDragMode && mCallback != null) {
+ if (tapDragMode) {
onThumbDragStarted(getAngle(x - mCenterX, y - mCenterY));
}
}
@@ -244,35 +420,44 @@ public class ZoomRing extends View {
switch (action) {
case MotionEvent.ACTION_DOWN:
- if (mPreviousDownTime + DOUBLE_TAP_DISMISS_TIMEOUT >= time) {
- if (mCallback != null) {
- mCallback.onZoomRingDismissed();
- }
- } else {
- mPreviousDownTime = time;
- mPreviousDownX = x;
- mPreviousDownY = y;
+ mCallback.onUserInteractionStarted();
+
+ if (time - mPreviousUpTime <= DOUBLE_TAP_DISMISS_TIMEOUT) {
+ mCallback.onZoomRingDismissed(true);
}
+
+ mPreviousDownX = x;
+ mPreviousDownY = y;
resetState();
- return true;
+ // Fall through to code below switch (since the down is used for
+ // jumping to the touched tick)
+ break;
case MotionEvent.ACTION_MOVE:
+ if (mMode == MODE_IGNORE_UNTIL_UP) return true;
+
// Fall through to code below switch
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
- if (mCallback != null) {
- if (mMode == MODE_MOVE_ZOOM_RING || mMode == MODE_WAITING_FOR_MOVE_ZOOM_RING) {
- mCallback.onZoomRingSetMovableHintVisible(false);
- if (mMode == MODE_MOVE_ZOOM_RING) {
- mCallback.onZoomRingMovingStopped();
- }
- } else if (mMode == MODE_DRAG_THUMB || mMode == MODE_TAP_DRAG) {
- onThumbDragStopped(getAngle(x - mCenterX, y - mCenterY));
+ if (mMode == MODE_MOVE_ZOOM_RING || mMode == MODE_WAITING_FOR_MOVE_ZOOM_RING) {
+ mCallback.onZoomRingSetMovableHintVisible(false);
+ if (mMode == MODE_MOVE_ZOOM_RING) {
+ mCallback.onZoomRingMovingStopped();
+ }
+ } else if (mMode == MODE_DRAG_THUMB || mMode == MODE_TAP_DRAG ||
+ mMode == MODE_WAITING_FOR_DRAG_THUMB) {
+ onThumbDragStopped();
+
+ if (mMode == MODE_DRAG_THUMB) {
+ // Animate back to a tick
+ setThumbAngleAnimated(mPreviousCallbackAngle, 0);
}
}
- mDisabler.setEnabling(true);
+
+ mPreviousUpTime = time;
+ mCallback.onUserInteractionStopped();
return true;
default:
@@ -283,18 +468,18 @@ public class ZoomRing extends View {
int localX = x - mCenterX;
int localY = y - mCenterY;
boolean isTouchingThumb = true;
- boolean isInBounds = true;
+ boolean isInRingBounds = true;
+
int touchAngle = getAngle(localX, localY);
-
int radiusSquared = localX * localX + localY * localY;
if (radiusSquared < mBoundInnerRadiusSquared ||
radiusSquared > mBoundOuterRadiusSquared) {
// Out-of-bounds
isTouchingThumb = false;
- isInBounds = false;
+ isInRingBounds = false;
}
- int deltaThumbAndTouch = getDelta(touchAngle, mThumbAngle);
+ int deltaThumbAndTouch = getDelta(mThumbAngle, touchAngle);
int absoluteDeltaThumbAndTouch = deltaThumbAndTouch >= 0 ?
deltaThumbAndTouch : -deltaThumbAndTouch;
if (isTouchingThumb &&
@@ -305,17 +490,68 @@ public class ZoomRing extends View {
if (mMode == MODE_IDLE) {
if (isTouchingThumb) {
+ // They grabbed the thumb
mMode = MODE_DRAG_THUMB;
+ onThumbDragStarted(touchAngle);
+
+ } else if (isInRingBounds) {
+ // They tapped somewhere else on the ring
+ int tickAngle = getClosestTickAngle(touchAngle);
+
+ int deltaThumbAndTick = getDelta(mThumbAngle, tickAngle);
+ int boundAngle = getBoundIfExceeds(mThumbAngle, deltaThumbAndTick);
+
+ if (mEnforceMaxAbsJump) {
+ // Enforcing the max jump
+ if (deltaThumbAndTick > MAX_ABS_JUMP_DELTA_ANGLE ||
+ deltaThumbAndTick < -MAX_ABS_JUMP_DELTA_ANGLE) {
+ // Trying to jump too far, ignore this touch interaction
+ mMode = MODE_IGNORE_UNTIL_UP;
+ return true;
+ }
+
+ // Make sure we only let them jump within bounds
+ if (boundAngle != Integer.MIN_VALUE) {
+ tickAngle = boundAngle;
+ }
+ } else {
+ // Not enforcing the max jump, but we have to make sure
+ // we're getting to the tapped angle by going through the
+ // in-bounds region
+ if (boundAngle != Integer.MIN_VALUE) {
+ // Going this direction hits a bound, let's go the opposite direction
+ boolean oldDirectionIsCcw = deltaThumbAndTick > 0;
+ deltaThumbAndTick = getDelta(mThumbAngle, tickAngle, !oldDirectionIsCcw);
+ boundAngle = getBoundIfExceeds(mThumbAngle, deltaThumbAndTick);
+ if (boundAngle != Integer.MIN_VALUE) {
+ Log
+ .d(
+ TAG,
+ "Tapped somewhere where the shortest distance goes through a bound, but then the opposite direction also went through a bound!");
+ }
+ }
+ }
+
+ mMode = MODE_WAITING_FOR_DRAG_THUMB;
+ mWaitingForDragThumbDownAngle = touchAngle;
+ boolean ccw = deltaThumbAndTick > 0;
+ setThumbAngleAnimated(tickAngle, 0, ccw);
+
+ // Our thumb scrolling animation takes us from mThumbAngle to tickAngle
+ onThumbDragStarted(mThumbAngle);
+ onThumbDragged(tickAngle, true, ccw);
+
} else {
+ // They tapped somewhere else
mMode = MODE_WAITING_FOR_MOVE_ZOOM_RING;
+ mCallback.onZoomRingSetMovableHintVisible(true);
}
- if (mCallback != null) {
- if (mMode == MODE_DRAG_THUMB) {
- onThumbDragStarted(touchAngle);
- } else if (mMode == MODE_WAITING_FOR_MOVE_ZOOM_RING) {
- mCallback.onZoomRingSetMovableHintVisible(true);
- }
+ } else if (mMode == MODE_WAITING_FOR_DRAG_THUMB) {
+ int deltaDownAngle = getDelta(mWaitingForDragThumbDownAngle, touchAngle);
+ if ((deltaDownAngle < -THUMB_DRAG_SLOP || deltaDownAngle > THUMB_DRAG_SLOP) &&
+ isDeltaInBounds(mWaitingForDragThumbDownAngle, deltaDownAngle)) {
+ mMode = MODE_DRAG_THUMB;
}
} else if (mMode == MODE_WAITING_FOR_MOVE_ZOOM_RING) {
@@ -323,19 +559,14 @@ public class ZoomRing extends View {
Math.abs(y - mPreviousDownY) > mTouchSlop) {
/* Make sure the user has moved the slop amount before going into that mode. */
mMode = MODE_MOVE_ZOOM_RING;
-
- if (mCallback != null) {
- mCallback.onZoomRingMovingStarted();
- }
+ mCallback.onZoomRingMovingStarted();
}
}
// Purposefully not an "else if"
if (mMode == MODE_DRAG_THUMB || mMode == MODE_TAP_DRAG) {
- if (isInBounds) {
- onThumbDragged(touchAngle, mIsThumbAngleValid ? deltaThumbAndTouch : 0);
- } else {
- mIsThumbAngleValid = false;
+ if (isInRingBounds) {
+ onThumbDragged(touchAngle, false, false);
}
} else if (mMode == MODE_MOVE_ZOOM_RING) {
onZoomRingMoved(rawX, rawY);
@@ -344,55 +575,219 @@ public class ZoomRing extends View {
return true;
}
- private int getDelta(int angle1, int angle2) {
- int delta = angle1 - angle2;
-
- // Assume this is a result of crossing over the discontinuous 0 -> 2pi
- if (delta > PI_INT_MULTIPLIED || delta < -PI_INT_MULTIPLIED) {
- // Bring both the radians and previous angle onto a continuous range
- if (angle1 < HALF_PI_INT_MULTIPLIED) {
- // Same as deltaRadians = (radians + 2PI) - previousAngle
- delta += PI_INT_MULTIPLIED * 2;
- } else if (angle2 < HALF_PI_INT_MULTIPLIED) {
- // Same as deltaRadians = radians - (previousAngle + 2PI)
- delta -= PI_INT_MULTIPLIED * 2;
+ private boolean isDeltaInBounds(int startAngle, int deltaAngle) {
+ return getBoundIfExceeds(startAngle, deltaAngle) == Integer.MIN_VALUE;
+ }
+
+ private int getBoundIfExceeds(int startAngle, int deltaAngle) {
+ if (deltaAngle > 0) {
+ // Counterclockwise movement
+ if (mThumbCcwBound != Integer.MIN_VALUE &&
+ getDelta(startAngle, mThumbCcwBound, true) < deltaAngle) {
+ return mThumbCcwBound;
+ }
+ } else if (deltaAngle < 0) {
+ // Clockwise movement, both of these will be negative
+ int deltaThumbAndBound = getDelta(startAngle, mThumbCwBound, false);
+ if (mThumbCwBound != Integer.MIN_VALUE &&
+ deltaThumbAndBound > deltaAngle) {
+ // Tapped outside of the bound in that direction
+ return mThumbCwBound;
}
}
-
- return delta;
+
+ return Integer.MIN_VALUE;
}
+ private int getDelta(int startAngle, int endAngle, boolean useDirection, boolean ccw) {
+ return useDirection ? getDelta(startAngle, endAngle, ccw) : getDelta(startAngle, endAngle);
+ }
+
+ /**
+ * Gets the smallest delta between two angles, and infers the direction
+ * based on the shortest path between the two angles. If going from
+ * startAngle to endAngle is counterclockwise, the result will be positive.
+ * If it is clockwise, the result will be negative.
+ *
+ * @param startAngle The start angle.
+ * @param endAngle The end angle.
+ * @return The difference in angles.
+ */
+ private int getDelta(int startAngle, int endAngle) {
+ int largerAngle, smallerAngle;
+ if (endAngle > startAngle) {
+ largerAngle = endAngle;
+ smallerAngle = startAngle;
+ } else {
+ largerAngle = startAngle;
+ smallerAngle = endAngle;
+ }
+
+ int delta = largerAngle - smallerAngle;
+ if (delta <= PI_INT_MULTIPLIED) {
+ // If going clockwise, negate the delta
+ return startAngle == largerAngle ? -delta : delta;
+ } else {
+ // The other direction is the delta we want (it includes the
+ // discontinuous 0-2PI angle)
+ delta = TWO_PI_INT_MULTIPLIED - delta;
+ // If going clockwise, negate the delta
+ return startAngle == smallerAngle ? -delta : delta;
+ }
+ }
+
+ /**
+ * Gets the delta between two angles in the direction specified.
+ *
+ * @param startAngle The start angle.
+ * @param endAngle The end angle.
+ * @param counterClockwise The direction to take when computing the delta.
+ * @return The difference in angles in the given direction.
+ */
+ private int getDelta(int startAngle, int endAngle, boolean counterClockwise) {
+ int delta = endAngle - startAngle;
+
+ if (!counterClockwise && delta > 0) {
+ // Crossed the discontinuous 0/2PI angle, take the leftover slice of
+ // the pie and negate it
+ return -TWO_PI_INT_MULTIPLIED + delta;
+ } else if (counterClockwise && delta < 0) {
+ // Crossed the discontinuous 0/2PI angle, take the leftover slice of
+ // the pie (and ensure it is positive)
+ return TWO_PI_INT_MULTIPLIED + delta;
+ } else {
+ return delta;
+ }
+ }
+
private void onThumbDragStarted(int startAngle) {
+ setThumbArrowsVisible(false);
mThumbDragStartAngle = startAngle;
- mCallback.onZoomRingThumbDraggingStarted(startAngle);
+ mCallback.onZoomRingThumbDraggingStarted();
}
+
+ private void onThumbDragged(int touchAngle, boolean useDirection, boolean ccw) {
+ boolean animateThumbToNewAngle = false;
+
+ int totalDeltaAngle;
+ totalDeltaAngle = getDelta(mPreviousCallbackAngle, touchAngle, useDirection, ccw);
+ int fuzzyCallbackThreshold = (int) (mCallbackThreshold * 0.65f);
+ if (totalDeltaAngle >= fuzzyCallbackThreshold
+ || totalDeltaAngle <= -fuzzyCallbackThreshold) {
- private void onThumbDragged(int touchAngle, int deltaAngle) {
- mAcculumalatedTrailAngle += Math.toDegrees(deltaAngle / (double) RADIAN_INT_MULTIPLIER);
- int totalDeltaAngle = getDelta(touchAngle, mPreviousCallbackAngle);
- if (totalDeltaAngle > mCallbackThreshold
- || totalDeltaAngle < -mCallbackThreshold) {
- if (mCallback != null) {
- boolean canStillZoom = mCallback.onZoomRingThumbDragged(
- totalDeltaAngle / mCallbackThreshold,
- mThumbDragStartAngle, touchAngle);
- mDisabler.setEnabling(canStillZoom);
-
- if (canStillZoom) {
- // TODO: we're trying the haptics to see how it goes with
- // users, so we're ignoring the settings (for now)
- performHapticFeedback(HapticFeedbackConstants.ZOOM_RING_TICK,
- HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING |
- HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
+ if (!useDirection) {
+ // Set ccw to match the direction found by getDelta
+ ccw = totalDeltaAngle > 0;
+ }
+
+ /*
+ * When the user slides the thumb through the tick that corresponds
+ * to a zoom bound, we don't want to abruptly stop there. Instead,
+ * let the user slide it to the next tick, and then animate it back
+ * to the original zoom bound tick. Because of this, we make sure
+ * the delta from the bound is more than halfway to the next tick.
+ * We make sure the bound is between the touch and the previous
+ * callback to ensure we just passed the bound.
+ */
+ int oldTouchAngle = touchAngle;
+ if (ccw && mThumbCcwBound != Integer.MIN_VALUE) {
+ int deltaCcwBoundAndTouch =
+ getDelta(mThumbCcwBound, touchAngle, useDirection, true);
+ if (deltaCcwBoundAndTouch >= mCallbackThreshold / 2) {
+ // The touch has past a bound
+ int deltaPreviousCbAndTouch = getDelta(mPreviousCallbackAngle,
+ touchAngle, useDirection, true);
+ if (deltaPreviousCbAndTouch >= deltaCcwBoundAndTouch) {
+ // The bound is between the previous callback angle and the touch
+ touchAngle = mThumbCcwBound;
+ // We're moving the touch BACK to the bound, so opposite direction
+ ccw = false;
+ }
+ }
+ } else if (!ccw && mThumbCwBound != Integer.MIN_VALUE) {
+ // See block above for general comments
+ int deltaCwBoundAndTouch =
+ getDelta(mThumbCwBound, touchAngle, useDirection, false);
+ if (deltaCwBoundAndTouch <= -mCallbackThreshold / 2) {
+ int deltaPreviousCbAndTouch = getDelta(mPreviousCallbackAngle,
+ touchAngle, useDirection, false);
+ /*
+ * Both of these will be negative since we got delta in
+ * clockwise direction, and we want the magnitude of
+ * deltaPreviousCbAndTouch to be greater than the magnitude
+ * of deltaCwBoundAndTouch
+ */
+ if (deltaPreviousCbAndTouch <= deltaCwBoundAndTouch) {
+ touchAngle = mThumbCwBound;
+ ccw = true;
+ }
+ }
+ }
+ if (touchAngle != oldTouchAngle) {
+ // We bounded the touch angle
+ totalDeltaAngle = getDelta(mPreviousCallbackAngle, touchAngle, useDirection, ccw);
+ animateThumbToNewAngle = true;
+ mMode = MODE_IGNORE_UNTIL_UP;
+ }
+
+
+ // Prevent it from jumping too far
+ if (mEnforceMaxAbsJump) {
+ if (totalDeltaAngle <= -MAX_ABS_JUMP_DELTA_ANGLE) {
+ totalDeltaAngle = -MAX_ABS_JUMP_DELTA_ANGLE;
+ animateThumbToNewAngle = true;
+ } else if (totalDeltaAngle >= MAX_ABS_JUMP_DELTA_ANGLE) {
+ totalDeltaAngle = MAX_ABS_JUMP_DELTA_ANGLE;
+ animateThumbToNewAngle = true;
}
}
- // Get the closest tick and lock on there
- mPreviousCallbackAngle = getClosestTickAngle(touchAngle);
+ /*
+ * We need to cover the edge case of a user grabbing the thumb,
+ * going into the center of the widget, and then coming out from the
+ * center to an angle that's slightly below the angle he's trying to
+ * hit. If we do int division, we'll end up with one level lower
+ * than the one he was going for.
+ */
+ int deltaLevels = Math.round((float) totalDeltaAngle / mCallbackThreshold);
+ if (deltaLevels != 0) {
+ boolean canStillZoom = mCallback.onZoomRingThumbDragged(
+ deltaLevels, mThumbDragStartAngle, touchAngle);
+
+ // TODO: we're trying the haptics to see how it goes with
+ // users, so we're ignoring the settings (for now)
+ performHapticFeedback(HapticFeedbackConstants.ZOOM_RING_TICK,
+ HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING |
+ HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
+
+ // Set the callback angle to the actual angle based on how many delta levels we gave
+ mPreviousCallbackAngle = getValidAngle(
+ mPreviousCallbackAngle + (deltaLevels * mCallbackThreshold));
+ }
}
- setThumbAngle(touchAngle);
- mIsThumbAngleValid = true;
+ int deltaAngle = getDelta(mThumbAngle, touchAngle, useDirection, ccw);
+ mAcculumalatedTrailAngle += Math.toDegrees(deltaAngle / (double) RADIAN_INT_MULTIPLIER);
+
+ if (animateThumbToNewAngle) {
+ if (useDirection) {
+ setThumbAngleAnimated(touchAngle, 0, ccw);
+ } else {
+ setThumbAngleAnimated(touchAngle, 0);
+ }
+ } else {
+ setThumbAngleAuto(touchAngle, useDirection, ccw);
+ }
+ }
+
+ private int getValidAngle(int invalidAngle) {
+ if (invalidAngle < 0) {
+ return (invalidAngle % TWO_PI_INT_MULTIPLIED) + TWO_PI_INT_MULTIPLIED;
+ } else if (invalidAngle >= TWO_PI_INT_MULTIPLIED) {
+ return invalidAngle % TWO_PI_INT_MULTIPLIED;
+ } else {
+ return invalidAngle;
+ }
}
private int getClosestTickAngle(int angle) {
@@ -403,12 +798,12 @@ public class ZoomRing extends View {
return smallerAngle;
} else {
// Closer to the bigger angle (premodding)
- return (smallerAngle + mCallbackThreshold) % (PI_INT_MULTIPLIED * 2);
+ return (smallerAngle + mCallbackThreshold) % TWO_PI_INT_MULTIPLIED;
}
}
- private void onThumbDragStopped(int stopAngle) {
- mCallback.onZoomRingThumbDraggingStopped(stopAngle);
+ private void onThumbDragStopped() {
+ mCallback.onZoomRingThumbDraggingStopped();
}
private void onZoomRingMoved(int x, int y) {
@@ -416,9 +811,7 @@ public class ZoomRing extends View {
int deltaX = x - mPreviousWidgetDragX;
int deltaY = y - mPreviousWidgetDragY;
- if (mCallback != null) {
- mCallback.onZoomRingMoved(deltaX, deltaY);
- }
+ mCallback.onZoomRingMoved(deltaX, deltaY);
}
mPreviousWidgetDragX = x;
@@ -429,11 +822,11 @@ public class ZoomRing extends View {
public void onWindowFocusChanged(boolean hasWindowFocus) {
super.onWindowFocusChanged(hasWindowFocus);
- if (!hasWindowFocus && mCallback != null) {
- mCallback.onZoomRingDismissed();
+ if (!hasWindowFocus) {
+ mCallback.onZoomRingDismissed(true);
}
}
-
+
private int getAngle(int localX, int localY) {
int radians = (int) (Math.atan2(localY, localX) * RADIAN_INT_MULTIPLIER);
@@ -458,45 +851,65 @@ public class ZoomRing extends View {
if (DRAW_TRAIL) {
mTrail.draw(canvas);
}
+
+ // If we aren't near the bounds, draw the corresponding arrows
+ int callbackAngle = mPreviousCallbackAngle;
+ if (callbackAngle < mThumbCwBound - RADIAN_INT_ERROR ||
+ callbackAngle > mThumbCwBound + RADIAN_INT_ERROR) {
+ mThumbPlusArrowDrawable.draw(canvas);
+ }
+ if (callbackAngle < mThumbCcwBound - RADIAN_INT_ERROR ||
+ callbackAngle > mThumbCcwBound + RADIAN_INT_ERROR) {
+ mThumbMinusArrowDrawable.draw(canvas);
+ }
mThumbDrawable.draw(canvas);
}
}
-
- private class Disabler implements Runnable {
- private static final int DELAY = 15;
- private static final float ENABLE_RATE = 1.05f;
- private static final float DISABLE_RATE = 0.95f;
-
- private int mAlpha = 255;
- private boolean mEnabling;
-
- public int getAlpha() {
- return mAlpha;
- }
-
- public void setEnabling(boolean enabling) {
- if ((enabling && mAlpha != 255) || (!enabling && mAlpha != DISABLED_ALPHA)) {
- mEnabling = enabling;
- post(this);
- }
- }
-
- public void run() {
- mAlpha *= mEnabling ? ENABLE_RATE : DISABLE_RATE;
- if (mAlpha < DISABLED_ALPHA) {
- mAlpha = DISABLED_ALPHA;
- } else if (mAlpha > 255) {
- mAlpha = 255;
- } else {
- // Still more to go
- postDelayed(this, DELAY);
- }
-
- getBackground().setAlpha(mAlpha);
+
+ private void setThumbArrowsAngle(int angle) {
+ int level = -angle * 10000 / ZoomRing.TWO_PI_INT_MULTIPLIED;
+ mThumbPlusArrowDrawable.setLevel(level);
+ mThumbMinusArrowDrawable.setLevel(level);
+ }
+
+ public void setThumbArrowsVisible(boolean visible) {
+ if (visible) {
+ mThumbArrowsAlpha = 255;
+ mThumbPlusArrowDrawable.setAlpha(255);
+ mThumbMinusArrowDrawable.setAlpha(255);
invalidate();
+ } else if (mThumbArrowsAlpha == 255) {
+ // Only start fade if we're fully visible (otherwise another fade is happening already)
+ mThumbArrowsFadeStartTime = SystemClock.elapsedRealtime();
+ onThumbArrowsFadeTick();
}
}
+ private void onThumbArrowsFadeTick() {
+ if (mThumbArrowsAlpha <= 0) return;
+
+ mThumbArrowsAlpha = (int)
+ (255 - (255 * (SystemClock.elapsedRealtime() - mThumbArrowsFadeStartTime)
+ / THUMB_ARROWS_FADE_DURATION));
+ if (mThumbArrowsAlpha < 0) mThumbArrowsAlpha = 0;
+ mThumbPlusArrowDrawable.setAlpha(mThumbArrowsAlpha);
+ mThumbMinusArrowDrawable.setAlpha(mThumbArrowsAlpha);
+ invalidateDrawable(mThumbPlusArrowDrawable);
+ invalidateDrawable(mThumbMinusArrowDrawable);
+
+ if (!mHandler.hasMessages(MSG_THUMB_ARROWS_FADE_TICK)) {
+ mHandler.sendEmptyMessage(MSG_THUMB_ARROWS_FADE_TICK);
+ }
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+
+ setThumbArrowsAngle(mThumbAngle);
+ setThumbArrowsVisible(true);
+ }
+
public interface OnZoomRingCallback {
void onZoomRingSetMovableHintVisible(boolean visible);
@@ -504,11 +917,17 @@ public class ZoomRing extends View {
boolean onZoomRingMoved(int deltaX, int deltaY);
void onZoomRingMovingStopped();
- void onZoomRingThumbDraggingStarted(int startAngle);
+ void onZoomRingThumbDraggingStarted();
boolean onZoomRingThumbDragged(int numLevels, int startAngle, int curAngle);
- void onZoomRingThumbDraggingStopped(int endAngle);
+ void onZoomRingThumbDraggingStopped();
- void onZoomRingDismissed();
+ void onZoomRingDismissed(boolean dismissImmediately);
+
+ void onUserInteractionStarted();
+ void onUserInteractionStopped();
}
+ private static void printAngle(String angleName, int angle) {
+ Log.d(TAG, angleName + ": " + (long) angle * 180 / PI_INT_MULTIPLIED);
+ }
}
diff --git a/core/java/android/widget/ZoomRingController.java b/core/java/android/widget/ZoomRingController.java
index eb287670c7a16..31074b6402698 100644
--- a/core/java/android/widget/ZoomRingController.java
+++ b/core/java/android/widget/ZoomRingController.java
@@ -16,6 +16,8 @@
package android.widget;
+import android.app.AlertDialog;
+import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -27,7 +29,6 @@ import android.graphics.Rect;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
-import android.os.Vibrator;
import android.provider.Settings;
import android.util.Log;
import android.view.Gravity;
@@ -35,6 +36,7 @@ import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
+import android.view.Window;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.animation.Animation;
@@ -46,12 +48,16 @@ import android.view.animation.DecelerateInterpolator;
/**
* TODO: Docs
*
+ * If you are using this with a custom View, please call
+ * {@link #setVisible(boolean) setVisible(false)} from the
+ * {@link View#onDetachedFromWindow}.
+ *
* @hide
*/
public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
View.OnTouchListener, View.OnKeyListener {
- private static final int SHOW_TUTORIAL_TOAST_DELAY = 1000;
+ private static final int ZOOM_RING_RADIUS_INSET = 10;
private static final int ZOOM_RING_RECENTERING_DURATION = 500;
@@ -69,9 +75,11 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
// TODO: scale px values based on latest from ViewConfiguration
private static final int SECOND_TAP_TIMEOUT = 500;
private static final int ZOOM_RING_DISMISS_DELAY = SECOND_TAP_TIMEOUT / 2;
- private static final int SECOND_TAP_SLOP = 70;
- private static final int SECOND_TAP_MOVE_SLOP = 15;
- private static final int MAX_PAN_GAP = 30;
+ // TODO: view config? at least scaled
+ private static final int MAX_PAN_GAP = 20;
+ private static final int MAX_INITIATE_PAN_GAP = 10;
+ // TODO view config
+ private static final int INITIATE_PAN_DELAY = 400;
private static final String SETTING_NAME_SHOWN_TOAST = "shown_zoom_ring_toast";
@@ -95,6 +103,23 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
private FrameLayout mContainer;
private LayoutParams mContainerLayoutParams;
+ /**
+ * The view (or null) that should receive touch events. This will get set if
+ * the touch down hits the container. It will be reset on the touch up.
+ */
+ private View mTouchTargetView;
+ /**
+ * The {@link #mTouchTargetView}'s location in window, set on touch down.
+ */
+ private int[] mTouchTargetLocationInWindow = new int[2];
+ /**
+ * If the zoom ring is dismissed but the user is still in a touch
+ * interaction, we set this to true. This will ignore all touch events until
+ * up/cancel, and then set the owner's touch listener to null.
+ */
+ private boolean mReleaseTouchListenerOnUp;
+
+
/*
* Tap-drag is an interaction where the user first taps and then (quickly)
* does the clockwise or counter-clockwise drag. In reality, this is: (down,
@@ -122,6 +147,8 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
/** Invokes panning of owner view if the zoom ring is touching an edge. */
private Panner mPanner = new Panner();
+ private long mTouchingEdgeStartTime;
+ private boolean mPanningEnabledForThisInteraction;
private ImageView mPanningArrows;
private Animation mPanningArrowsEnterAnimation;
@@ -162,26 +189,13 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
* the UI thread so it will be exceuted AFTER the layout. This is the logic.
*/
private Runnable mPostedVisibleInitializer;
-
- // TODO: need a better way to persist this value, becuase right now this
- // requires the WRITE_SETTINGS perimssion which the app may not have
-// private Runnable mShowTutorialToast = new Runnable() {
-// public void run() {
-// if (Settings.System.getInt(mContext.getContentResolver(),
-// SETTING_NAME_SHOWN_TOAST, 0) == 1) {
-// return;
-// }
-// try {
-// Settings.System.putInt(mContext.getContentResolver(), SETTING_NAME_SHOWN_TOAST, 1);
-// } catch (SecurityException e) {
-// // The app does not have permission to clear this flag, oh well!
-// }
-//
-// Toast.makeText(mContext,
-// com.android.internal.R.string.tutorial_double_tap_to_zoom_message,
-// Toast.LENGTH_LONG).show();
-// }
-// };
+
+ /**
+ * Only touch from the main thread.
+ */
+ private static Dialog sTutorialDialog;
+ private static long sTutorialShowTime;
+ private static final int TUTORIAL_MIN_DISPLAY_TIME = 2000;
private IntentFilter mConfigurationChangedFilter =
new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED);
@@ -230,38 +244,37 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
mOwnerView = ownerView;
mZoomRing = new ZoomRing(context);
+ mZoomRing.setId(com.android.internal.R.id.zoomControls);
mZoomRing.setLayoutParams(new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT,
- FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.CENTER));
+ FrameLayout.LayoutParams.WRAP_CONTENT,
+ Gravity.CENTER));
mZoomRing.setCallback(this);
createPanningArrows();
- mContainer = new FrameLayout(context);
- mContainer.setMeasureAllChildren(true);
- mContainer.setOnTouchListener(this);
-
- mContainer.addView(mZoomRing);
- mContainer.addView(mPanningArrows);
- mContainer.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
-
mContainerLayoutParams = new LayoutParams();
mContainerLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
- mContainerLayoutParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL |
+ mContainerLayoutParams.flags = LayoutParams.FLAG_NOT_TOUCHABLE |
LayoutParams.FLAG_NOT_FOCUSABLE |
- LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | LayoutParams.FLAG_LAYOUT_NO_LIMITS;
+ LayoutParams.FLAG_LAYOUT_NO_LIMITS;
mContainerLayoutParams.height = LayoutParams.WRAP_CONTENT;
mContainerLayoutParams.width = LayoutParams.WRAP_CONTENT;
mContainerLayoutParams.type = LayoutParams.TYPE_APPLICATION_PANEL;
- mContainerLayoutParams.format = PixelFormat.TRANSLUCENT;
+ mContainerLayoutParams.format = PixelFormat.TRANSPARENT;
// TODO: make a new animation for this
mContainerLayoutParams.windowAnimations = com.android.internal.R.style.Animation_Dialog;
+
+ mContainer = new FrameLayout(context);
+ mContainer.setLayoutParams(mContainerLayoutParams);
+ mContainer.setMeasureAllChildren(true);
+
+ mContainer.addView(mZoomRing);
+ mContainer.addView(mPanningArrows);
mScroller = new Scroller(context, new DecelerateInterpolator());
mViewConfig = ViewConfiguration.get(context);
-
-// mHandler.postDelayed(mShowTutorialToast, SHOW_TUTORIAL_TOAST_DELAY);
}
private void createPanningArrows() {
@@ -272,7 +285,7 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT,
Gravity.CENTER));
- mPanningArrows.setVisibility(View.GONE);
+ mPanningArrows.setVisibility(View.INVISIBLE);
mPanningArrowsEnterAnimation = AnimationUtils.loadAnimation(mContext,
com.android.internal.R.anim.fade_in);
@@ -291,6 +304,17 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
public void setZoomCallbackThreshold(float callbackThreshold) {
mZoomRing.setCallbackThreshold((int) (callbackThreshold * ZoomRing.RADIAN_INT_MULTIPLIER));
}
+
+ /**
+ * Sets a drawable for the zoom ring track.
+ *
+ * @param drawable The drawable to use for the track.
+ * @hide Need a better way of doing this, but this one-off for browser so it
+ * can have its final look for the usability study
+ */
+ public void setZoomRingTrack(int drawable) {
+ mZoomRing.setBackgroundResource(drawable);
+ }
public void setCallback(OnZoomListener callback) {
mCallback = callback;
@@ -300,10 +324,26 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
mZoomRing.setThumbAngle((int) (angle * ZoomRing.RADIAN_INT_MULTIPLIER));
}
+ public void setThumbAngleAnimated(float angle) {
+ mZoomRing.setThumbAngleAnimated((int) (angle * ZoomRing.RADIAN_INT_MULTIPLIER), 0);
+ }
+
public void setResetThumbAutomatically(boolean resetThumbAutomatically) {
mZoomRing.setResetThumbAutomatically(resetThumbAutomatically);
}
+ public void setThumbClockwiseBound(float angle) {
+ mZoomRing.setThumbClockwiseBound(angle >= 0 ?
+ (int) (angle * ZoomRing.RADIAN_INT_MULTIPLIER) :
+ Integer.MIN_VALUE);
+ }
+
+ public void setThumbCounterclockwiseBound(float angle) {
+ mZoomRing.setThumbCounterclockwiseBound(angle >= 0 ?
+ (int) (angle * ZoomRing.RADIAN_INT_MULTIPLIER) :
+ Integer.MIN_VALUE);
+ }
+
public boolean isVisible() {
return mIsZoomRingVisible;
}
@@ -321,12 +361,13 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
if (mIsZoomRingVisible == visible) {
return;
}
+ mIsZoomRingVisible = visible;
if (visible) {
if (mContainerLayoutParams.token == null) {
mContainerLayoutParams.token = mOwnerView.getWindowToken();
}
-
+
mWindowManager.addView(mContainer, mContainerLayoutParams);
if (mPostedVisibleInitializer == null) {
@@ -340,6 +381,10 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
// probably can only be retrieved after it's measured, which happens
// after it's added).
mWindowManager.updateViewLayout(mContainer, mContainerLayoutParams);
+
+ if (mCallback != null) {
+ mCallback.onVisibilityChanged(true);
+ }
}
};
}
@@ -349,24 +394,49 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
// Handle configuration changes when visible
mContext.registerReceiver(mConfigurationChangedReceiver, mConfigurationChangedFilter);
- // Steal key events from the owner
+ // Steal key/touches events from the owner
mOwnerView.setOnKeyListener(this);
+ mOwnerView.setOnTouchListener(this);
+ mReleaseTouchListenerOnUp = false;
} else {
- // Don't want to steal any more keys
+ // Don't want to steal any more keys/touches
mOwnerView.setOnKeyListener(null);
+ if (mTouchTargetView != null) {
+ // We are still stealing the touch events for this touch
+ // sequence, so release the touch listener later
+ mReleaseTouchListenerOnUp = true;
+ } else {
+ mOwnerView.setOnTouchListener(null);
+ }
// No longer care about configuration changes
mContext.unregisterReceiver(mConfigurationChangedReceiver);
mWindowManager.removeView(mContainer);
+
+ if (mCallback != null) {
+ mCallback.onVisibilityChanged(false);
+ }
}
- mIsZoomRingVisible = visible;
-
- if (mCallback != null) {
- mCallback.onVisibilityChanged(visible);
- }
+ }
+
+ /**
+ * TODO: docs
+ *
+ * Notes:
+ * - Touch dispatching is different. Only direct children who are clickable are eligble for touch events.
+ * - Please ensure you set your View to INVISIBLE not GONE when hiding it.
+ *
+ * @return
+ */
+ public FrameLayout getContainer() {
+ return mContainer;
+ }
+
+ public int getZoomRingId() {
+ return mZoomRing.getId();
}
private void dismissZoomRingDelayed(int delay) {
@@ -484,77 +554,8 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
mOwnerViewBounds, mTempRect);
mCenteredContainerX = mTempRect.left;
mCenteredContainerY = mTempRect.top;
-
}
- // MOVE ALL THIS TO GESTURE DETECTOR
-// public boolean onTouch(View v, MotionEvent event) {
-// int action = event.getAction();
-//
-// if (mListenForInvocation) {
-// switch (mTouchMode) {
-// case TOUCH_MODE_IDLE: {
-// if (action == MotionEvent.ACTION_DOWN) {
-// setFirstTap(event);
-// }
-// break;
-// }
-//
-// case TOUCH_MODE_WAITING_FOR_SECOND_TAP: {
-// switch (action) {
-// case MotionEvent.ACTION_DOWN:
-// if (isSecondTapWithinSlop(event)) {
-// handleDoubleTapEvent(event);
-// } else {
-// setFirstTap(event);
-// }
-// break;
-//
-// case MotionEvent.ACTION_MOVE:
-// int deltaX = (int) event.getX() - mFirstTapX;
-// if (deltaX < -SECOND_TAP_MOVE_SLOP ||
-// deltaX > SECOND_TAP_MOVE_SLOP) {
-// mTouchMode = TOUCH_MODE_IDLE;
-// } else {
-// int deltaY = (int) event.getY() - mFirstTapY;
-// if (deltaY < -SECOND_TAP_MOVE_SLOP ||
-// deltaY > SECOND_TAP_MOVE_SLOP) {
-// mTouchMode = TOUCH_MODE_IDLE;
-// }
-// }
-// break;
-// }
-// break;
-// }
-//
-// case TOUCH_MODE_WAITING_FOR_TAP_DRAG_MOVEMENT:
-// case TOUCH_MODE_FORWARDING_FOR_TAP_DRAG: {
-// handleDoubleTapEvent(event);
-// break;
-// }
-// }
-//
-// if (action == MotionEvent.ACTION_CANCEL) {
-// mTouchMode = TOUCH_MODE_IDLE;
-// }
-// }
-//
-// return false;
-// }
-//
-// private void setFirstTap(MotionEvent event) {
-// mFirstTapTime = event.getEventTime();
-// mFirstTapX = (int) event.getX();
-// mFirstTapY = (int) event.getY();
-// mTouchMode = TOUCH_MODE_WAITING_FOR_SECOND_TAP;
-// }
-//
-// private boolean isSecondTapWithinSlop(MotionEvent event) {
-// return mFirstTapTime + SECOND_TAP_TIMEOUT > event.getEventTime() &&
-// Math.abs((int) event.getX() - mFirstTapX) < SECOND_TAP_SLOP &&
-// Math.abs((int) event.getY() - mFirstTapY) < SECOND_TAP_SLOP;
-// }
-
/**
* Centers the point (in owner view's coordinates).
*/
@@ -575,16 +576,28 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
public void onZoomRingSetMovableHintVisible(boolean visible) {
setPanningArrowsVisible(visible);
}
+
+ public void onUserInteractionStarted() {
+ mHandler.removeMessages(MSG_DISMISS_ZOOM_RING);
+ }
+
+ public void onUserInteractionStopped() {
+ dismissZoomRingDelayed(ZOOM_CONTROLS_TIMEOUT);
+ }
public void onZoomRingMovingStarted() {
- mHandler.removeMessages(MSG_DISMISS_ZOOM_RING);
mScroller.abortAnimation();
+ mPanningEnabledForThisInteraction = false;
+ mTouchingEdgeStartTime = 0;
+ if (mCallback != null) {
+ mCallback.onBeginPan();
+ }
}
private void setPanningArrowsVisible(boolean visible) {
mPanningArrows.startAnimation(visible ? mPanningArrowsEnterAnimation
: mPanningArrowsExitAnimation);
- mPanningArrows.setVisibility(visible ? View.VISIBLE : View.GONE);
+ mPanningArrows.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
}
public boolean onZoomRingMoved(int deltaX, int deltaY) {
@@ -611,37 +624,73 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
mWindowManager.updateViewLayout(mContainer, lp);
// Check for pan
+ boolean horizontalPanning = true;
int leftGap = newZoomRingX - ownerBounds.left;
if (leftGap < MAX_PAN_GAP) {
- mPanner.setHorizontalStrength(-getStrengthFromGap(leftGap));
+ if (shouldPan(leftGap)) {
+ mPanner.setHorizontalStrength(-getStrengthFromGap(leftGap));
+ }
} else {
int rightGap = ownerBounds.right - (lp.x + mZoomRingWidth + zoomRingLeft);
if (rightGap < MAX_PAN_GAP) {
- mPanner.setHorizontalStrength(getStrengthFromGap(rightGap));
+ if (shouldPan(rightGap)) {
+ mPanner.setHorizontalStrength(getStrengthFromGap(rightGap));
+ }
} else {
mPanner.setHorizontalStrength(0);
+ horizontalPanning = false;
}
}
int topGap = newZoomRingY - ownerBounds.top;
if (topGap < MAX_PAN_GAP) {
- mPanner.setVerticalStrength(-getStrengthFromGap(topGap));
+ if (shouldPan(topGap)) {
+ mPanner.setVerticalStrength(-getStrengthFromGap(topGap));
+ }
} else {
int bottomGap = ownerBounds.bottom - (lp.y + mZoomRingHeight + zoomRingTop);
if (bottomGap < MAX_PAN_GAP) {
- mPanner.setVerticalStrength(getStrengthFromGap(bottomGap));
+ if (shouldPan(bottomGap)) {
+ mPanner.setVerticalStrength(getStrengthFromGap(bottomGap));
+ }
} else {
mPanner.setVerticalStrength(0);
+ if (!horizontalPanning) {
+ // Neither are panning, reset any timer to start pan mode
+ mTouchingEdgeStartTime = 0;
+ }
}
}
return true;
}
+ private boolean shouldPan(int gap) {
+ if (mPanningEnabledForThisInteraction) return true;
+
+ if (gap < MAX_INITIATE_PAN_GAP) {
+ long time = SystemClock.elapsedRealtime();
+ if (mTouchingEdgeStartTime != 0 &&
+ mTouchingEdgeStartTime + INITIATE_PAN_DELAY < time) {
+ mPanningEnabledForThisInteraction = true;
+ return true;
+ } else if (mTouchingEdgeStartTime == 0) {
+ mTouchingEdgeStartTime = time;
+ } else {
+ }
+ } else {
+ // Moved away from the initiate pan gap, so reset the timer
+ mTouchingEdgeStartTime = 0;
+ }
+ return false;
+ }
+
public void onZoomRingMovingStopped() {
- dismissZoomRingDelayed(ZOOM_CONTROLS_TIMEOUT);
mPanner.stop();
- setPanningArrowsVisible(false);
+ setPanningArrowsVisible(false);
+ if (mCallback != null) {
+ mCallback.onEndPan();
+ }
}
private int getStrengthFromGap(int gap) {
@@ -649,10 +698,9 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
(MAX_PAN_GAP - gap) * 100 / MAX_PAN_GAP;
}
- public void onZoomRingThumbDraggingStarted(int startAngle) {
- mHandler.removeMessages(MSG_DISMISS_ZOOM_RING);
+ public void onZoomRingThumbDraggingStarted() {
if (mCallback != null) {
- mCallback.onBeginDrag((float) startAngle / ZoomRing.RADIAN_INT_MULTIPLIER);
+ mCallback.onBeginDrag();
}
}
@@ -674,25 +722,122 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
return false;
}
- public void onZoomRingThumbDraggingStopped(int endAngle) {
- dismissZoomRingDelayed(ZOOM_CONTROLS_TIMEOUT);
+ public void onZoomRingThumbDraggingStopped() {
if (mCallback != null) {
- mCallback.onEndDrag((float) endAngle / ZoomRing.RADIAN_INT_MULTIPLIER);
+ mCallback.onEndDrag();
}
}
- public void onZoomRingDismissed() {
- dismissZoomRingDelayed(ZOOM_RING_DISMISS_DELAY);
- }
-
- public boolean onTouch(View v, MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
- // If the user touches outside of the zoom ring, dismiss the zoom ring
+ public void onZoomRingDismissed(boolean dismissImmediately) {
+ if (dismissImmediately) {
+ mHandler.removeMessages(MSG_DISMISS_ZOOM_RING);
+ setVisible(false);
+ } else {
dismissZoomRingDelayed(ZOOM_RING_DISMISS_DELAY);
+ }
+ }
+
+ public void onRingDown(int tickAngle, int touchAngle) {
+ }
+
+ public boolean onTouch(View v, MotionEvent event) {
+ if (sTutorialDialog != null && sTutorialDialog.isShowing() &&
+ SystemClock.elapsedRealtime() - sTutorialShowTime >= TUTORIAL_MIN_DISPLAY_TIME) {
+ finishZoomTutorial();
+ }
+
+ int action = event.getAction();
+
+ if (mReleaseTouchListenerOnUp) {
+ // The ring was dismissed but we need to throw away all events until the up
+ if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+ mOwnerView.setOnTouchListener(null);
+ mReleaseTouchListenerOnUp = false;
+ }
+
+ // Eat this event
return true;
}
- return false;
+ View targetView = mTouchTargetView;
+
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ targetView = mTouchTargetView =
+ getViewForTouch((int) event.getRawX(), (int) event.getRawY());
+ if (targetView != null) {
+ targetView.getLocationInWindow(mTouchTargetLocationInWindow);
+ }
+ break;
+
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ mTouchTargetView = null;
+ break;
+ }
+
+ if (targetView != null) {
+ // The upperleft corner of the target view in raw coordinates
+ int targetViewRawX = mContainerLayoutParams.x + mTouchTargetLocationInWindow[0];
+ int targetViewRawY = mContainerLayoutParams.y + mTouchTargetLocationInWindow[1];
+
+ MotionEvent containerEvent = MotionEvent.obtain(event);
+ // Convert the motion event into the target view's coordinates (from
+ // owner view's coordinates)
+ containerEvent.offsetLocation(mOwnerViewBounds.left - targetViewRawX,
+ mOwnerViewBounds.top - targetViewRawY);
+ boolean retValue = targetView.dispatchTouchEvent(containerEvent);
+ containerEvent.recycle();
+ return retValue;
+
+ } else {
+ if (action == MotionEvent.ACTION_DOWN) {
+ dismissZoomRingDelayed(ZOOM_RING_DISMISS_DELAY);
+ }
+
+ return false;
+ }
+ }
+
+ /**
+ * Returns the View that should receive a touch at the given coordinates.
+ *
+ * @param rawX The raw X.
+ * @param rawY The raw Y.
+ * @return The view that should receive the touches, or null if there is not one.
+ */
+ private View getViewForTouch(int rawX, int rawY) {
+ // Check to see if it is touching the ring
+ int containerCenterX = mContainerLayoutParams.x + mContainer.getWidth() / 2;
+ int containerCenterY = mContainerLayoutParams.y + mContainer.getHeight() / 2;
+ int distanceFromCenterX = rawX - containerCenterX;
+ int distanceFromCenterY = rawY - containerCenterY;
+ int zoomRingRadius = mZoomRingWidth / 2 - ZOOM_RING_RADIUS_INSET;
+ if (distanceFromCenterX * distanceFromCenterX +
+ distanceFromCenterY * distanceFromCenterY <=
+ zoomRingRadius * zoomRingRadius) {
+ return mZoomRing;
+ }
+
+ // Check to see if it is touching any other clickable View.
+ // Reverse order so the child drawn on top gets first dibs.
+ int containerCoordsX = rawX - mContainerLayoutParams.x;
+ int containerCoordsY = rawY - mContainerLayoutParams.y;
+ Rect frame = mTempRect;
+ for (int i = mContainer.getChildCount() - 1; i >= 0; i--) {
+ View child = mContainer.getChildAt(i);
+ if (child == mZoomRing || child.getVisibility() != View.VISIBLE ||
+ !child.isClickable()) {
+ continue;
+ }
+
+ child.getHitRect(frame);
+ if (frame.contains(containerCoordsX, containerCoordsY)) {
+ return child;
+ }
+ }
+
+ return null;
}
/** Steals key events from the owner view. */
@@ -707,6 +852,8 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
case KeyEvent.KEYCODE_DPAD_DOWN:
// Keep the zoom alive a little longer
dismissZoomRingDelayed(ZOOM_CONTROLS_TIMEOUT);
+ // They started zooming, hide the thumb arrows
+ mZoomRing.setThumbArrowsVisible(false);
if (mCallback != null && event.getAction() == KeyEvent.ACTION_DOWN) {
mCallback.onSimpleZoom(keyCode == KeyEvent.KEYCODE_DPAD_UP);
@@ -734,9 +881,14 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
ensureZoomRingIsCentered();
}
+ /*
+ * This is static so Activities can call this instead of the Views
+ * (Activities usually do not have a reference to the ZoomRingController
+ * instance.)
+ */
/**
* Shows a "tutorial" (some text) to the user teaching her the new zoom
- * invocation method.
+ * invocation method. Must call from the main thread.
*
* It checks the global system setting to ensure this has not been seen
* before. Furthermore, if the application does not have privilege to write
@@ -757,20 +909,45 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
return;
}
+ if (sTutorialDialog != null && sTutorialDialog.isShowing()) {
+ sTutorialDialog.dismiss();
+ }
+
+ sTutorialDialog = new AlertDialog.Builder(context)
+ .setMessage(
+ com.android.internal.R.string.tutorial_double_tap_to_zoom_message_short)
+ .setIcon(0)
+ .create();
+
+ Window window = sTutorialDialog.getWindow();
+ window.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
+ window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND |
+ WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
+ window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
+ WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
+
+ sTutorialDialog.show();
+ sTutorialShowTime = SystemClock.elapsedRealtime();
+ }
+
+ public void finishZoomTutorial() {
+ if (sTutorialDialog == null) return;
+
+ sTutorialDialog.dismiss();
+ sTutorialDialog = null;
+
+ // Record that they have seen the tutorial
try {
- Settings.System.putInt(cr, SETTING_NAME_SHOWN_TOAST, 1);
+ Settings.System.putInt(mContext.getContentResolver(), SETTING_NAME_SHOWN_TOAST, 1);
} catch (SecurityException e) {
/*
* The app does not have permission to clear this global flag, make
* sure the user does not see the message when he comes back to this
* same app at least.
*/
+ SharedPreferences sp = mContext.getSharedPreferences("_zoom", Context.MODE_PRIVATE);
sp.edit().putInt(SETTING_NAME_SHOWN_TOAST, 1).commit();
}
-
- Toast.makeText(context,
- com.android.internal.R.string.tutorial_double_tap_to_zoom_message_short,
- Toast.LENGTH_LONG).show();
}
private class Panner implements Runnable {
@@ -861,12 +1038,14 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
}
public interface OnZoomListener {
- void onBeginDrag(float startAngle);
+ void onBeginDrag();
boolean onDragZoom(int deltaZoomLevel, int centerX, int centerY, float startAngle,
float curAngle);
- void onEndDrag(float endAngle);
+ void onEndDrag();
void onSimpleZoom(boolean deltaZoomLevel);
+ void onBeginPan();
boolean onPan(int deltaX, int deltaY);
+ void onEndPan();
void onCenter(int x, int y);
void onVisibilityChanged(boolean visible);
}
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index eb232c7ad03e1..b502a6c13977c 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -19,13 +19,11 @@ package com.android.internal.app;
import com.android.internal.os.BatteryStatsImpl;
interface IBatteryStats {
- BatteryStatsImpl getStatistics();
+ byte[] getStatistics();
void noteStartWakelock(int uid, String name, int type);
void noteStopWakelock(int uid, String name, int type);
- void noteStartSensor(int uid, String name, int sensor);
- void noteStopSensor(int uid, String name, int sensor);
- void noteRequestGpsOn(int uid);
- void noteRequestGpsOff(int uid);
+ void noteStartSensor(int uid, int sensor);
+ void noteStopSensor(int uid, int sensor);
void noteStartGps(int uid);
void noteStopGps(int uid);
void noteScreenOn();
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index cbb65dc43679a..558a122c73956 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -31,7 +31,6 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Map;
/**
@@ -39,7 +38,7 @@ import java.util.Map;
* battery life. All times are represented in microseconds except where indicated
* otherwise.
*/
-public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
+public final class BatteryStatsImpl extends BatteryStats {
private static final String TAG = "BatteryStatsImpl";
@@ -47,7 +46,7 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 15;
+ private static final int VERSION = 23;
private final File mFile;
private final File mBackupFile;
@@ -65,8 +64,13 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
final ArrayList mPartialTimers = new ArrayList();
final ArrayList mFullTimers = new ArrayList();
final ArrayList mWindowTimers = new ArrayList();
- final ArrayList mSensorTimers = new ArrayList();
+ final SparseArray> mSensorTimers
+ = new SparseArray>();
+ // These are the objects that will want to do something when the device
+ // is unplugged from power.
+ final ArrayList mUnpluggables = new ArrayList();
+
int mStartCount;
long mBatteryUptime;
@@ -90,6 +94,7 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
* in to power.
*/
boolean mOnBattery;
+ boolean mOnBatteryInternal;
long mTrackBatteryPastUptime;
long mTrackBatteryUptimeStart;
long mTrackBatteryPastRealtime;
@@ -98,8 +103,6 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
long mUnpluggedBatteryUptime;
long mUnpluggedBatteryRealtime;
- HashSet mGpsRequesters = new HashSet();
-
long mLastWriteTime = 0; // Milliseconds
// For debugging
@@ -107,87 +110,100 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
mFile = mBackupFile = null;
}
+ public static interface Unpluggable {
+ void unplug(long batteryUptime, long batteryRealtime);
+ void plug(long batteryUptime, long batteryRealtime);
+ }
+
/**
* State for keeping track of timing information.
*/
- public static final class Timer extends BatteryStats.Timer {
- ArrayList mTimerPool;
+ public static final class Timer extends BatteryStats.Timer implements Unpluggable {
+ final int mType;
+ final ArrayList mTimerPool;
- int mType;
int mNesting;
int mCount;
int mLoadedCount;
int mLastCount;
+ int mUnpluggedCount;
- // Times are in microseconds for better accuracy when dividing by the lock count
+ // Times are in microseconds for better accuracy when dividing by the
+ // lock count, and are in "battery realtime" units.
- long mTotalTime; // Add mUnpluggedTotalTime to get true value
+ long mTotalTime;
long mLoadedTotalTime;
long mLastTotalTime;
- long mStartTime;
long mUpdateTime;
/**
* The value of mTotalTime when unplug() was last called, initially 0.
*/
- long mTotalTimeAtLastUnplug;
+ long mUnpluggedTotalTime;
- /** Constructor used for unmarshalling only. */
- Timer() {}
-
- Timer(int type, ArrayList timerPool) {
+ Timer(int type, ArrayList timerPool,
+ ArrayList unpluggables, Parcel in) {
mType = type;
mTimerPool = timerPool;
- }
-
- public void writeToParcel(Parcel out) {
- out.writeInt(mType);
- out.writeInt(mNesting);
- out.writeInt(mCount);
- out.writeInt(mLoadedCount);
- out.writeInt(mLastCount);
- out.writeLong(mTotalTime);
- out.writeLong(mLoadedTotalTime);
- out.writeLong(mLastTotalTime);
- out.writeLong(mStartTime);
- out.writeLong(mUpdateTime);
- out.writeLong(mTotalTimeAtLastUnplug);
- }
-
- public void readFromParcel(Parcel in) {
- mType = in.readInt();
- mNesting = in.readInt();
mCount = in.readInt();
mLoadedCount = in.readInt();
mLastCount = in.readInt();
+ mUnpluggedCount = in.readInt();
mTotalTime = in.readLong();
mLoadedTotalTime = in.readLong();
mLastTotalTime = in.readLong();
- mStartTime = in.readLong();
mUpdateTime = in.readLong();
- mTotalTimeAtLastUnplug = in.readLong();
- }
-
- private void unplug() {
- mTotalTimeAtLastUnplug += mTotalTime;
- mTotalTime = 0;
+ mUnpluggedTotalTime = in.readLong();
+ unpluggables.add(this);
}
+ Timer(int type, ArrayList timerPool,
+ ArrayList unpluggables) {
+ mType = type;
+ mTimerPool = timerPool;
+ unpluggables.add(this);
+ }
+
+ public void writeToParcel(Parcel out, long batteryRealtime) {
+ out.writeInt(mCount);
+ out.writeInt(mLoadedCount);
+ out.writeInt(mLastCount);
+ out.writeInt(mUnpluggedCount);
+ out.writeLong(computeRunTimeLocked(batteryRealtime));
+ out.writeLong(mLoadedTotalTime);
+ out.writeLong(mLastTotalTime);
+ out.writeLong(mUpdateTime);
+ out.writeLong(mUnpluggedTotalTime);
+ }
+
+ public void unplug(long batteryUptime, long batteryRealtime) {
+ mUnpluggedTotalTime = computeRunTimeLocked(batteryRealtime);
+ mUnpluggedCount = mCount;
+ }
+
+ public void plug(long batteryUptime, long batteryRealtime) {
+ if (mNesting > 0) {
+ mTotalTime = computeRunTimeLocked(batteryRealtime);
+ mUpdateTime = batteryRealtime;
+ }
+ }
+
/**
* Writes a possibly null Timer to a Parcel.
*
* @param out the Parcel to be written to.
* @param timer a Timer, or null.
*/
- public static void writeTimerToParcel(Parcel out, Timer timer) {
+ public static void writeTimerToParcel(Parcel out, Timer timer,
+ long batteryRealtime) {
if (timer == null) {
out.writeInt(0); // indicates null
return;
}
out.writeInt(1); // indicates non-null
- timer.writeToParcel(out);
+ timer.writeToParcel(out, batteryRealtime);
}
@Override
@@ -197,10 +213,9 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
val = mLastTotalTime;
} else {
val = computeRunTimeLocked(now);
- if (which != STATS_UNPLUGGED) {
- val += mTotalTimeAtLastUnplug;
- }
- if ((which == STATS_CURRENT) || (which == STATS_UNPLUGGED)) {
+ if (which == STATS_UNPLUGGED) {
+ val -= mUnpluggedTotalTime;
+ } else if (which != STATS_TOTAL) {
val -= mLoadedTotalTime;
}
}
@@ -215,7 +230,9 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
val = mLastCount;
} else {
val = mCount;
- if ((which == STATS_CURRENT) || (which == STATS_UNPLUGGED)) {
+ if (which == STATS_UNPLUGGED) {
+ val -= mUnpluggedCount;
+ } else if (which != STATS_TOTAL) {
val -= mLoadedCount;
}
}
@@ -223,12 +240,23 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
return val;
}
+ public void logState() {
+ Log.i("foo", "mNesting=" + mNesting + " mCount=" + mCount
+ + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
+ + " mUnpluggedCount=" + mUnpluggedCount);
+ Log.i("foo", "mTotalTime=" + mTotalTime
+ + " mLoadedTotalTime=" + mLoadedTotalTime);
+ Log.i("foo", "mLastTotalTime=" + mLastTotalTime
+ + " mUpdateTime=" + mUpdateTime);
+ }
+
void startRunningLocked(BatteryStatsImpl stats) {
if (mNesting++ == 0) {
- mStartTime = mUpdateTime =
- stats.getBatteryUptimeLocked(SystemClock.elapsedRealtime() * 1000);
- // Accumulate time to all other active counters with the current value of mCount
- refreshTimersLocked(stats);
+ mUpdateTime = stats.getBatteryRealtimeLocked(
+ SystemClock.elapsedRealtime() * 1000);
+ // Accumulate time to all currently active timers before adding
+ // this new one to the pool.
+ refreshTimersLocked(stats, mTimerPool);
// Add this timer to the active pool
mTimerPool.add(this);
// Increment the count
@@ -242,38 +270,34 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
return;
}
if (--mNesting == 0) {
- // Accumulate time to all active counters with the current value of mCount
- refreshTimersLocked(stats);
+ // Accumulate time to all active counters, scaled by the total
+ // active in the pool, before taking this one out of the pool.
+ refreshTimersLocked(stats, mTimerPool);
// Remove this timer from the active pool
mTimerPool.remove(this);
- // Decrement the count
- mCount--;
}
}
// Update the total time for all other running Timers with the same type as this Timer
// due to a change in timer count
- private void refreshTimersLocked(BatteryStatsImpl stats) {
- for (Timer t : mTimerPool) {
- t.updateTimeLocked(stats);
+ private static void refreshTimersLocked(final BatteryStatsImpl stats,
+ final ArrayList pool) {
+ final long realtime = SystemClock.elapsedRealtime() * 1000;
+ final long batteryRealtime = stats.getBatteryRealtimeLocked(realtime);
+ final int N = pool.size();
+ for (int i=N-1; i>= 0; i--) {
+ final Timer t = pool.get(i);
+ long heldTime = batteryRealtime - t.mUpdateTime;
+ if (heldTime > 0) {
+ t.mTotalTime += heldTime / N;
+ }
+ t.mUpdateTime = batteryRealtime;
}
}
- /**
- * Update totalTime and reset updateTime
- * @param stats
- */
- private void updateTimeLocked(BatteryStatsImpl stats) {
- long realtime = SystemClock.elapsedRealtime() * 1000;
- long heldTime = stats.getBatteryUptimeLocked(realtime) - mUpdateTime;
- if (heldTime > 0) {
- mTotalTime += heldTime / mCount;
- }
- mUpdateTime = stats.getBatteryUptimeLocked(realtime);
- }
-
- private long computeRunTimeLocked(long curBatteryUptime) {
- return mTotalTime + (mNesting > 0 ? (curBatteryUptime - mUpdateTime) / mCount : 0);
+ private long computeRunTimeLocked(long curBatteryRealtime) {
+ return mTotalTime + (mNesting > 0
+ ? (curBatteryRealtime - mUpdateTime) / mTimerPool.size() : 0);
}
void writeSummaryFromParcelLocked(Parcel out, long curBatteryUptime) {
@@ -295,53 +319,41 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
}
}
- public void unplugTcpCounters() {
- final int NU = mUidStats.size();
- for (int iu = 0; iu < NU; iu++) {
+ public void doUnplug(long batteryUptime, long batteryRealtime) {
+ for (int iu = mUidStats.size() - 1; iu >= 0; iu--) {
Uid u = mUidStats.valueAt(iu);
- u.mTcpBytesReceivedAtLastUnplug = u.getTcpBytesReceived(STATS_TOTAL);
- u.mTcpBytesSentAtLastUnplug = u.getTcpBytesSent(STATS_TOTAL);
+ u.mStartedTcpBytesReceived = NetStat.getUidRxBytes(u.mUid);
+ u.mStartedTcpBytesSent = NetStat.getUidTxBytes(u.mUid);
+ u.mTcpBytesReceivedAtLastUnplug = u.mCurrentTcpBytesReceived;
+ u.mTcpBytesSentAtLastUnplug = u.mCurrentTcpBytesSent;
+ }
+ for (int i = mUnpluggables.size() - 1; i >= 0; i--) {
+ mUnpluggables.get(i).unplug(batteryUptime, batteryRealtime);
}
}
- public void unplugTimers() {
- ArrayList timers;
-
- timers = mPartialTimers;
- for (int i = timers.size() - 1; i >= 0; i--) {
- timers.get(i).unplug();
+ public void doPlug(long batteryUptime, long batteryRealtime) {
+ for (int iu = mUidStats.size() - 1; iu >= 0; iu--) {
+ Uid u = mUidStats.valueAt(iu);
+ if (u.mStartedTcpBytesReceived >= 0) {
+ u.mCurrentTcpBytesReceived = u.computeCurrentTcpBytesReceived();
+ u.mStartedTcpBytesReceived = -1;
+ }
+ if (u.mStartedTcpBytesSent >= 0) {
+ u.mCurrentTcpBytesSent = u.computeCurrentTcpBytesSent();
+ u.mStartedTcpBytesSent = -1;
+ }
}
- timers = mFullTimers;
- for (int i = timers.size() - 1; i >= 0; i--) {
- timers.get(i).unplug();
- }
- timers = mWindowTimers;
- for (int i = timers.size() - 1; i >= 0; i--) {
- timers.get(i).unplug();
- }
- timers = mSensorTimers;
- for (int i = timers.size() - 1; i >= 0; i--) {
- timers.get(i).unplug();
+ for (int i = mUnpluggables.size() - 1; i >= 0; i--) {
+ mUnpluggables.get(i).plug(batteryUptime, batteryRealtime);
}
}
public void noteStartGps(int uid) {
- mGpsRequesters.add(uid);
mUidStats.get(uid).noteStartGps();
}
public void noteStopGps(int uid) {
- mGpsRequesters.remove(uid);
- mUidStats.get(uid).noteStopGps();
- }
-
- public void noteRequestGpsOn(int uid) {
- mGpsRequesters.add(uid);
- mUidStats.get(uid).noteStartGps();
- }
-
- public void noteRequestGpsOff(int uid) {
- mGpsRequesters.remove(uid);
mUidStats.get(uid).noteStopGps();
}
@@ -349,7 +361,7 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
* When the device screen or battery state changes, update the appropriate "screen on time"
* counter.
*/
- private void updateScreenOnTime(boolean screenOn) {
+ private void updateScreenOnTimeLocked(boolean screenOn) {
if (!mScreenOn) {
Log.w(TAG, "updateScreenOnTime without mScreenOn, ignored");
return;
@@ -366,17 +378,17 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
}
}
- public void noteScreenOn() {
+ public void noteScreenOnLocked() {
mScreenOn = true;
mLastScreenOnTimeMillis = SystemClock.elapsedRealtime();
}
- public void noteScreenOff() {
+ public void noteScreenOffLocked() {
if (!mScreenOn) {
Log.w(TAG, "noteScreenOff without mScreenOn, ignored");
return;
}
- updateScreenOnTime(false);
+ updateScreenOnTimeLocked(false);
mScreenOn = false;
}
@@ -388,8 +400,11 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
return mPluggedScreenOnTimeMillis;
}
- @Override
- public SparseArray extends BatteryStats.Uid> getUidStats() {
+ @Override public boolean getIsOnBattery() {
+ return mOnBattery;
+ }
+
+ @Override public SparseArray extends BatteryStats.Uid> getUidStats() {
return mUidStats;
}
@@ -401,11 +416,16 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
final int mUid;
long mLoadedTcpBytesReceived;
long mLoadedTcpBytesSent;
+ long mCurrentTcpBytesReceived;
+ long mCurrentTcpBytesSent;
long mTcpBytesReceivedAtLastUnplug;
long mTcpBytesSentAtLastUnplug;
- private final byte[] mBuf = new byte[16];
-
+ // These are not saved/restored when parcelling, since we want
+ // to return from the parcel with a snapshot of the state.
+ long mStartedTcpBytesReceived = -1;
+ long mStartedTcpBytesSent = -1;
+
/**
* The statistics we have collected for this uid's wake locks.
*/
@@ -455,51 +475,56 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
}
public long getTcpBytesReceived(int which) {
- long current = NetStat.getUidRxBytes(mUid);
-
- if (which == STATS_CURRENT) {
- return current;
- } else if (which == STATS_LAST) {
+ if (which == STATS_LAST) {
return mLoadedTcpBytesReceived;
- } else if (which == STATS_UNPLUGGED) {
- return current - mTcpBytesReceivedAtLastUnplug;
- } else if (which == STATS_TOTAL) {
- return mLoadedTcpBytesReceived + current;
} else {
- throw new IllegalArgumentException("which = " + which);
+ long current = computeCurrentTcpBytesReceived();
+ if (which == STATS_UNPLUGGED) {
+ current -= mTcpBytesReceivedAtLastUnplug;
+ } else if (which == STATS_TOTAL) {
+ current += mLoadedTcpBytesReceived;
+ }
+ return current;
}
}
+ public long computeCurrentTcpBytesReceived() {
+ return mCurrentTcpBytesReceived + (mStartedTcpBytesReceived >= 0
+ ? (NetStat.getUidRxBytes(mUid) - mStartedTcpBytesReceived) : 0);
+ }
+
public long getTcpBytesSent(int which) {
- long current = NetStat.getUidTxBytes(mUid);
-
- if (which == STATS_CURRENT) {
- return current;
- } else if (which == STATS_LAST) {
+ if (which == STATS_LAST) {
return mLoadedTcpBytesSent;
- } else if (which == STATS_UNPLUGGED) {
- return current - mTcpBytesSentAtLastUnplug;
- } else if (which == STATS_TOTAL) {
- return mLoadedTcpBytesSent + current;
} else {
- throw new IllegalArgumentException("which = " + which);
+ long current = computeCurrentTcpBytesSent();
+ if (which == STATS_UNPLUGGED) {
+ current -= mTcpBytesSentAtLastUnplug;
+ } else if (which == STATS_TOTAL) {
+ current += mLoadedTcpBytesSent;
+ }
+ return current;
}
}
-
- void writeToParcelLocked(Parcel out) {
+
+ public long computeCurrentTcpBytesSent() {
+ return mCurrentTcpBytesSent + (mStartedTcpBytesSent >= 0
+ ? (NetStat.getUidTxBytes(mUid) - mStartedTcpBytesSent) : 0);
+ }
+
+ void writeToParcelLocked(Parcel out, long batteryRealtime) {
out.writeInt(mWakelockStats.size());
for (Map.Entry wakelockEntry : mWakelockStats.entrySet()) {
out.writeString(wakelockEntry.getKey());
Uid.Wakelock wakelock = wakelockEntry.getValue();
- wakelock.writeToParcelLocked(out);
+ wakelock.writeToParcelLocked(out, batteryRealtime);
}
out.writeInt(mSensorStats.size());
for (Map.Entry sensorEntry : mSensorStats.entrySet()) {
out.writeInt(sensorEntry.getKey());
- out.writeString(sensorEntry.getValue().getName());
Uid.Sensor sensor = sensorEntry.getValue();
- sensor.writeToParcelLocked(out);
+ sensor.writeToParcelLocked(out, batteryRealtime);
}
out.writeInt(mProcessStats.size());
@@ -518,17 +543,19 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
out.writeLong(mLoadedTcpBytesReceived);
out.writeLong(mLoadedTcpBytesSent);
+ out.writeLong(computeCurrentTcpBytesReceived());
+ out.writeLong(computeCurrentTcpBytesSent());
out.writeLong(mTcpBytesReceivedAtLastUnplug);
out.writeLong(mTcpBytesSentAtLastUnplug);
}
- void readFromParcelLocked(Parcel in) {
+ void readFromParcelLocked(ArrayList unpluggables, Parcel in) {
int numWakelocks = in.readInt();
mWakelockStats.clear();
for (int j = 0; j < numWakelocks; j++) {
String wakelockName = in.readString();
Uid.Wakelock wakelock = new Wakelock();
- wakelock.readFromParcelLocked(in);
+ wakelock.readFromParcelLocked(unpluggables, in);
mWakelockStats.put(wakelockName, wakelock);
}
@@ -536,9 +563,8 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
mSensorStats.clear();
for (int k = 0; k < numSensors; k++) {
int sensorNumber = in.readInt();
- String name = in.readString();
- Uid.Sensor sensor = new Sensor(name);
- sensor.readFromParcelLocked(in);
+ Uid.Sensor sensor = new Sensor(sensorNumber);
+ sensor.readFromParcelLocked(mUnpluggables, in);
mSensorStats.put(sensorNumber, sensor);
}
@@ -562,6 +588,8 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
mLoadedTcpBytesReceived = in.readLong();
mLoadedTcpBytesSent = in.readLong();
+ mCurrentTcpBytesReceived = in.readLong();
+ mCurrentTcpBytesSent = in.readLong();
mTcpBytesReceivedAtLastUnplug = in.readLong();
mTcpBytesSentAtLastUnplug = in.readLong();
}
@@ -573,17 +601,17 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
/**
* How long (in ms) this uid has been keeping the device partially awake.
*/
- Timer wakeTimePartial;
+ Timer mTimerPartial;
/**
* How long (in ms) this uid has been keeping the device fully awake.
*/
- Timer wakeTimeFull;
+ Timer mTimerFull;
/**
* How long (in ms) this uid has had a window keeping the device awake.
*/
- Timer wakeTimeWindow;
+ Timer mTimerWindow;
/**
* Reads a possibly null Timer from a Parcel. The timer is associated with the
@@ -592,103 +620,85 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
* @param in the Parcel to be read from.
* return a new Timer, or null.
*/
- private Timer readTimerFromParcel(Parcel in) {
+ private Timer readTimerFromParcel(int type, ArrayList pool,
+ ArrayList unpluggables, Parcel in) {
if (in.readInt() == 0) {
return null;
}
- Timer timer = new Timer();
- timer.readFromParcel(in);
- // Set the timer pool for the timer according to its type
- switch (timer.mType) {
- case WAKE_TYPE_PARTIAL:
- timer.mTimerPool = mPartialTimers;
- break;
- case WAKE_TYPE_FULL:
- timer.mTimerPool = mFullTimers;
- break;
- case WAKE_TYPE_WINDOW:
- timer.mTimerPool = mWindowTimers;
- break;
- }
- // If the timer is active, add it to the pool
- if (timer.mNesting > 0) {
- timer.mTimerPool.add(timer);
- }
- return timer;
+ return new Timer(type, pool, unpluggables, in);
}
- void readFromParcelLocked(Parcel in) {
- wakeTimePartial = readTimerFromParcel(in);
- wakeTimeFull = readTimerFromParcel(in);
- wakeTimeWindow = readTimerFromParcel(in);
+ void readFromParcelLocked(ArrayList unpluggables, Parcel in) {
+ mTimerPartial = readTimerFromParcel(WAKE_TYPE_PARTIAL,
+ mPartialTimers, unpluggables, in);
+ mTimerFull = readTimerFromParcel(WAKE_TYPE_FULL,
+ mFullTimers, unpluggables, in);
+ mTimerWindow = readTimerFromParcel(WAKE_TYPE_WINDOW,
+ mWindowTimers, unpluggables, in);
}
- void writeToParcelLocked(Parcel out) {
- Timer.writeTimerToParcel(out, wakeTimePartial);
- Timer.writeTimerToParcel(out, wakeTimeFull);
- Timer.writeTimerToParcel(out, wakeTimeWindow);
+ void writeToParcelLocked(Parcel out, long batteryRealtime) {
+ Timer.writeTimerToParcel(out, mTimerPartial, batteryRealtime);
+ Timer.writeTimerToParcel(out, mTimerFull, batteryRealtime);
+ Timer.writeTimerToParcel(out, mTimerWindow, batteryRealtime);
}
@Override
public Timer getWakeTime(int type) {
switch (type) {
- case WAKE_TYPE_FULL: return wakeTimeFull;
- case WAKE_TYPE_PARTIAL: return wakeTimePartial;
- case WAKE_TYPE_WINDOW: return wakeTimeWindow;
+ case WAKE_TYPE_FULL: return mTimerFull;
+ case WAKE_TYPE_PARTIAL: return mTimerPartial;
+ case WAKE_TYPE_WINDOW: return mTimerWindow;
default: throw new IllegalArgumentException("type = " + type);
}
}
}
public final class Sensor extends BatteryStats.Uid.Sensor {
- static final int GPS = -10000; // Treat GPS as a sensor
- final String mName;
- Timer sensorTime;
+ final int mHandle;
+ Timer mTimer;
- public Sensor(String name) {
- mName = name;
+ public Sensor(int handle) {
+ mHandle = handle;
}
- private Timer readTimerFromParcel(Parcel in) {
+ private Timer readTimerFromParcel(ArrayList unpluggables,
+ Parcel in) {
if (in.readInt() == 0) {
return null;
}
- Timer timer = new Timer();
- timer.readFromParcel(in);
- // Set the timer pool for the timer
- timer.mTimerPool = mSensorTimers;
-
- // If the timer is active, add it to the pool
- if (timer.mNesting > 0) {
- timer.mTimerPool.add(timer);
+ ArrayList pool = mSensorTimers.get(mHandle);
+ if (pool == null) {
+ pool = new ArrayList();
+ mSensorTimers.put(mHandle, pool);
}
- return timer;
+ return new Timer(0, pool, unpluggables, in);
}
- void readFromParcelLocked(Parcel in) {
- sensorTime = readTimerFromParcel(in);
+ void readFromParcelLocked(ArrayList unpluggables, Parcel in) {
+ mTimer = readTimerFromParcel(unpluggables, in);
}
- void writeToParcelLocked(Parcel out) {
- Timer.writeTimerToParcel(out, sensorTime);
+ void writeToParcelLocked(Parcel out, long batteryRealtime) {
+ Timer.writeTimerToParcel(out, mTimer, batteryRealtime);
}
@Override
public Timer getSensorTime() {
- return sensorTime;
+ return mTimer;
}
- public String getName() {
- return mName;
+ public int getHandle() {
+ return mHandle;
}
}
/**
* The statistics associated with a particular process.
*/
- public final class Proc extends BatteryStats.Uid.Proc {
+ public final class Proc extends BatteryStats.Uid.Proc implements Unpluggable {
/**
* Total time (in 1/100 sec) spent executing in user code.
*/
@@ -734,6 +744,34 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
*/
int mLastStarts;
+ /**
+ * The amount of user time when last unplugged.
+ */
+ long mUnpluggedUserTime;
+
+ /**
+ * The amount of system time when last unplugged.
+ */
+ long mUnpluggedSystemTime;
+
+ /**
+ * The number of times the process has started before unplugged.
+ */
+ int mUnpluggedStarts;
+
+ Proc() {
+ mUnpluggables.add(this);
+ }
+
+ public void unplug(long batteryUptime, long batteryRealtime) {
+ mUnpluggedUserTime = mUserTime;
+ mUnpluggedSystemTime = mSystemTime;
+ mUnpluggedStarts = mStarts;
+ }
+
+ public void plug(long batteryUptime, long batteryRealtime) {
+ }
+
void writeToParcelLocked(Parcel out) {
out.writeLong(mUserTime);
out.writeLong(mSystemTime);
@@ -744,6 +782,9 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
out.writeLong(mLastUserTime);
out.writeLong(mLastSystemTime);
out.writeInt(mLastStarts);
+ out.writeLong(mUnpluggedUserTime);
+ out.writeLong(mUnpluggedSystemTime);
+ out.writeInt(mUnpluggedStarts);
}
void readFromParcelLocked(Parcel in) {
@@ -756,6 +797,9 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
mLastUserTime = in.readLong();
mLastSystemTime = in.readLong();
mLastStarts = in.readInt();
+ mUnpluggedUserTime = in.readLong();
+ mUnpluggedSystemTime = in.readLong();
+ mUnpluggedStarts = in.readInt();
}
public BatteryStatsImpl getBatteryStats() {
@@ -780,6 +824,8 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
val = mUserTime;
if (which == STATS_CURRENT) {
val -= mLoadedUserTime;
+ } else if (which == STATS_UNPLUGGED) {
+ val -= mUnpluggedUserTime;
}
}
return val;
@@ -794,6 +840,8 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
val = mSystemTime;
if (which == STATS_CURRENT) {
val -= mLoadedSystemTime;
+ } else if (which == STATS_UNPLUGGED) {
+ val -= mUnpluggedSystemTime;
}
}
return val;
@@ -808,6 +856,8 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
val = mStarts;
if (which == STATS_CURRENT) {
val -= mLoadedStarts;
+ } else if (which == STATS_UNPLUGGED) {
+ val -= mUnpluggedStarts;
}
}
return val;
@@ -817,7 +867,7 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
/**
* The statistics associated with a particular package.
*/
- public final class Pkg extends BatteryStats.Uid.Pkg {
+ public final class Pkg extends BatteryStats.Uid.Pkg implements Unpluggable {
/**
* Number of times this package has done something that could wake up the
* device from sleep.
@@ -836,15 +886,33 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
*/
int mLastWakeups;
+ /**
+ * Number of things that could wake up the device as of the
+ * last run.
+ */
+ int mUnpluggedWakeups;
+
/**
* The statics we have collected for this package's services.
*/
final HashMap mServiceStats = new HashMap();
+ Pkg() {
+ mUnpluggables.add(this);
+ }
+
+ public void unplug(long batteryUptime, long batteryRealtime) {
+ mUnpluggedWakeups = mWakeups;
+ }
+
+ public void plug(long batteryUptime, long batteryRealtime) {
+ }
+
void readFromParcelLocked(Parcel in) {
mWakeups = in.readInt();
mLoadedWakeups = in.readInt();
mLastWakeups = in.readInt();
+ mUnpluggedWakeups = in.readInt();
int numServs = in.readInt();
mServiceStats.clear();
@@ -861,6 +929,7 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
out.writeInt(mWakeups);
out.writeInt(mLoadedWakeups);
out.writeInt(mLastWakeups);
+ out.writeInt(mUnpluggedWakeups);
out.writeInt(mServiceStats.size());
for (Map.Entry servEntry : mServiceStats.entrySet()) {
@@ -885,6 +954,8 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
val = mWakeups;
if (which == STATS_CURRENT) {
val -= mLoadedWakeups;
+ } else if (which == STATS_UNPLUGGED) {
+ val -= mUnpluggedWakeups;
}
}
@@ -894,9 +965,9 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
/**
* The statistics associated with a particular service.
*/
- public final class Serv extends BatteryStats.Uid.Pkg.Serv {
+ public final class Serv extends BatteryStats.Uid.Pkg.Serv implements Unpluggable {
/**
- * Total time (ms) the service has been left started.
+ * Total time (ms in battery uptime) the service has been left started.
*/
long mStartTime;
@@ -917,13 +988,13 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
int mStarts;
/**
- * Total time (ms) the service has been left launched.
+ * Total time (ms in battery uptime) the service has been left launched.
*/
long mLaunchedTime;
/**
* If service has been launched and not yet exited, this is
- * when it was launched.
+ * when it was launched (ms in battery uptime).
*/
long mLaunchedSince;
@@ -938,7 +1009,8 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
int mLaunches;
/**
- * The amount of time spent started loaded from a previous save.
+ * The amount of time spent started loaded from a previous save
+ * (ms in battery uptime).
*/
long mLoadedStartTime;
@@ -953,7 +1025,8 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
int mLoadedLaunches;
/**
- * The amount of time spent started as of the last run.
+ * The amount of time spent started as of the last run (ms
+ * in battery uptime).
*/
long mLastStartTime;
@@ -967,6 +1040,35 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
*/
int mLastLaunches;
+ /**
+ * The amount of time spent started when last unplugged (ms
+ * in battery uptime).
+ */
+ long mUnpluggedStartTime;
+
+ /**
+ * The number of starts when last unplugged.
+ */
+ int mUnpluggedStarts;
+
+ /**
+ * The number of launches when last unplugged.
+ */
+ int mUnpluggedLaunches;
+
+ Serv() {
+ mUnpluggables.add(this);
+ }
+
+ public void unplug(long batteryUptime, long batteryRealtime) {
+ mUnpluggedStartTime = getStartTimeToNowLocked(batteryUptime);
+ mUnpluggedStarts = mStarts;
+ mUnpluggedLaunches = mLaunches;
+ }
+
+ public void plug(long batteryUptime, long batteryRealtime) {
+ }
+
void readFromParcelLocked(Parcel in) {
mStartTime = in.readLong();
mRunningSince = in.readLong();
@@ -982,6 +1084,9 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
mLastStartTime = in.readLong();
mLastStarts = in.readInt();
mLastLaunches = in.readInt();
+ mUnpluggedStartTime = in.readLong();
+ mUnpluggedStarts = in.readInt();
+ mUnpluggedLaunches = in.readInt();
}
void writeToParcelLocked(Parcel out) {
@@ -999,6 +1104,9 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
out.writeLong(mLastStartTime);
out.writeInt(mLastStarts);
out.writeInt(mLastLaunches);
+ out.writeLong(mUnpluggedStartTime);
+ out.writeInt(mUnpluggedStarts);
+ out.writeInt(mUnpluggedLaunches);
}
long getLaunchTimeToNowLocked(long batteryUptime) {
@@ -1065,6 +1173,8 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
val = mLaunches;
if (which == STATS_CURRENT) {
val -= mLoadedLaunches;
+ } else if (which == STATS_UNPLUGGED) {
+ val -= mUnpluggedLaunches;
}
}
@@ -1080,6 +1190,8 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
val = getStartTimeToNowLocked(now);
if (which == STATS_CURRENT) {
val -= mLoadedStartTime;
+ } else if (which == STATS_UNPLUGGED) {
+ val -= mUnpluggedStartTime;
}
}
@@ -1095,6 +1207,8 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
val = mStarts;
if (which == STATS_CURRENT) {
val -= mLoadedStarts;
+ } else if (which == STATS_UNPLUGGED) {
+ val -= mUnpluggedStarts;
}
}
@@ -1167,24 +1281,24 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
Timer t = null;
switch (type) {
case WAKE_TYPE_PARTIAL:
- t = wl.wakeTimePartial;
+ t = wl.mTimerPartial;
if (t == null) {
- t = new Timer(WAKE_TYPE_PARTIAL, mPartialTimers);
- wl.wakeTimePartial = t;
+ t = new Timer(WAKE_TYPE_PARTIAL, mPartialTimers, mUnpluggables);
+ wl.mTimerPartial = t;
}
return t;
case WAKE_TYPE_FULL:
- t = wl.wakeTimeFull;
+ t = wl.mTimerFull;
if (t == null) {
- t = new Timer(WAKE_TYPE_FULL, mFullTimers);
- wl.wakeTimeFull = t;
+ t = new Timer(WAKE_TYPE_FULL, mFullTimers, mUnpluggables);
+ wl.mTimerFull = t;
}
return t;
case WAKE_TYPE_WINDOW:
- t = wl.wakeTimeWindow;
+ t = wl.mTimerWindow;
if (t == null) {
- t = new Timer(WAKE_TYPE_WINDOW, mWindowTimers);
- wl.wakeTimeWindow = t;
+ t = new Timer(WAKE_TYPE_WINDOW, mWindowTimers, mUnpluggables);
+ wl.mTimerWindow = t;
}
return t;
default:
@@ -1192,21 +1306,26 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
}
}
- public Timer getSensorTimerLocked(String name, int sensor, boolean create) {
- Integer sId = Integer.valueOf(sensor);
- Sensor se = mSensorStats.get(sId);
+ public Timer getSensorTimerLocked(int sensor, boolean create) {
+ Sensor se = mSensorStats.get(sensor);
if (se == null) {
if (!create) {
return null;
}
- se = new Sensor(name);
- mSensorStats.put(sId, se);
+ se = new Sensor(sensor);
+ mSensorStats.put(sensor, se);
}
- Timer t = se.sensorTime;
- if (t == null) {
- t = new Timer(BatteryStats.SENSOR, mSensorTimers);
- se.sensorTime = t;
+ Timer t = se.mTimer;
+ if (t != null) {
+ return t;
}
+ ArrayList timers = mSensorTimers.get(sensor);
+ if (timers == null) {
+ timers = new ArrayList();
+ mSensorTimers.put(sensor, timers);
+ }
+ t = new Timer(BatteryStats.SENSOR, timers, mUnpluggables);
+ se.mTimer = t;
return t;
}
@@ -1224,30 +1343,30 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
}
}
- public void noteStartSensor(String name, int sensor) {
- Timer t = getSensorTimerLocked(name, sensor, true);
+ public void noteStartSensor(int sensor) {
+ Timer t = getSensorTimerLocked(sensor, true);
if (t != null) {
t.startRunningLocked(BatteryStatsImpl.this);
}
}
- public void noteStopSensor(String name, int sensor) {
+ public void noteStopSensor(int sensor) {
// Don't create a timer if one doesn't already exist
- Timer t = getSensorTimerLocked(name, sensor, false);
+ Timer t = getSensorTimerLocked(sensor, false);
if (t != null) {
t.stopRunningLocked(BatteryStatsImpl.this);
}
}
public void noteStartGps() {
- Timer t = getSensorTimerLocked("GPS", Sensor.GPS, true);
+ Timer t = getSensorTimerLocked(Sensor.GPS, true);
if (t != null) {
t.startRunningLocked(BatteryStatsImpl.this);
}
}
public void noteStopGps() {
- Timer t = getSensorTimerLocked("GPS", Sensor.GPS, false);
+ Timer t = getSensorTimerLocked(Sensor.GPS, false);
if (t != null) {
t.stopRunningLocked(BatteryStatsImpl.this);
}
@@ -1262,12 +1381,11 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
mFile = new File(filename);
mBackupFile = new File(filename + ".bak");
mStartCount++;
- mOnBattery = true;
+ mOnBattery = mOnBatteryInternal = false;
mTrackBatteryPastUptime = 0;
mTrackBatteryPastRealtime = 0;
mUptimeStart = mTrackBatteryUptimeStart = SystemClock.uptimeMillis() * 1000;
mRealtimeStart = mTrackBatteryRealtimeStart = SystemClock.elapsedRealtime() * 1000;
-
mUnpluggedBatteryUptime = getBatteryUptimeLocked(mUptimeStart);
mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(mRealtimeStart);
}
@@ -1290,25 +1408,25 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
synchronized(this) {
if (mOnBattery != onBattery) {
if (mScreenOn) {
- updateScreenOnTime(true);
+ updateScreenOnTimeLocked(true);
}
+ mOnBattery = mOnBatteryInternal = onBattery;
+
long uptime = SystemClock.uptimeMillis() * 1000;
long mSecRealtime = SystemClock.elapsedRealtime();
long realtime = mSecRealtime * 1000;
if (onBattery) {
- mTrackBatteryUptimeStart = getBatteryUptime(uptime);
- mTrackBatteryRealtimeStart = getBatteryRealtime(realtime);
- unplugTcpCounters();
- unplugTimers();
-
- mUnpluggedBatteryUptime = getBatteryUptime(uptime);
- mUnpluggedBatteryRealtime = getBatteryRealtime(realtime);
+ mTrackBatteryUptimeStart = uptime;
+ mTrackBatteryRealtimeStart = realtime;
+ mUnpluggedBatteryUptime = getBatteryUptimeLocked(uptime);
+ mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(realtime);
+ doUnplug(mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime);
} else {
mTrackBatteryPastUptime += uptime - mTrackBatteryUptimeStart;
mTrackBatteryPastRealtime += realtime - mTrackBatteryRealtimeStart;
+ doPlug(mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime);
}
- mOnBattery = onBattery;
if ((mLastWriteTime + (60 * 1000)) < mSecRealtime) {
if (mFile != null) {
writeLocked();
@@ -1359,7 +1477,7 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
case STATS_CURRENT:
return uptime;
case STATS_UNPLUGGED:
- return uptime - mUnpluggedBatteryUptime;
+ return getBatteryUptimeLocked(curTime) - mUnpluggedBatteryUptime;
}
return 0;
}
@@ -1381,7 +1499,7 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
long getBatteryUptimeLocked(long curTime) {
long time = mTrackBatteryPastUptime;
- if (mOnBattery) {
+ if (mOnBatteryInternal) {
time += curTime - mTrackBatteryUptimeStart;
}
return time;
@@ -1398,7 +1516,7 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
long getBatteryRealtimeLocked(long curTime) {
long time = mTrackBatteryPastRealtime;
- if (mOnBattery) {
+ if (mOnBatteryInternal) {
time += curTime - mTrackBatteryRealtimeStart;
}
return time;
@@ -1554,8 +1672,8 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
private void readSummaryFromParcel(Parcel in) {
final int version = in.readInt();
if (version != VERSION) {
- Log.e("BatteryStats", "readFromParcel: version got " + version
- + ", expected " + VERSION);
+ Log.w("BatteryStats", "readFromParcel: version got " + version
+ + ", expected " + VERSION + "; erasing old stats");
return;
}
@@ -1570,11 +1688,9 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
mLastRealtime = in.readLong();
mStartCount++;
- if (version >= 14) {
- mBatteryScreenOnTimeMillis = in.readLong();
- mPluggedScreenOnTimeMillis = in.readLong();
- mScreenOn = false;
- }
+ mBatteryScreenOnTimeMillis = in.readLong();
+ mPluggedScreenOnTimeMillis = in.readLong();
+ mScreenOn = false;
final int NU = in.readInt();
for (int iu = 0; iu < NU; iu++) {
@@ -1596,22 +1712,16 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
}
}
- if (version >= 12) {
- int NSE = in.readInt();
- for (int is = 0; is < NSE; is++) {
- int seNumber = in.readInt();
- String seName = "";
- if (version >= 14) {
- seName = in.readString();
- }
- if (in.readInt() != 0) {
- u.getSensorTimerLocked(seName, seNumber, true)
- .readSummaryFromParcelLocked(in);
- }
+ int NP = in.readInt();
+ for (int is = 0; is < NP; is++) {
+ int seNumber = in.readInt();
+ if (in.readInt() != 0) {
+ u.getSensorTimerLocked(seNumber, true)
+ .readSummaryFromParcelLocked(in);
}
}
- int NP = in.readInt();
+ NP = in.readInt();
for (int ip = 0; ip < NP; ip++) {
String procName = in.readString();
Uid.Proc p = u.getProcessStatsLocked(procName);
@@ -1642,10 +1752,8 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
}
}
- if (version >= 14) {
- u.mLoadedTcpBytesReceived = in.readLong();
- u.mLoadedTcpBytesSent = in.readLong();
- }
+ u.mLoadedTcpBytesReceived = in.readLong();
+ u.mLoadedTcpBytesSent = in.readLong();
}
}
@@ -1685,24 +1793,24 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
out.writeInt(NW);
if (NW > 0) {
for (Map.Entry ent
- : u.mWakelockStats.entrySet()) {
+ : u.mWakelockStats.entrySet()) {
out.writeString(ent.getKey());
Uid.Wakelock wl = ent.getValue();
- if (wl.wakeTimeFull != null) {
+ if (wl.mTimerFull != null) {
out.writeInt(1);
- wl.wakeTimeFull.writeSummaryFromParcelLocked(out, NOW);
+ wl.mTimerFull.writeSummaryFromParcelLocked(out, NOW);
} else {
out.writeInt(0);
}
- if (wl.wakeTimePartial != null) {
+ if (wl.mTimerPartial != null) {
out.writeInt(1);
- wl.wakeTimePartial.writeSummaryFromParcelLocked(out, NOW);
+ wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOW);
} else {
out.writeInt(0);
}
- if (wl.wakeTimeWindow != null) {
+ if (wl.mTimerWindow != null) {
out.writeInt(1);
- wl.wakeTimeWindow.writeSummaryFromParcelLocked(out, NOW);
+ wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOW);
} else {
out.writeInt(0);
}
@@ -1713,13 +1821,12 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
out.writeInt(NSE);
if (NSE > 0) {
for (Map.Entry ent
- : u.mSensorStats.entrySet()) {
+ : u.mSensorStats.entrySet()) {
out.writeInt(ent.getKey());
Uid.Sensor se = ent.getValue();
- out.writeString(se.getName());
- if (se.sensorTime != null) {
+ if (se.mTimer != null) {
out.writeInt(1);
- se.sensorTime.writeSummaryFromParcelLocked(out, NOW);
+ se.mTimer.writeSummaryFromParcelLocked(out, NOW);
} else {
out.writeInt(0);
}
@@ -1800,6 +1907,7 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
mRealtimeStart = in.readLong();
mLastRealtime = in.readLong();
mOnBattery = in.readInt() != 0;
+ mOnBatteryInternal = false; // we are no longer really running.
mTrackBatteryPastUptime = in.readLong();
mTrackBatteryUptimeStart = in.readLong();
mTrackBatteryPastRealtime = in.readLong();
@@ -1815,7 +1923,7 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
for (int i = 0; i < numUids; i++) {
int uid = in.readInt();
Uid u = new Uid(uid);
- u.readFromParcelLocked(in);
+ u.readFromParcelLocked(mUnpluggables, in);
mUidStats.append(uid, u);
}
}
@@ -1826,6 +1934,11 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
@SuppressWarnings("unused")
void writeToParcelLocked(Parcel out, int flags) {
+ final long uSecUptime = SystemClock.uptimeMillis() * 1000;
+ final long uSecRealtime = SystemClock.elapsedRealtime() * 1000;
+ final long batteryUptime = getBatteryUptimeLocked(uSecUptime);
+ final long batteryRealtime = getBatteryRealtimeLocked(uSecRealtime);
+
out.writeInt(MAGIC);
out.writeInt(mStartCount);
out.writeLong(mBatteryUptime);
@@ -1853,7 +1966,7 @@ public final class BatteryStatsImpl extends BatteryStats implements Parcelable {
out.writeInt(mUidStats.keyAt(i));
Uid uid = mUidStats.valueAt(i);
- uid.writeToParcelLocked(out);
+ uid.writeToParcelLocked(out, batteryRealtime);
}
}
diff --git a/core/java/com/android/internal/os/HandlerThread.java b/core/java/com/android/internal/os/HandlerThread.java
deleted file mode 100644
index 1de6bfd407b3b..0000000000000
--- a/core/java/com/android/internal/os/HandlerThread.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.os.Handler;
-import android.os.HandlerInterface;
-import android.os.Looper;
-
-/**
- * Handy class for starting a new thread containing a Handler
- * @hide
- * @deprecated
- */
-public class HandlerThread extends Thread
-{
- Runnable mSetup;
- HandlerInterface mhi;
- Handler mh;
- Throwable mtr;
- final Object mMonitor = new Object();
-
- public
- HandlerThread(HandlerInterface h, Runnable setup, String name)
- {
- super(name);
-
- mhi = h;
- mSetup = setup;
-
- synchronized (mMonitor) {
- start();
- while (mh == null && mtr == null) {
- try {
- mMonitor.wait();
- } catch (InterruptedException ex) {
- }
- }
- }
-
- if (mtr != null) {
- throw new RuntimeException("exception while starting", mtr);
- }
- }
-
- @Override
- public void
- run()
- {
- synchronized(mMonitor) {
- try {
- Looper.prepare();
- mh = new HandlerHelper (mhi);
-
- if (mSetup != null) {
- mSetup.run();
- mSetup = null;
- }
- } catch (RuntimeException exc) {
- mtr = exc;
- }
-
- mMonitor.notify();
- }
-
- if (mtr == null) {
- Looper.loop();
- }
- }
-
- public Handler
- getHandler()
- {
- return mh;
- }
-
-}
-
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index ac72a20e64839..4f98cee688e13 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -1,7 +1,5 @@
package com.android.internal.view;
-import com.android.internal.view.IInputContext;
-
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@@ -324,7 +322,7 @@ public class IInputConnectionWrapper extends IInputContext.Stub {
Log.w(TAG, "showStatusIcon on inactive InputConnection");
return;
}
- ic.reportFullscreenMode(msg.arg1 != 1);
+ ic.reportFullscreenMode(msg.arg1 == 1);
return;
}
case DO_PERFORM_PRIVATE_COMMAND: {
diff --git a/core/java/com/android/internal/widget/EditableInputConnection.java b/core/java/com/android/internal/widget/EditableInputConnection.java
index 648d944cc7b86..44cf0ed1fcd30 100644
--- a/core/java/com/android/internal/widget/EditableInputConnection.java
+++ b/core/java/com/android/internal/widget/EditableInputConnection.java
@@ -96,4 +96,21 @@ public class EditableInputConnection extends BaseInputConnection {
mTextView.onPrivateIMECommand(action, data);
return true;
}
+
+ @Override
+ public boolean commitText(CharSequence text, int newCursorPosition) {
+ if (mTextView == null) {
+ return super.commitText(text, newCursorPosition);
+ }
+
+ CharSequence errorBefore = mTextView.getError();
+ boolean success = super.commitText(text, newCursorPosition);
+ CharSequence errorAfter = mTextView.getError();
+
+ if (errorAfter != null && errorBefore == errorAfter) {
+ mTextView.setError(null, null);
+ }
+
+ return success;
+ }
}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index ed1cd58c73850..c8b3ad48ec454 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -77,11 +77,10 @@ public class LockPatternUtils {
public static final int MIN_PATTERN_REGISTER_FAIL = 3;
private final static String LOCKOUT_PERMANENT_KEY = "lockscreen.lockedoutpermanently";
+ private final static String LOCKOUT_ATTEMPT_DEADLINE = "lockscreen.lockoutattemptdeadline";
private final ContentResolver mContentResolver;
- private long mLockoutDeadline = 0;
-
private static String sLockPatternFilename;
/**
@@ -270,12 +269,14 @@ public class LockPatternUtils {
}
/**
- * Store the lockout deadline, meaning the user can't attempt his/her unlock
- * pattern until the deadline has passed. Does not persist across reboots.
- * @param deadline The elapsed real time in millis in future.
+ * Set and store the lockout deadline, meaning the user can't attempt his/her unlock
+ * pattern until the deadline has passed.
+ * @return the chosen deadline.
*/
- public void setLockoutAttemptDeadline(long deadline) {
- mLockoutDeadline = deadline;
+ public long setLockoutAttemptDeadline() {
+ final long deadline = SystemClock.elapsedRealtime() + FAILED_ATTEMPT_TIMEOUT_MS;
+ setLong(LOCKOUT_ATTEMPT_DEADLINE, deadline);
+ return deadline;
}
/**
@@ -284,7 +285,12 @@ public class LockPatternUtils {
* enter a pattern.
*/
public long getLockoutAttemptDeadline() {
- return (mLockoutDeadline <= SystemClock.elapsedRealtime()) ? 0 : mLockoutDeadline;
+ final long deadline = getLong(LOCKOUT_ATTEMPT_DEADLINE, 0L);
+ final long now = SystemClock.elapsedRealtime();
+ if (deadline < now || deadline > (now + FAILED_ATTEMPT_TIMEOUT_MS)) {
+ return 0L;
+ }
+ return deadline;
}
/**
@@ -341,5 +347,13 @@ public class LockPatternUtils {
enabled ? 1 : 0);
}
+ private long getLong(String systemSettingKey, long def) {
+ return android.provider.Settings.System.getLong(mContentResolver, systemSettingKey, def);
+ }
+
+ private void setLong(String systemSettingKey, long value) {
+ android.provider.Settings.System.putLong(mContentResolver, systemSettingKey, value);
+ }
+
}
diff --git a/core/java/com/android/internal/widget/TextProgressBar.java b/core/java/com/android/internal/widget/TextProgressBar.java
new file mode 100644
index 0000000000000..d068865634723
--- /dev/null
+++ b/core/java/com/android/internal/widget/TextProgressBar.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget;
+
+import android.content.Context;
+import android.os.SystemClock;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Chronometer;
+import android.widget.Chronometer.OnChronometerTickListener;
+import android.widget.ProgressBar;
+import android.widget.RelativeLayout;
+import android.widget.RemoteViews.RemoteView;
+
+/**
+ * Container that links together a {@link ProgressBar} and {@link Chronometer}
+ * as children. It subscribes to {@link Chronometer#OnChronometerTickListener}
+ * and updates the {@link ProgressBar} based on a preset finishing time.
+ *
+ * This widget expects to contain two children with specific ids
+ * {@link android.R.id.progress} and {@link android.R.id.text1}.
+ *
+ * If the {@link Chronometer} {@link android.R.attr#layout_width} is
+ * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT}, then the
+ * {@link android.R.attr#gravity} will be used to automatically move it with
+ * respect to the {@link ProgressBar} position. For example, if
+ * {@link android.view.Gravity#LEFT} then the {@link Chronometer} will be placed
+ * just ahead of the leading edge of the {@link ProgressBar} position.
+ */
+@RemoteView
+public class TextProgressBar extends RelativeLayout implements OnChronometerTickListener {
+ public static final String TAG = "TextProgressBar";
+
+ static final int CHRONOMETER_ID = android.R.id.text1;
+ static final int PROGRESSBAR_ID = android.R.id.progress;
+
+ Chronometer mChronometer = null;
+ ProgressBar mProgressBar = null;
+
+ long mDurationBase = -1;
+ int mDuration = -1;
+
+ boolean mChronometerFollow = false;
+ int mChronometerGravity = Gravity.NO_GRAVITY;
+
+ public TextProgressBar(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ public TextProgressBar(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public TextProgressBar(Context context) {
+ super(context);
+ }
+
+ /**
+ * Catch any interesting children when they are added.
+ */
+ @Override
+ public void addView(View child, int index, ViewGroup.LayoutParams params) {
+ super.addView(child, index, params);
+
+ int childId = child.getId();
+ if (childId == CHRONOMETER_ID && child instanceof Chronometer) {
+ mChronometer = (Chronometer) child;
+ mChronometer.setOnChronometerTickListener(this);
+
+ // Check if Chronometer should move with with ProgressBar
+ mChronometerFollow = (params.width == ViewGroup.LayoutParams.WRAP_CONTENT);
+ mChronometerGravity = (mChronometer.getGravity() & Gravity.HORIZONTAL_GRAVITY_MASK);
+
+ } else if (childId == PROGRESSBAR_ID && child instanceof ProgressBar) {
+ mProgressBar = (ProgressBar) child;
+ }
+ }
+
+ /**
+ * Set the expected termination time of the running {@link Chronometer}.
+ * This value is used to adjust the {@link ProgressBar} against the elapsed
+ * time.
+ *
+ * Call this after adjusting the {@link Chronometer} base, if
+ * necessary.
+ *
+ * @param durationBase Use the {@link SystemClock#elapsedRealtime} time
+ * base.
+ */
+ public void setDurationBase(long durationBase) {
+ mDurationBase = durationBase;
+
+ if (mProgressBar == null || mChronometer == null) {
+ throw new RuntimeException("Expecting child ProgressBar with id " +
+ "'android.R.id.progress' and Chronometer id 'android.R.id.text1'");
+ }
+
+ // Update the ProgressBar maximum relative to Chronometer base
+ mDuration = (int) (durationBase - mChronometer.getBase());
+ mProgressBar.setMax(mDuration);
+
+ }
+
+ /**
+ * Callback when {@link Chronometer} changes, indicating that we should
+ * update the {@link ProgressBar} and change the layout if necessary.
+ */
+ public void onChronometerTick(Chronometer chronometer) {
+ if (mProgressBar == null) {
+ throw new RuntimeException(
+ "Expecting child ProgressBar with id 'android.R.id.progress'");
+ }
+
+ // Stop Chronometer if we're past duration
+ long now = SystemClock.elapsedRealtime();
+ if (now >= mDurationBase) {
+ mChronometer.stop();
+ }
+
+ // Update the ProgressBar status
+ int remaining = (int) (mDurationBase - now);
+ mProgressBar.setProgress(mDuration - remaining);
+
+ // Move the Chronometer if gravity is set correctly
+ if (mChronometerFollow) {
+ RelativeLayout.LayoutParams params;
+
+ // Calculate estimate of ProgressBar leading edge position
+ params = (RelativeLayout.LayoutParams) mProgressBar.getLayoutParams();
+ int contentWidth = mProgressBar.getWidth() - (params.leftMargin + params.rightMargin);
+ int leadingEdge = ((contentWidth * mProgressBar.getProgress()) /
+ mProgressBar.getMax()) + params.leftMargin;
+
+ // Calculate any adjustment based on gravity
+ int adjustLeft = 0;
+ int textWidth = mChronometer.getWidth();
+ if (mChronometerGravity == Gravity.RIGHT) {
+ adjustLeft = -textWidth;
+ } else if (mChronometerGravity == Gravity.CENTER_HORIZONTAL) {
+ adjustLeft = -(textWidth / 2);
+ }
+
+ // Limit margin to keep text inside ProgressBar bounds
+ leadingEdge += adjustLeft;
+ int rightLimit = contentWidth - params.rightMargin - textWidth;
+ if (leadingEdge < params.leftMargin) {
+ leadingEdge = params.leftMargin;
+ } else if (leadingEdge > rightLimit) {
+ leadingEdge = rightLimit;
+ }
+
+ params = (RelativeLayout.LayoutParams) mChronometer.getLayoutParams();
+ params.leftMargin = leadingEdge;
+
+ // Request layout to move Chronometer
+ mChronometer.requestLayout();
+
+ }
+ }
+}
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 79965b94313c8..2f1f9b8c64199 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -51,9 +51,9 @@ struct fields_t {
static fields_t fields;
static Mutex sLock;
+static jclass sCameraClass;
struct callback_cookie {
- jclass camera_class;
jobject camera_ref;
};
@@ -87,7 +87,7 @@ static void err_callback(status_t err, void *cookie)
}
LOGV("err_callback: camera_ref=%x, cookie=%x", (int)c->camera_ref, (int)cookie);
- env->CallStaticVoidMethod(c->camera_class, fields.post_event,
+ env->CallStaticVoidMethod(sCameraClass, fields.post_event,
c->camera_ref, kErrorCallback, error, 0, NULL);
}
@@ -115,7 +115,6 @@ static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, jobj
jniThrowException(env, "java/lang/Exception", NULL);
return;
}
- cookie->camera_class = (jclass)env->NewGlobalRef(clazz);
// We use a weak reference so the Camera object can be garbage collected.
// The reference is only used as a proxy for callbacks.
@@ -157,7 +156,6 @@ static void android_hardware_Camera_release(JNIEnv *env, jobject thiz)
if (cookie) {
env->DeleteGlobalRef(cookie->camera_ref);
- env->DeleteGlobalRef(cookie->camera_class);
delete cookie;
env->SetIntField(thiz, fields.listener_context, 0);
}
@@ -207,7 +205,7 @@ static void preview_callback(const sp& mem, void *cookie)
obj = array;
- env->CallStaticVoidMethod(c->camera_class, fields.post_event,
+ env->CallStaticVoidMethod(sCameraClass, fields.post_event,
c->camera_ref, kPreviewCallback, arg1, arg2, obj);
env->DeleteLocalRef(array);
}
@@ -270,13 +268,11 @@ static void autofocus_callback_impl(bool success, void *cookie)
return;
}
callback_cookie *c = (callback_cookie *)cookie;
- env->CallStaticVoidMethod(c->camera_class, fields.post_event,
+ env->CallStaticVoidMethod(sCameraClass, fields.post_event,
c->camera_ref, kAutoFocusCallback,
success, 0, NULL);
}
-
-
static void android_hardware_Camera_autoFocus(JNIEnv *env, jobject thiz)
{
sp c = get_native_camera(env, thiz);
@@ -301,7 +297,7 @@ static void jpeg_callback(const sp& mem, void *cookie)
jobject obj = NULL;
if (mem == NULL) {
- env->CallStaticVoidMethod(c->camera_class, fields.post_event,
+ env->CallStaticVoidMethod(sCameraClass, fields.post_event,
c->camera_ref, kJpegCallback, arg1, arg2, NULL);
return;
}
@@ -331,7 +327,7 @@ static void jpeg_callback(const sp& mem, void *cookie)
obj = array;
- env->CallStaticVoidMethod(c->camera_class, fields.post_event,
+ env->CallStaticVoidMethod(sCameraClass, fields.post_event,
c->camera_ref, kJpegCallback, arg1, arg2, obj);
env->DeleteLocalRef(array);
}
@@ -344,7 +340,7 @@ static void shutter_callback_impl(void *cookie)
return;
}
callback_cookie *c = (callback_cookie *)cookie;
- env->CallStaticVoidMethod(c->camera_class, fields.post_event,
+ env->CallStaticVoidMethod(sCameraClass, fields.post_event,
c->camera_ref, kShutterCallback, 0, 0, NULL);
}
@@ -357,7 +353,7 @@ static void raw_callback(const sp& mem __attribute__((unused)),
return;
}
callback_cookie *c = (callback_cookie *)cookie;
- env->CallStaticVoidMethod(c->camera_class, fields.post_event,
+ env->CallStaticVoidMethod(sCameraClass, fields.post_event,
c->camera_ref, kRawCallback, 0, 0, NULL);
}
@@ -524,6 +520,7 @@ int register_android_hardware_Camera(JNIEnv *env)
return -1;
jclass clazz = env->FindClass("android/hardware/Camera");
+ sCameraClass = (jclass)env->NewGlobalRef(clazz);
fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative",
"(Ljava/lang/Object;IIILjava/lang/Object;)V");
if (fields.post_event == NULL) {
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 6ca821d2fca5e..d9effeed19aad 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
#define LOG_TAG "AudioTrack-JNI"
@@ -164,8 +164,8 @@ android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_th
jint streamType, jint sampleRateInHertz, jint nbChannels,
jint audioFormat, jint buffSizeInBytes, jint memoryMode)
{
- //LOGV("sampleRate=%d, audioFormat(from Java)=%d, nbChannels=%d, buffSize=%d",
- // sampleRateInHertz, audioFormat, nbChannels, buffSizeInBytes);
+ LOGV("sampleRate=%d, audioFormat(from Java)=%d, nbChannels=%d, buffSize=%d",
+ sampleRateInHertz, audioFormat, nbChannels, buffSizeInBytes);
int afSampleRate;
int afFrameCount;
@@ -210,7 +210,20 @@ android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_th
LOGE("Error creating AudioTrack: unsupported audio format.");
return AUDIOTRACK_ERROR_SETUP_INVALIDFORMAT;
}
-
+
+ // for the moment 8bitPCM in MODE_STATIC is not supported natively in the AudioTrack C++ class
+ // so we declare everything as 16bitPCM, the 8->16bit conversion for MODE_STATIC will be handled
+ // in android_media_AudioTrack_native_write()
+ if ((audioFormat == javaAudioTrackFields.PCM8)
+ && (memoryMode == javaAudioTrackFields.MODE_STATIC)) {
+ LOGV("android_media_AudioTrack_native_setup(): requesting MODE_STATIC for 8bit \
+ buff size of %dbytes, switching to 16bit, buff size of %dbytes",
+ buffSizeInBytes, 2*buffSizeInBytes);
+ audioFormat = javaAudioTrackFields.PCM16;
+ // we will need twice the memory to store the data
+ buffSizeInBytes *= 2;
+ }
+
// compute the frame count
int bytesPerSample = audioFormat == javaAudioTrackFields.PCM16 ? 2 : 1;
int format = audioFormat == javaAudioTrackFields.PCM16 ?
@@ -387,13 +400,13 @@ android_media_AudioTrack_set_volume(JNIEnv *env, jobject thiz, jfloat leftVol, j
// ----------------------------------------------------------------------------
static void android_media_AudioTrack_native_finalize(JNIEnv *env, jobject thiz) {
- LOGV("android_media_AudioTrack_native_finalize jobject: %x\n", (int)thiz);
+ //LOGV("android_media_AudioTrack_native_finalize jobject: %x\n", (int)thiz);
// delete the AudioTrack object
AudioTrack *lpTrack = (AudioTrack *)env->GetIntField(
thiz, javaAudioTrackFields.nativeTrackInJavaObj);
if (lpTrack) {
- LOGV("deleting lpTrack: %x\n", (int)lpTrack);
+ //LOGV("deleting lpTrack: %x\n", (int)lpTrack);
lpTrack->stop();
delete lpTrack;
}
@@ -402,7 +415,7 @@ static void android_media_AudioTrack_native_finalize(JNIEnv *env, jobject thiz)
AudioTrackJniStorage* pJniStorage = (AudioTrackJniStorage *)env->GetIntField(
thiz, javaAudioTrackFields.jniData);
if (pJniStorage) {
- LOGV("deleting pJniStorage: %x\n", (int)pJniStorage);
+ //LOGV("deleting pJniStorage: %x\n", (int)pJniStorage);
delete pJniStorage;
}
}
@@ -422,7 +435,8 @@ static void android_media_AudioTrack_native_release(JNIEnv *env, jobject thiz)
// ----------------------------------------------------------------------------
static jint android_media_AudioTrack_native_write(JNIEnv *env, jobject thiz,
jbyteArray javaAudioData,
- jint offsetInBytes, jint sizeInBytes) {
+ jint offsetInBytes, jint sizeInBytes,
+ jint javaAudioFormat) {
jbyte* cAudioData = NULL;
AudioTrack *lpTrack = NULL;
//LOGV("android_media_AudioTrack_native_write(offset=%d, sizeInBytes=%d) called",
@@ -453,8 +467,22 @@ static jint android_media_AudioTrack_native_write(JNIEnv *env, jobject thiz,
if (lpTrack->sharedBuffer() == 0) {
written = lpTrack->write(cAudioData + offsetInBytes, sizeInBytes);
} else {
- memcpy(lpTrack->sharedBuffer()->pointer(), cAudioData + offsetInBytes, sizeInBytes);
- written = sizeInBytes;
+ if (javaAudioFormat == javaAudioTrackFields.PCM16) {
+ memcpy(lpTrack->sharedBuffer()->pointer(), cAudioData + offsetInBytes, sizeInBytes);
+ written = sizeInBytes;
+ } else if (javaAudioFormat == javaAudioTrackFields.PCM8) {
+ // cAudioData contains 8bit data we need to expand to 16bit before copying
+ // to the shared memory
+ int count = sizeInBytes;
+ int16_t *dst = (int16_t *)lpTrack->sharedBuffer()->pointer();
+ const int8_t *src = (const int8_t *)(cAudioData + offsetInBytes);
+ while(count--) {
+ *dst++ = (int16_t)(*src++^0x80) << 8;
+ }
+ // even though we wrote 2*sizeInBytes, we only report sizeInBytes as written to hide
+ // the 8bit mixer restriction from the user of this function
+ written = sizeInBytes;
+ }
}
env->ReleasePrimitiveArrayCritical(javaAudioData, cAudioData, 0);
@@ -468,10 +496,12 @@ static jint android_media_AudioTrack_native_write(JNIEnv *env, jobject thiz,
// ----------------------------------------------------------------------------
static jint android_media_AudioTrack_native_write_short(JNIEnv *env, jobject thiz,
jshortArray javaAudioData,
- jint offsetInShorts, jint sizeInShorts) {
+ jint offsetInShorts, jint sizeInShorts,
+ jint javaAudioFormat) {
return (android_media_AudioTrack_native_write(env, thiz,
(jbyteArray) javaAudioData,
- offsetInShorts*2, sizeInShorts*2)
+ offsetInShorts*2, sizeInShorts*2,
+ javaAudioFormat)
/ 2);
}
@@ -676,6 +706,7 @@ static jint android_media_AudioTrack_get_output_sample_rate(JNIEnv *env, jobjec
// ----------------------------------------------------------------------------
// returns the minimum required size for the successful creation of a streaming AudioTrack
+// returns -1 if there was an error querying the hardware.
static jint android_media_AudioTrack_get_min_buff_size(JNIEnv *env, jobject thiz,
jint sampleRateInHertz, jint nbChannels, jint audioFormat) {
int afSamplingRate;
@@ -715,8 +746,8 @@ static JNINativeMethod gMethods[] = {
(void *)android_media_AudioTrack_native_setup},
{"native_finalize", "()V", (void *)android_media_AudioTrack_native_finalize},
{"native_release", "()V", (void *)android_media_AudioTrack_native_release},
- {"native_write_byte", "([BII)I", (void *)android_media_AudioTrack_native_write},
- {"native_write_short", "([SII)I", (void *)android_media_AudioTrack_native_write_short},
+ {"native_write_byte", "([BIII)I", (void *)android_media_AudioTrack_native_write},
+ {"native_write_short", "([SIII)I", (void *)android_media_AudioTrack_native_write_short},
{"native_setVolume", "(FF)V", (void *)android_media_AudioTrack_set_volume},
{"native_get_native_frame_count",
"()I", (void *)android_media_AudioTrack_get_native_frame_count},
diff --git a/core/jni/android_media_JetPlayer.cpp b/core/jni/android_media_JetPlayer.cpp
index fe6094341886d..e345af6213141 100644
--- a/core/jni/android_media_JetPlayer.cpp
+++ b/core/jni/android_media_JetPlayer.cpp
@@ -81,7 +81,7 @@ android_media_JetPlayer_setup(JNIEnv *env, jobject thiz, jobject weak_this,
jint maxTracks, jint trackBufferSize)
{
//LOGV("android_media_JetPlayer_setup(): entering.");
- JetPlayer* lpJet = new JetPlayer(weak_this, maxTracks, trackBufferSize);
+ JetPlayer* lpJet = new JetPlayer(env->NewGlobalRef(weak_this), maxTracks, trackBufferSize);
EAS_RESULT result = lpJet->init();
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index a7a0428a4f6f1..a6b63d81f2b9a 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -117,22 +117,25 @@ static void read_mapinfo(FILE *fp, stats_t* stats)
line[--len] = 0;
/* ignore guard pages */
- if (len > 18 && line[18] == '-') skip = true;
+ if (len > 18 && line[17] == '-') skip = true;
start = strtoul(line, 0, 16);
- if (strstr("[heap]", line)) {
+ if (strstr(line, "[heap]")) {
isNativeHeap = 1;
- } else if (strstr("/dalvik-LinearAlloc", line)) {
+ } else if (strstr(line, "/dalvik-LinearAlloc")) {
isDalvikHeap = 1;
- } else if (strstr("/mspace/dalvik-heap", line)) {
+ } else if (strstr(line, "/mspace/dalvik-heap")) {
isDalvikHeap = 1;
- } else if (strstr("/dalvik-heap-bitmap/", line)) {
+ } else if (strstr(line, "/dalvik-heap-bitmap/")) {
isDalvikHeap = 1;
- } else if (strstr("/tmp/sqlite-heap", line)) {
+ } else if (strstr(line, "/tmp/sqlite-heap")) {
isSqliteHeap = 1;
}
+ //LOGI("native=%d dalvik=%d sqlite=%d: %s\n", isNativeHeap, isDalvikHeap,
+ // isSqliteHeap, line);
+
while (true) {
if (fgets(line, 1024, fp) == 0) {
done = true;
diff --git a/core/jni/android_server_BluetoothDeviceService.cpp b/core/jni/android_server_BluetoothDeviceService.cpp
index 0936310ba06df..796da1536b1c2 100644
--- a/core/jni/android_server_BluetoothDeviceService.cpp
+++ b/core/jni/android_server_BluetoothDeviceService.cpp
@@ -515,24 +515,39 @@ static jboolean cancelBondingProcessNative(JNIEnv *env, jobject object,
static jboolean removeBondingNative(JNIEnv *env, jobject object, jstring address) {
LOGV(__FUNCTION__);
+ jboolean result = JNI_FALSE;
#ifdef HAVE_BLUETOOTH
native_data_t *nat = get_native_data(env, object);
if (nat) {
const char *c_address = env->GetStringUTFChars(address, NULL);
LOGV("... address = %s", c_address);
+ DBusError err;
+ dbus_error_init(&err);
DBusMessage *reply =
- dbus_func_args_timeout(env, nat->conn, -1, nat->adapter,
- DBUS_CLASS_NAME, "RemoveBonding",
- DBUS_TYPE_STRING, &c_address,
- DBUS_TYPE_INVALID);
- env->ReleaseStringUTFChars(address, c_address);
- if (reply) {
- dbus_message_unref(reply);
+ dbus_func_args_error(env, nat->conn, &err, nat->adapter,
+ DBUS_CLASS_NAME, "RemoveBonding",
+ DBUS_TYPE_STRING, &c_address,
+ DBUS_TYPE_INVALID);
+ if (dbus_error_is_set(&err)) {
+ if (dbus_error_has_name(&err,
+ BLUEZ_DBUS_BASE_IFC ".Error.DoesNotExist")) {
+ LOGW("%s: Warning: %s (%s)", __FUNCTION__, err.message,
+ c_address);
+ result = JNI_TRUE;
+ } else {
+ LOGE("%s: D-Bus error %s (%s)", __FUNCTION__, err.name,
+ err.message);
+ }
+ } else {
+ result = JNI_TRUE;
}
- return JNI_TRUE;
+
+ env->ReleaseStringUTFChars(address, c_address);
+ dbus_error_free(&err);
+ if (reply) dbus_message_unref(reply);
}
#endif
- return JNI_FALSE;
+ return result;
}
static jobjectArray listBondingsNative(JNIEnv *env, jobject object) {
diff --git a/core/jni/android_server_BluetoothEventLoop.cpp b/core/jni/android_server_BluetoothEventLoop.cpp
index e5ae2ea19bea6..9100e81013e78 100644
--- a/core/jni/android_server_BluetoothEventLoop.cpp
+++ b/core/jni/android_server_BluetoothEventLoop.cpp
@@ -755,17 +755,22 @@ void onCreateBondingResult(DBusMessage *msg, void *user) {
// already bonded
LOGV("... error = %s (%s)\n", err.name, err.message);
result = BOND_RESULT_SUCCESS;
+ } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.InProgress")) {
+ // don't make the java callback
+ LOGV("... error = %s (%s)\n", err.name, err.message);
+ goto done;
} else {
LOGE("%s: D-Bus error: %s (%s)\n", __FUNCTION__, err.name, err.message);
result = BOND_RESULT_ERROR;
}
- dbus_error_free(&err);
}
env->CallVoidMethod(event_loop_nat->me,
method_onCreateBondingResult,
env->NewStringUTF(address),
result);
+done:
+ dbus_error_free(&err);
free(user);
}
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index f09bd4c7be982..8baaa84e6820c 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -212,7 +212,9 @@ static jobject Surface_lockCanvas(JNIEnv* env, jobject clazz, jobject dirtyRect)
dirty.top = env->GetIntField(dirtyRect, ro.t);
dirty.right = env->GetIntField(dirtyRect, ro.r);
dirty.bottom= env->GetIntField(dirtyRect, ro.b);
- dirtyRegion.set(dirty);
+ if (dirty.left < dirty.right && dirty.top < dirty.bottom) {
+ dirtyRegion.set(dirty);
+ }
} else {
dirtyRegion.set(Rect(0x3FFF,0x3FFF));
}
@@ -246,6 +248,14 @@ static jobject Surface_lockCanvas(JNIEnv* env, jobject clazz, jobject dirtyRect)
int saveCount = nativeCanvas->save();
env->SetIntField(clazz, so.saveCount, saveCount);
+ if (dirtyRect) {
+ Rect bounds(dirtyRegion.bounds());
+ env->SetIntField(dirtyRect, ro.l, bounds.left);
+ env->SetIntField(dirtyRect, ro.t, bounds.top);
+ env->SetIntField(dirtyRect, ro.r, bounds.right);
+ env->SetIntField(dirtyRect, ro.b, bounds.bottom);
+ }
+
return canvas;
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 0e8d3fd8a03fa..2c3b590229443 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -18,7 +18,8 @@
*/
-->
+ package="android" android:sharedUserId="android.uid.system"
+ android:sharedUserLabel="@string/android_system_label">
@@ -946,7 +947,7 @@
+
+
+
diff --git a/core/res/res/drawable/zoom_ring_thumb_plus_arrow.png b/core/res/res/drawable/zoom_ring_thumb_plus_arrow.png
new file mode 100644
index 0000000000000..0591d397c1436
Binary files /dev/null and b/core/res/res/drawable/zoom_ring_thumb_plus_arrow.png differ
diff --git a/core/res/res/drawable/zoom_ring_thumb_plus_arrow_rotatable.xml b/core/res/res/drawable/zoom_ring_thumb_plus_arrow_rotatable.xml
new file mode 100644
index 0000000000000..b77eaa4090c18
--- /dev/null
+++ b/core/res/res/drawable/zoom_ring_thumb_plus_arrow_rotatable.xml
@@ -0,0 +1,22 @@
+
+
+
+
diff --git a/core/res/res/drawable/zoom_ring_track.png b/core/res/res/drawable/zoom_ring_track.png
index 91d91f47061fc..60a15b7aded0f 100644
Binary files a/core/res/res/drawable/zoom_ring_track.png and b/core/res/res/drawable/zoom_ring_track.png differ
diff --git a/core/res/res/drawable/zoom_ring_track_absolute.png b/core/res/res/drawable/zoom_ring_track_absolute.png
new file mode 100644
index 0000000000000..6b38c53431f43
Binary files /dev/null and b/core/res/res/drawable/zoom_ring_track_absolute.png differ
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index e0c0a64ee7f52..672c4b9885376 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -262,10 +262,8 @@
"Umožňuje aplikaci vynutit restartování telefonu.""připojení a odpojení souborových systémů""Umožňuje aplikaci připojit či odpojit souborové systémy ve vyměnitelných úložištích."
-
-
-
-
+ "formátovat externí úložiště"
+ "Umožňuje aplikaci formátovat vyměnitelná úložiště.""ovládání vibrací""Umožňuje aplikaci ovládat vibrace.""ovládání kontrolky"
@@ -280,10 +278,8 @@
"Umožňuje povolit či zakázat aktualizace polohy prostřednictvím bezdrátového připojení. Aplikace toto nastavení obvykle nepoužívají.""přístup k vlastnostem Checkin""Umožňuje čtení i zápis vlastností nahraných službou Checkin. Běžné aplikace toto nastavení obvykle nevyužívají."
-
-
-
-
+ "zvolit gadgety"
+ "Umožňuje aplikaci sdělit systému, které aplikace mohou použít které gadgety. Aplikace s tímto oprávněním mohou zpřístupnit osobní údaje jiným aplikacím. Není určeno pro normální aplikace.""změny stavu telefonu""Umožňuje aplikaci ovládat telefonní funkce zařízení. Aplikace s tímto oprávněním může přepínat sítě nebo zapnout či vypnout bezdrátové připojení telefonu bez vašeho svolení.""zjistit stav telefonu"
@@ -312,10 +308,8 @@
"Umožňuje aplikaci změnit nastavení APN, jako je například proxy či port APN.""změna připojení k síti""Umožňuje aplikaci změnit stav připojení k síti."
-
-
-
-
+ "změnit nastavení použití dat na pozadí"
+ "Umožňuje aplikaci změnit nastavení použití dat na pozadí.""zobrazení stavu WiFi""Umožňuje aplikaci zobrazit informace o stavu připojení WiFi.""Změnit stav WiFi"
@@ -336,14 +330,10 @@
"Umožňuje aplikaci získat podrobnosti o aktuálně synchronizovaných zdrojích.""zápis odebíraných zdrojů""Umožňuje aplikaci upravit vaše aktuálně synchronizované zdroje. To může škodlivým aplikacím umožnit změnu vašich synchronizovaných zdrojů."
-
-
-
-
-
-
-
-
+ "číst slovník definovaný uživatelem"
+ "Umožní aplikaci číst soukromá slova, jména a fráze, která uživatel mohl uložit do svého slovníku."
+ "zapisovat do slovníku definovaného uživatelem"
+ "Umožní aplikaci zapisovat nová slova do uživatelského slovníku.""Domů""Mobil"
@@ -440,12 +430,9 @@
"Test FACTORY_TEST lze provést pouze u balíčků nainstalovaných ve složce /system/app.""Nebyl nalezen žádný balíček umožňující test FACTORY_TEST.""Restartovat"
-
-
-
-
-
-
+ "Stránka %s uvádí:"
+ "JavaScript"
+ "Chcete opustit tuto stránku?"\n\n"%s"\n\n"Vyberte OK, chcete-li pokračovat, nebo Zrušit, chcete-li na stránce zůstat.""Potvrdit""Chcete, aby si prohlížeč zapamatoval toto heslo?""Nyní ne"
@@ -496,22 +483,38 @@
"zítra""zbývající počet dní: %d"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ "před 1 s"
+ "před %d s"
+
+
+ "před 1 min."
+ "před %d min."
+
+
+ "před 1 hodinou"
+ "před %d hod."
+
+
+ "včera"
+ "před %d dny"
+
+
+ "za 1 s"
+ "za %d s"
+
+
+ "za 1 min."
+ "za %d min."
+
+
+ "za 1 hodinu"
+ "za %d hod."
+
+
+ "zítra"
+ "zbývající počet dní: %d"
+ "%s""%s""v roce %s"
@@ -553,17 +556,15 @@
"%1$s, %2$s, %3$s""%2$s, %3$s""%1$s, %3$s"
-
-
-
-
+ "%1$s, %2$s"
+ "%1$s, %2$s""%1$s, %2$s"
- "MMMM' 'd', 'yyyy"
- "d'. 'MMMM' 'yyyy"
- "d'. 'MMM' 'yyyy"
- "d'. 'MMM' 'yyyy"
- "h':'mm' 'a"
- "H':'mm"
+ "MMMM' 'd', 'yyyy"
+ "d'. 'MMMM' 'yyyy"
+ "d'. 'MMM' 'yyyy"
+ "d'. 'MMM' 'yyyy"
+ "h':'mm' 'a"
+ "H':'mm""poledne""Poledne""půlnoc"
@@ -691,8 +692,7 @@
"Vložit""Kopírovat adresu URL""Metoda zadávání dat"
-
-
+ "Přidat „%s“ do slovníku""Úpravy textu""Málo paměti""V telefonu zbývá málo místa pro ukládání dat."
@@ -700,8 +700,7 @@
"Zrušit""OK""Zrušit"
-
-
+ "Upozornění""ZAPNUTO""VYPNOUT""Dokončit akci pomocí aplikace"
@@ -725,8 +724,7 @@
"Hlasitost médií""Přehrávání pomocí rozhraní Bluetooth""Hlasitost hovoru"
-
-
+ "Hlasitost příchozích hovorů při připojení Bluetooth""Hlasitost upozornění a budíku""Hlasitost oznámení""Hlasitost"
@@ -762,60 +760,35 @@
"Při používání vaší karty SD jako úložiště USB došlo k problému.""USB připojeno""Vyberte, chcete-li kopírovat soubory do nebo z počítače."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "Vypnout úložiště USB"
+ "Vyberte, chcete-li vypnout úložiště USB."
+ "Vypnout úložiště USB"
+ "Před vypnutím úložiště USB se přesvědčte, zda byl hostitel USB odpojen. Úložiště USB vypnete volbou Vypnout."
+ "Vypnout"
+ "Zrušit"
+ "Při vypínání úložiště USB došlo k problémům. Zkontrolujte, zda byl hostitel USB odpojen, a zkuste to znovu."
+ "Formátovat kartu SD"
+ "Opravdu chcete kartu SD naformátovat? Všechna data na kartě budou ztracena."
+ "Formátovat""Výběr metody zadávání dat""AÁBCČDĎEÉĚFGHCHIÍJKLMNŇOÓPQRŘSŠTŤUÚVWXYÝZŽ""0123456789AÁBCČDĎEÉĚFGHCHIÍJKLMNŇOÓPQRŘSŠTŤUÚVWXYÝZŽ"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "kandidáti"
+ "Příprava karty SD"
+ "Kontrola chyb"
+ "Prázdná karta SD"
+ "Karta SD je prázdná nebo používá nepodporovaný systém souborů."
+ "Poškozená karta SD"
+ "Karta SD je poškozena. Pravděpodobně ji bude nutné znovu formátovat."
+ "Karta SD byla neočekávaně odebrána"
+ "Chcete-li zabránit ztrátě dat, kartu SD před odebráním odpojte."
+ "Kartu SD je možné bezpečně odebrat"
+ "Kartu SD lze nyní bezpečně vyjmout."
+ "Karta SD byla odstraněna"
+ "Karta SD byla odebrána. Chcete-li zvětšit úložiště svého zařízení, vložte kartu SD."
+ "Nebyly nalezeny žádné odpovídající aktivity."
+ "aktualizovat statistiku použití součástí"
+ "Umožňuje změnu shromážděných statistických údajů o použití součástí. Není určeno pro běžné aplikace."
+
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index d9c417434a30f..113c22672a908 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -262,10 +262,8 @@
"Ermöglicht der Anwendung, einen Neustart des Telefons zu erzwingen.""Dateisysteme bereitstellen oder Bereitstellung aufheben""Ermöglicht der Anwendung, Dateisysteme für austauschbare Speicherplätze bereitzustellen oder die Bereitstellung aufzuheben."
-
-
-
-
+ "Externen Speicher formatieren"
+ "Erlaubt der Anwendung, austauschbaren Speicher zu formatieren.""Vibrationsalarm steuern""Ermöglicht der Anwendung, den Vibrationsalarm zu steuern.""Lichtanzeige steuern"
@@ -280,10 +278,8 @@
"Ermöglicht die Aktivierung/Deaktivierung der Radio-Benachrichtigungen über Standort-Updates. Nicht für normale Anwendungen vorgesehen.""Auf Check-In-Eigenschaften zugreifen""Ermöglicht den Schreib-/Lesezugriff auf vom Check-In-Service hochgeladene Elemente. Nicht für normale Anwendungen vorgesehen."
-
-
-
-
+ "Gadgets auswählen"
+ "Bei dieser Option meldet die Anwendung dem System, welche Gadgets von welcher Anwendung verwendet werden können. Mit dieser Genehmigung können Anwendungen anderen Anwendungen Zugriff auf persönliche Daten geben. Nicht für normale Anwendungen vorgesehen.""Telefonstatus ändern""Ermöglicht einer Anwendung, die Telefonfunktionen des Gerätes zu steuern. Eine Anwendung mit dieser Berechtigung kann unter anderem das Netzwerk wechseln oder das Radio des Telefons ein- und ausschalten, ohne Sie darüber zu informieren.""Telefonstatus lesen"
@@ -312,10 +308,8 @@
"Ermöglicht einer Anwendung, die APN-Einstellungen wie Proxy und Port eines Zugriffspunkts zu ändern.""Netzwerkkonnektivität ändern""Ermöglicht einer Anwendung, den Status der Netzwerkkonnektivität zu ändern."
-
-
-
-
+ "Einstellung zur Verwendung von Hintergrunddaten ändern"
+ "Ermöglicht einer Anwendung, die Einstellung der Verwendung von Hintergrunddaten zu ändern.""WLAN-Status anzeigen""Ermöglicht einer Anwendung, die Informationen zum WLAN-Status einzusehen.""WLAN-Status ändern"
@@ -336,14 +330,10 @@
"Ermöglicht einer Anwendung, Details zu den zurzeit synchronisierten Feeds abzurufen.""Abonnierte Feeds schreiben""Ermöglicht einer Anwendung, Änderungen an den kürzlich synchronisierten Feeds vorzunehmen. Schädliche Anwendungen könnten so Ihre synchronisierten Feeds ändern."
-
-
-
-
-
-
-
-
+ "Nutzerdefiniertes Wörterbuch lesen"
+ "Erlaubt einer Anwendung, alle privaten Wörter, Namen und Ausdrücke zu lesen, die ein Nutzer in seinem Wörterbuch gespeichert hat."
+ "in nutzerdefiniertes Wörterbuch schreiben"
+ "Erlaubt einer Anwendung, neue Wörter in das Wörterbuch des Nutzers zu schreiben.""Privat""Mobil"
@@ -440,12 +430,9 @@
"Die Aktion FACTORY_TEST wird nur für unter \"/system/app\" gespeicherte Pakete unterstützt.""Es wurden kein Paket mit der Aktion FACTORY_TEST gefunden.""Neu booten"
-
-
-
-
-
-
+ "Die Seite auf \'%s\' sagt:"
+ "JavaScript"
+ "Von dieser Seite navigieren?"\n\n"%s"\n\n"Wählen Sie \"OK\", um fortzufahren, oder wählen Sie \"Abbrechen\", um auf der aktuellen Seite zu bleiben.""Bestätigen""Möchten Sie, dass der Browser dieses Passwort speichert?""Nicht jetzt"
@@ -496,22 +483,38 @@
"morgen""in %d Tagen"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ "vor 1 Sekunde"
+ "Vor %d Sekunden"
+
+
+ "vor 1 Minute"
+ "vor %d Minuten"
+
+
+ "Vor 1 Stunde"
+ "Vor %d Stunden"
+
+
+ "Gestern"
+ "Vor %d Tagen"
+
+
+ "in 1 Sekunde"
+ "in %d Sekunden"
+
+
+ "in 1 Minute"
+ "in %d Minuten"
+
+
+ "in 1 Stunde"
+ "In %d Stunden"
+
+
+ "morgen"
+ "in %d Tagen"
+ "am %s""am %s""in %s"
@@ -542,8 +545,7 @@
"Video kann nicht wiedergegeben werden.""Dieses Video kann leider nicht abgespielt werden.""OK"
-
-
+ "AM""..""%d/%m/%Y""%1$s, %2$s, %3$s – %4$s, %5$s, %6$s"
@@ -554,17 +556,15 @@
"%1$s, %2$s, %3$s""%2$s, %3$s""%1$s, %3$s"
-
-
-
-
+ "%1$s, %2$s"
+ "%1$s, %2$s""%1$s, %2$s"
- "d'. 'MMMM' 'yyyy"
- "d'. 'MMMM' 'yyyy"
- "d'. 'MMM' 'yyyy"
- "d'. 'MMM' 'yyyy"
- "h':'mm' 'a"
- "H':'mm"
+ "d'. 'MMMM' 'yyyy"
+ "d'. 'MMMM' 'yyyy"
+ "d'. 'MMM' 'yyyy"
+ "d'. 'MMM' 'yyyy"
+ "h':'mm' 'a"
+ "H':'mm""Mittag""Mittag""Mitternacht"
@@ -692,8 +692,7 @@
"Einfügen""URL kopieren""Eingabemethode"
-
-
+ "\"%s\" dem Wörterbuch hinzufügen""Text bearbeiten""Geringer Speicher""Kaum noch freier Telefonspeicher verfügbar."
@@ -701,8 +700,7 @@
"Abbrechen""OK""Abbrechen"
-
-
+ "Achtung""EIN""AUS""Aktion beenden mit"
@@ -726,8 +724,7 @@
"Medienlautstärke""Wiedergabe durch Bluetooth""Hörerlautstärke"
-
-
+ "Lautstärke bei eingehendem Bluetooth-Anruf""Lautstärke für Alarm""Benachrichtigungslautstärke""Lautstärke"
@@ -763,60 +760,35 @@
"Bei der Verwendung Ihrer SD-Karte als USB-Speicher ist ein Problem aufgetreten.""USB-Verbindung""Wählen Sie die Dateien aus, die von Ihrem oder auf Ihren Computer kopiert werden sollen."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "USB-Speicher deaktivieren"
+ "Auswählen, um USB-Speicher zu deaktivieren."
+ "USB-Speicher deaktivieren"
+ "Bevor Sie den USB-Speicher deaktivieren, stellen Sie sicher, dass Sie Ihn vom USB-Host getrennt haben. Wählen Sie \"Deaktivieren\", um den USB-Speicher zu deaktivieren."
+ "Ausschalten"
+ "Abbrechen"
+ "Wir haben beim Deaktivieren des USB-Speichers ein Problem festgestellt. Überprüfen Sie, ob Sie den USB-Host getrennt haben, und versuchen Sie es erneut."
+ "SD-Karte formatieren"
+ "Möchten Sie die SD-Karte wirklich formatieren? Alle Daten auf Ihrer Karte gehen dann verloren."
+ "Format""Eingabemethode auswählen""ABCDEFGHIJKLMNOPQRSTUVWXYZ""0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "Kandidaten"
+ "SD-Karte wird vorbereitet"
+ "Nach Fehlern wird gesucht"
+ "SD-Karte leer"
+ "Die SD-Karte ist leer oder verwendet ein Dateisystem, das nicht unterstützt wird."
+ "Beschädigte SD-Karte"
+ "Die SD-Karte ist beschädigt. Sie müssen Ihre Karte eventuell neu formatieren."
+ "SD-Karte unerwartet entfernt"
+ "SD-Karte vor dem Entnehmen trennen, um Datenverlust zu vermeiden."
+ "SD-Karte\nkann entfernt werden."
+ "Die SD-Karte kann jetzt entfernt werden."
+ "SD-Karte entfernt"
+ "Die SD-Karte wurde entfernt. Legen Sie eine neue SD-Karte ein, um den Speicherplatz Ihres Geräts zu erweitern."
+ "Keine passenden Aktivitäten gefunden"
+ "Nutzungsstatistik der Komponente aktualisieren"
+ "Ermöglicht die Änderung von gesammelten Nutzungsstatistiken der Komponente. Nicht für normale Anwendungen vorgesehen."
+
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index b9df983a3fc3c..9da879b34a16c 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -710,7 +710,7 @@
-
+ "h:mmAA"
@@ -861,34 +861,38 @@
+
+
-
+ "%d/%m/%Y"
-
+ "%1$s, %2$s, %3$s – %4$s, %5$s, %6$s"
+ "%1$s, %2$s – %4$s, %5$s"
+
-
+ "%2$s, %3$s – %5$s, %6$s"
-
+ "%2$s – %5$s"
-
+ "%1$s – %2$s"
-
+ "%1$s, %2$s, %3$s"
-
+ "%2$s, %3$s"
-
+ "%1$s, %3$s"
-
+ "ddMMMMyyyy"
-
+ "ddMMMyyyy"
@@ -902,71 +906,73 @@
-
+ "%-d%B"
-
+ "%-d%B%Y"
-
+ "%H:%M:%S"
-
+ "%3$s%2$s – %8$s%7$s"
-
+ "%1$s, %3$s%2$s – %6$s, %8$s%7$s"
+
+ "%H:%M:%S%-d%B%Y"
-
+ "%3$s%2$s – %8$s%7$s%9$s"
-
+ "%1$s, %3$s%2$s – %6$s, %8$s%7$s%9$s"
-
+ " %3$s%2$s%5$s – %8$s%7$s%10$s"
-
+ "%1$s, %3$s%2$s, %5$s – %6$s, %8$s%7$s%10$s"
-
+ "%3$s%2$s, %4$s, %5$s – %8$s%7$s%9$s, %10$s"
-
+ "%1$s, %3$s%2$s%4$s, %5$s – %6$s, %8$s%7$s%9$s, %10$s"
-
+ "%3$s/%2$s – %8$s/%7$s"
-
+ "%1$s, %3$s/%2$s – %6$s, %8$s/%7$s"
-
+ "%3$s/%2$s/%4$s – %8$s/%7$s/%9$s"
-
+ "%1$s, %3$s/%2$s/%4$s – %6$s, %8$s/%7$s/%9$s"
-
+ "%3$s/%2$s, %5$s – %8$s/%7$s, %10$s"
-
+ "%1$s, %3$s/%2$s, %5$s – %6$s, %8$s/%7$s, %10$s"
-
+ "%3$s/%2$s/%4$s, %5$s – %8$s/%7$s/%9$s, %10$s"
-
+ "%1$s, %3$s/%2$s/%4$s, %5$s – %6$s, %8$s/%7$s/%9$s, %10$s"
-
+ "%3$s \u2013 %8$s%2$s"
-
+ "%1$s, %3$s%2$s – %6$s, %8$s%7$s"
-
+ "%3$s \u2013 %8$s%2$s%9$s"
-
+ "%1$s, %3$s%2$s%4$s – %6$s, %8$s%7$s%9$s"
-
+ "%3$s%2$s, %5$s – %8$s%7$s, %10$s"
-
+ "%1$s, %3$s%2$s, %5$s – %6$s, %8$s%7$s, %10$s"
-
+ "%3$s%2$s%4$s, %5$s – %8$s%7$s%9$s, %10$s"
-
+ "%1$s, %3$s%2$s%4$s, %5$s – %6$s, %8$s%7$s%9$s, %10$s"
-
+ "%-d%b%Y"
-
+ "%-d%b"
@@ -1112,9 +1118,9 @@
-
+ "%1$02d:%2$02d"
-
+ "%1$d:%2$02d:%3$02d"
diff --git a/core/res/res/values-en-rSG/strings.xml b/core/res/res/values-en-rSG/strings.xml
index b9df983a3fc3c..6850a5d2835b5 100644
--- a/core/res/res/values-en-rSG/strings.xml
+++ b/core/res/res/values-en-rSG/strings.xml
@@ -710,7 +710,7 @@
-
+ "h:mmAA"
@@ -861,34 +861,35 @@
-
-
+
-
+ "%1$s, %2$s, %3$s – %4$s, %5$s, %6$s"
-
+ "%1$s, %2$s – %4$s, %5$s"
+
+ "%d/%m/%Y"
-
+ "%2$s, %3$s – %5$s, %6$s"
-
+ "%2$s – %5$s"
-
+ "%1$s – %2$s"
-
+ "%1$s, %2$s, %3$s"
-
+ "%2$s, %3$s"
-
+ "%1$s, %3$s"
-
+ "%1$s, %2$s"
-
+ "ddMMMMyyyy"
-
+ "ddMMMyyyy"
@@ -902,71 +903,71 @@
-
+ "%-d%B"
-
+ "%-d%B%Y"
-
+ "%H:%M:%S"
-
+ "%H:%M:%S%-d%B%Y"
-
+ "%3$s%2$s – %8$s%7$s"
-
+ "%1$s, %3$s%2$s – %6$s, %8$s%7$s"
-
+ "%3$s%2$s – %8$s%7$s%9$s"
-
+ "%1$s, %3$s%2$s – %6$s, %8$s%7$s%9$s"
-
+ "%1$s, %3$s%2$s, %5$s – %6$s, %8$s%7$s%10$s"
-
+ "%3$s%2$s, %4$s, %5$s – %8$s%7$s%9$s, %10$s"
-
+ "%1$s, %3$s%2$s%4$s, %5$s – %6$s, %8$s%7$s%9$s, %10$s"
-
+ "%3$s/%2$s – %8$s/%7$s"
-
+ "%1$s, %3$s/%2$s – %6$s, %8$s/%7$s"
-
+ "%3$s/%2$s/%4$s – %8$s/%7$s/%9$s"
-
+ "%1$s, %3$s/%2$s/%4$s – %6$s, %8$s/%7$s/%9$s"
-
+ "%3$s/%2$s, %5$s – %8$s/%7$s, %10$s"
-
+ "%1$s, %3$s/%2$s, %5$s – %6$s, %8$s/%7$s, %10$s"
-
+ "%3$s/%2$s/%4$s, %5$s – %8$s/%7$s/%9$s, %10$s"
-
+ "%1$s, %3$s/%2$s/%4$s, %5$s – %6$s, %8$s/%7$s/%9$s, %10$s"
-
+ "%3$s \u2013 %8$s%2$s"
-
+ "%1$s, %3$s%2$s – %6$s, %8$s%7$s"
-
+ "%3$s \u2013 %8$s%2$s%9$s"
-
+ "%1$s, %3$s%2$s%4$s – %6$s, %8$s%7$s%9$s"
-
+ "%3$s%2$s, %5$s – %8$s%7$s, %10$s"
-
+ "%1$s, %3$s%2$s, %5$s – %6$s, %8$s%7$s, %10$s"
-
+ "%3$s%2$s%4$s, %5$s – %8$s%7$s%9$s, %10$s"
-
+ "%1$s, %3$s%2$s%4$s, %5$s – %6$s, %8$s%7$s%9$s, %10$s"
-
+ "%-d%b%Y"
-
+ "%-d%b"
@@ -1112,9 +1113,9 @@
-
+ "%1$02d:%2$02d"
-
+ "%1$d:%2$02d:%3$02d"
diff --git a/core/res/res/values-es-rES/arrays.xml b/core/res/res/values-es-rES/arrays.xml
new file mode 100644
index 0000000000000..7f5667cb966ec
--- /dev/null
+++ b/core/res/res/values-es-rES/arrays.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+ 40413496
+ -3713379
+
+
+
+ 6
+
+
+
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index dc17445527399..dc3fcd514e067 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -149,7 +149,7 @@
"habilitar depuración de aplicación""Permite que una aplicación active la depuración de otra aplicación. Las aplicaciones malintencionadas pueden utilizar este permiso para desactivar otras aplicaciones.""cambiar la configuración de la interfaz de usuario"
- "Permite que una aplicación cambie la configuración actual como, por ejemplo, la configuración regional o el tamaño de fuente general."
+ "Permite que una aplicación cambie la configuración actual como, por ejemplo, la configuración local o el tamaño de fuente general.""reiniciar otras aplicaciones""Permite que una aplicación reinicie de forma forzosa otras aplicaciones.""impedir su interrupción"
@@ -262,10 +262,8 @@
"Permite que la aplicación fuerce al teléfono a reiniciarse.""montar y desmontar sistemas de archivos""Permite que las aplicaciones monten y desmonten sistemas de archivos para un almacenamiento extraíble."
-
-
-
-
+ "formatear almacenamiento externo"
+ "Permite a la aplicación formatear un almacenamiento extraíble.""controlar vibración""Permite que la aplicación controle la función de vibración.""controlar linterna"
@@ -280,10 +278,8 @@
"Permite habilitar/inhabilitar las notificaciones de actualización de la ubicación de la radio. No está destinado al uso por parte de aplicaciones normales.""acceder a propiedades de registro""Permite el acceso de lectura/escritura a las propiedades cargadas por el servicio de registro. No está destinado al uso por parte de aplicaciones normales."
-
-
-
-
+ "seleccionar gadgets"
+ "Permite a la aplicación indicar al sistema qué gadgets puede utilizar cada aplicación. Con este permiso, las aplicaciones pueden permitir a otras aplicaciones acceder a datos personales. No está destinado al uso por parte de aplicaciones normales.""modificar estado del teléfono""Permite que la aplicación controle las funciones de teléfono del dispositivo. Una aplicación con este permiso puede cambiar redes, activar y desactivar la radio, etc., sin necesidad de notificar al usuario.""leer el estado del teléfono"
@@ -312,10 +308,8 @@
"Permite que una aplicación modifique los valores de configuración de un APN como, por ejemplo, el proxy y el puerto de cualquier APN.""cambiar la conectividad de red""Permite que una aplicación cambie la conectividad de red de estado."
-
-
-
-
+ "cambiar configuración de uso de datos de referencia"
+ "Permite a una aplicación cambiar la configuración de uso de los datos de referencia.""ver estado de la conectividad Wi-Fi""Permite que una aplicación vea la información sobre el estado de la conectividad Wi-Fi.""cambiar estado de Wi-Fi"
@@ -336,14 +330,10 @@
"Permite que una aplicación obtenga detalles sobre los feeds sincronizados en este momento.""escribir feeds a los que está suscrito el usuario""Permite que una aplicación modifique los feeds sincronizados actualmente. Este permiso podría provocar que una aplicación malintencionada cambie los feeds sincronizados."
-
-
-
-
-
-
-
-
+ "leer diccionario definido por el usuario"
+ "Permite a una aplicación leer cualquier frase, palabra o nombre privado que el usuario haya almacenado en su diccionario."
+ "escribir en el diccionario definido por el usuario"
+ "Permite a una aplicación escribir palabras nuevas en el diccionario del usuario.""Casa""Móvil"
@@ -355,7 +345,7 @@
"Personalizar"
- "Casa"
+ "Personal?????""Trabajo""Otra""Personalizar"
@@ -389,12 +379,12 @@
"Introduce el código PIN""El código PIN es incorrecto."
- "Para desbloquear el teléfono, pulsa \"Menú\" y, a continuación, pulsa 0."
+ "Para desbloquear el teléfono, pulsa MENU y, a continuación, pulsa 0.""Número de emergencia""(Sin servicio)"
- "Pantalla bloqueada."
- "Pulsa \"Menú\" para desbloquear el teléfono o realizar una llamada de emergencia."
- "Pulsa \"Menú\" para desbloquear el teléfono."
+ "Pantalla bloqueada"
+ "Pulsa MENU para desbloquear el teléfono o realizar una llamada de emergencia."
+ "Pulsa MENU para desbloquear el teléfono.""Crear patrón para desbloquear""Llamada de emergencia""Correcto"
@@ -440,12 +430,9 @@
"La acción FACTORY_TEST sólo es compatible con los paquetes instalados en /system/app.""No se ha encontrado ningún paquete que proporcione la acción FACTORY_TEST.""Reiniciar"
-
-
-
-
-
-
+ "La página \"%s\" dice:"
+ "JavaScript"
+ "¿Quieres salir de esta página?"\n\n"%s"\n\n"Selecciona \"Aceptar\" para continuar o \"Cancelar\" para permanecer en la página actual.""Confirmar""¿Deseas que el navegador recuerde esta contraseña?""Ahora no"
@@ -454,7 +441,7 @@
"No dispones de permiso para abrir esta página.""Texto copiado al portapapeles.""Más"
- "\"Menú\"+"
+ "MENU+""espacio""intro""suprimir"
@@ -496,22 +483,38 @@
"mañana""dentro de %d días"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ "hace 1 segundo"
+ "hace %d segundos"
+
+
+ "hace 1 minuto"
+ "hace %d minutos"
+
+
+ "hace 1 hora"
+ "hace %d horas"
+
+
+ "ayer"
+ "hace %d días"
+
+
+ "dentro de 1 segundo"
+ "dentro de %d segundos"
+
+
+ "dentro de 1 minuto"
+ "dentro de %d minutos"
+
+
+ "dentro de 1 hora"
+ "dentro de %d horas"
+
+
+ "mañana"
+ "dentro de %d días"
+ "el %s""a las %s""en %s"
@@ -553,17 +556,15 @@
"%1$s, %2$s, %3$s""%2$s, %3$s""%1$s, %3$s"
-
-
-
-
+ "%1$s, %2$s"
+ "%1$s, %2$s""%1$s, %2$s"
- "d' de 'MMMM' de 'yyyy"
- "MMMM' de 'd' de 'yyyy"
- "d' de 'MMM' de 'yyyy"
- "d' 'MMM', 'yyyy"
- "h':'mm' 'a"
- "H':'mm"
+ "d' de 'MMMM' de 'yyyy"
+ "MMMM' de 'd' de 'yyyy"
+ "d' de 'MMM' de 'yyyy"
+ "d' 'MMM', 'yyyy"
+ "h':'mm' 'a"
+ "H':'mm""mediodía""Mediodía""medianoche"
@@ -691,8 +692,7 @@
"Pegar""Copiar URL""Método de introducción de texto"
-
-
+ "Añadir \"%s\" al diccionario""Editar texto""Poco espacio""Se está agotando el espacio de almacenamiento del teléfono."
@@ -700,8 +700,7 @@
"Cancelar""Aceptar""Cancelar"
-
-
+ "Atención""Activado""Desconectado""Completar acción utilizando"
@@ -725,8 +724,7 @@
"Volumen multimedia""Reproduciendo a través de Bluetooth""Volumen de la llamada"
-
-
+ "Volumen de la llamada de Bluetooth""Volumen de alarma""Volumen de notificaciones""Volumen"
@@ -762,60 +760,35 @@
"Se ha producido un problema al intentar utilizar la tarjeta SD para el almacenamiento USB.""Conectado por USB""Seleccionar para copiar archivos al/desde el equipo"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "Desactivar almacenamiento USB"
+ "Selecciona esta opción para desactivar el almacenamiento USB."
+ "Desactivar almacenamiento USB"
+ "Antes de desactivar el almacenamiento USB, asegúrate de haber desmontado el host USB. Selecciona \"Desactivar\" para desactivar el almacenamiento USB."
+ "Desactivar"
+ "Cancelar"
+ "Se ha producido un problema al desactivar el almacenamiento USB. Asegúrate de que has desmontado el host USB e inténtalo de nuevo."
+ "Formatear tarjeta SD"
+ "¿Estás seguro de que quieres formatear la tarjeta SD? Se perderán todos los datos de la tarjeta."
+ "Formato""Seleccionar método de introducción de texto""ABCDEFGHIJKLMNOPQRSTUVWXYZ""0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "candidatos"
+ "Preparando tarjeta SD"
+ "Comprobando errores"
+ "Tarjeta SD vacía"
+ "La tarjeta SD está vacía o utiliza un sistema de archivos incompatible."
+ "Tarjeta SD dañada"
+ "La tarjeta SD está dañada. Es posible que sea necesario volver a formatearla."
+ "La tarjeta SD se ha extraído inesperadamente."
+ "Desmonta la tarjeta SD antes de extraerla para evitar la pérdida de datos."
+ "Es seguro extraer la tarjeta SD."
+ "Ya puedes extraer la tarjeta SD de forma segura."
+ "Tarjeta SD extraída"
+ "La tarjeta SD se ha extraído. Inserta una nueva tarjeta SD para aumentar la capacidad de almacenamiento de tu dispositivo."
+ "No se ha encontrado ninguna actividad coincidente."
+ "actualizar estadísticas de uso de componentes"
+ "Permite la modificación de estadísticas recopiladas sobre el uso de componentes. No está destinado al uso por parte de aplicaciones normales."
+
diff --git a/core/res/res/values-fr-rFR/arrays.xml b/core/res/res/values-fr-rFR/arrays.xml
new file mode 100644
index 0000000000000..504ab0f63a686
--- /dev/null
+++ b/core/res/res/values-fr-rFR/arrays.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+ 48850258
+ 2351074
+
+
+
+ 6
+
+
+
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 95e30528a1093..45b8f037fc1d8 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -38,7 +38,7 @@
"L\'ancien code PIN saisi est incorrect.""Le code PUK saisi est incorrect.""Les codes PIN saisis ne correspondent pas."
- "Saisissez un code PIN comptant 4 à 8 chiffres."
+ "Le code PIN doit compter de 4 à 8 chiffres.""Votre carte SIM est verrouillée par code PUK. Saisissez le code PUK pour la déverrouiller.""Saisissez le code PUK2 pour débloquer la carte SIM.""Identifiant d\'appelant entrant"
@@ -95,7 +95,7 @@
"Verrouillage de l\'écran""Éteindre""Arrêt en cours..."
- "Votre téléphone va s\'éteindra."
+ "Votre téléphone va s\'éteindre.""Aucune application récente""Options du téléphone""Verrouillage de l\'écran"
@@ -109,8 +109,8 @@
"Vos messages""Permet de lire et rédiger vos SMS, e-mails et autres messages.""Vos informations personnelles"
- "Accédez directement aux contacts et au calendrier enregistrés sur votre téléphone."
- "Votre position géographique"
+ "Accédez directement aux contacts et à l\'agenda enregistrés sur votre téléphone."
+ "Votre position""Suivre votre position géographique""Communications réseau""Permet à des applications d\'accéder à différentes fonctionnalités du réseau."
@@ -213,7 +213,7 @@
"Lire/écrire dans les ressources appartenant aux diagnostics""Permet à une application de lire et d\'éditer toute ressource appartenant au groupe de diagnostics (par exemple, les fichiers in/dev). Ceci peut affecter la stabilité et la sécurité du système. Cette fonctionnalité est UNIQUEMENT réservée aux diagnostics matériels effectués par le fabricant ou l\'opérateur.""Activer ou désactiver des éléments de l\'application"
- "Permet à une application de modifier l\'état d\'activation/désactivation d\'un élément d\'une autre application. Des applications malveillantes peuvent utiliser cette fonctionnalité pour désactiver des options importantes du téléphone. Soyez prudent en utilisant cette autorisation, car il est possible que certains éléments deviennent instables, incohérents ou inutilisables."
+ "Permet à une application d\'envoyer une notification lors de la réception d\'un message WAP PUSH. Des applications malveillantes peuvent utiliser cette fonctionnalité pour créer de faux accusés de réception de MMS ou remplacer le contenu de toute page Web par des données malveillantes.""Définir les applications préférées""Permet à une application de modifier vos applications préférées. Des applications malveillantes peuvent utiliser cette fonctionnalité pour modifier discrètement les applications en cours d\'exécution, en imitant vos applications existantes afin de récupérer des données personnelles vous concernant.""Modifier les paramètres généraux du système"
@@ -223,7 +223,7 @@
"Modifier la carte des services Google""Permet à une application de modifier la carte des services Google. Les applications normales n\'utilisent pas cette fonctionnalité.""Lancer automatiquement au démarrage"
- "Permet à une application de se lancer dès la fin du démarrage du système. Ceci peut rallonger le temps de démarrage requis par le téléphone. L\'application étant alors constamment en cours d\'exécution, le fonctionnement général du téléphone risque d\'être ralenti."
+ "Permet à une application de se lancer dès la fin du démarrage du système. Cela peut rallonger le temps de démarrage requis par le téléphone. L\'application étant alors constamment en cours d\'exécution, le fonctionnement général du téléphone risque d\'être ralenti.""Envoyer une diffusion persistante""Permet à une application d\'envoyer des diffusions \"persistantes\", qui perdurent après la fin de la diffusion. Des applications malveillantes peuvent ainsi ralentir le téléphone ou le rendre instable en l\'obligeant à utiliser trop de mémoire.""Lire les données des contacts"
@@ -234,17 +234,17 @@
"Permet à une application de modifier les données du propriétaire du téléphone enregistrées sur votre appareil. Des applications malveillantes peuvent utiliser cette fonctionnalité pour effacer ou modifier ces données.""Lire des données du propriétaire""Permet à une application de lire les données du propriétaire du téléphone enregistrées sur votre appareil. Des applications malveillantes peuvent utiliser cette fonctionnalité pour lire ces données."
- "Lire les données du calendrier"
- "Permet à une application de lire tous les événements du calendrier enregistrés sur votre téléphone. Des applications malveillantes peuvent utiliser cette fonctionnalité pour envoyer les événements de votre calendrier à d\'autres personnes."
- "Écrire les données du calendrier"
- "Permet à une application de modifier les événements du calendrier enregistrés sur votre téléphone. Des applications malveillantes peuvent utiliser cette fonctionnalité pour effacer ou modifier les données de votre calendrier."
+ "Lire les données de l\'agenda"
+ "Permet à une application de lire tous les événements de l\'agenda enregistrés sur votre téléphone. Des applications malveillantes peuvent utiliser cette fonctionnalité pour envoyer les événements de votre agenda à d\'autres personnes."
+ "Écrire les données de l\'agenda"
+ "Permet à une application de modifier les événements de l\'agenda enregistrés sur votre téléphone. Des applications malveillantes peuvent utiliser cette fonctionnalité pour effacer ou modifier les données de votre agenda.""Créer des sources géographiques fictives à des fins de test""Permet de créer des sources de position géographique fictives à des fins de test. Des applications malveillantes peuvent utiliser cette fonctionnalité pour remplacer la position géographique et/ou l\'état fournis par des sources réelles comme le GPS ou les fournisseurs d\'accès.""Accéder à des commandes de fournisseur de position géographique supplémentaires""Permet d\'accéder à des commandes de fournisseur de position géographique supplémentaires. Des applications malveillantes peuvent utiliser cette fonctionnalité pour interférer avec l\'utilisation du GPS ou d\'autres sources de positionnement géographique."
- "Position géographique précise (GPS)"
+ "Position géo. OK (GPS)""Permet d\'accéder à des sources de positionnement géographique précises comme le Global Positioning System (GPS) sur le téléphone, lorsque ces services sont disponibles. Des applications malveillantes peuvent utiliser cette fonctionnalité pour déterminer l\'endroit où vous vous trouvez et augmenter la consommation de la batterie de votre téléphone."
- "Position géographique approximative (selon le réseau)"
+ "Position géo. approximative (selon le réseau)""Accéder à des sources de positionnement géographique approximatif (par ex. des bases de données de réseaux mobiles) pour déterminer la position géographique du téléphone, lorsque cette option est disponible. Des applications malveillantes peuvent utiliser cette fonctionnalité pour déterminer approximativement l\'endroit où vous vous trouvez.""Accéder à SurfaceFlinger""Permet à certaines applications d\'utiliser les fonctionnalités SurfaceFlinger de bas niveau."
@@ -262,10 +262,8 @@
"Permet à l\'application de forcer le redémarrage du téléphone.""Monter et démonter des systèmes de fichiers""Permet à l\'application de monter et démonter des systèmes de fichiers pour des périphériques de stockage amovibles."
-
-
-
-
+ "formater le périphérique de stockage externe"
+ "Permet à l\'application de formater le périphérique de stockage amovible.""Contrôler le vibreur""Permet à l\'application de contrôler le vibreur.""Contrôler la lampe de poche"
@@ -280,10 +278,8 @@
"Permet l\'activation/la désactivation des notifications de mises à jour de la position géographique provenant de la radio. Les applications normales n\'utilisent pas cette fonctionnalité.""Accéder aux propriétés d\'enregistrement""Permet un accès en lecture/écriture à des propriétés envoyées par le service d\'inscription. Les applications normales n\'utilisent pas cette fonctionnalité."
-
-
-
-
+ "choisir les gadgets"
+ "Permet à l\'application de signaler au système quels gadgets peuvent être utilisés pour quelle application. Cette autorisation permet aux applications de fournir l\'accès à des données personnelles à d\'autres applications. Cette option n\'est pas utilisée par les applications standard.""Modifier l\'état du téléphone""Permet à une application de contrôler les fonctionnalités téléphoniques de l\'appareil. Une application bénéficiant de cette autorisation peut changer de réseau, éteindre et allumer la radio du téléphone, etc., sans vous en notifier.""Lire l\'état du téléphone"
@@ -312,10 +308,8 @@
"Permet à une application de modifier les paramètres APN (Nom des points d\'accès), comme le proxy ou le port de tout APN.""Modifier la connectivité du réseau""Permet à une application de modifier la connectivité du réseau."
-
-
-
-
+ "modifier le paramètre d\'utilisation des données en arrière-plan"
+ "Permet à une application de modifier le paramètre d\'utilisation des données en arrière-plan.""Afficher l\'état du Wi-Fi""Permet à une application d\'afficher des informations concernant l\'état du Wi-Fi.""Modifier l\'état du Wi-Fi"
@@ -336,16 +330,12 @@
"Permet à une application d\'obtenir des informations sur les flux récemment synchronisés.""Écrire les flux auxquels vous êtes abonné""Permet à une application de modifier vos flux synchronisés actuels. Cette fonctionnalité peut permettre à des applications malveillantes de modifier vos flux synchronisés."
-
-
-
-
-
-
-
-
+ "lire le dictionnaire défini par l\'utilisateur"
+ "Permet à une application de lire tous les mots, noms et expressions que l\'utilisateur a pu enregistrer dans son dictionnaire personnel."
+ "enregistrer dans le dictionnaire défini par l\'utilisateur"
+ "Permet à une application d\'enregistrer de nouveaux mots dans le dictionnaire personnel de l\'utilisateur."
- "Accueil"
+ "Domicile""Mobile""Bureau""Télécopie bureau"
@@ -355,19 +345,19 @@
"Personnalisé"
- "Accueil"
+ "Domicile""Bureau""Autre""Personnalisée"
- "Accueil"
+ "Domicile""Bureau""Autre""Personnalisée"
- "Accueil"
+ "Domicile""Bureau""Autre""Personnalisé"
@@ -387,14 +377,14 @@
"ICQ""Jabber"
- "Saisir le code PIN"
+ "Saisissez le code PIN""Le code PIN est incorrect !"
- "Pour débloquer le clavier, appuyez sur Menu puis sur 0."
+ "Pour débloquer le clavier, appuyez sur \"Menu\" puis sur 0.""Numéro d\'urgence""(Aucun service)""Écran verrouillé"
- "Appuyez sur Menu pour débloquer le téléphone ou appeler un numéro d\'urgence"
- "Appuyez sur Menu pour déverrouiller le téléphone."
+ "Appuyez sur \"Menu\" pour débloquer le téléphone ou appeler un numéro d\'urgence"
+ "Appuyez sur \"Menu\" pour déverrouiller le téléphone.""Dessinez un motif pour déverrouiller le téléphone""Appel d\'urgence""Combinaison correcte !"
@@ -440,12 +430,9 @@
"L\'action FACTORY_TEST est uniquement prise en charge pour les paquets de données installés dans in/system/app.""Impossible de trouver un paquet proposant l\'action FACTORY_TEST.""Redémarrer"
-
-
-
-
-
-
+ "La page \"%s\" affirme :"
+ "JavaScript"
+ "Vous souhaitez quitter cette page ?"\n\n"%s"\n\n"Sélectionnez OK pour continuer ou Annuler pour rester sur la page actuelle.""Confirmer""Voulez-vous que le navigateur se souvienne de ce mot de passe ?""Pas maintenant"
@@ -496,22 +483,38 @@
"demain""dans %d jours"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ "il y a 1 seconde"
+ "il y a %d secondes"
+
+
+ "il y a 1 minute"
+ "il y a %d minutes"
+
+
+ "il y a 1 heure"
+ "Il y a %d heures"
+
+
+ "hier"
+ "Il y a %d jours"
+
+
+ "dans 1 seconde"
+ "dans %d secondes"
+
+
+ "dans 1 minute"
+ "dans %d minutes"
+
+
+ "dans 1 heure"
+ "dans %d heures"
+
+
+ "demain"
+ "dans %d jours"
+ "%s""à %s""en %s"
@@ -553,17 +556,15 @@
"%1$s, %2$s, %3$s""%2$s, %3$s""%1$s, %3$s"
-
-
-
-
+ "%1$s, %2$s"
+ "%1$s, %2$s""%1$s, %2$s"
- "d' 'MMMM' 'yyyy"
- "d' 'MMMM' 'yyyy"
- "d' 'MMM' 'yyyy"
- "d' 'MMM' 'yyyy"
- "h':'mm' 'a"
- "H':'mm"
+ "d' 'MMMM' 'yyyy"
+ "d' 'MMMM' 'yyyy"
+ "d' 'MMM' 'yyyy"
+ "d' 'MMM' 'yyyy"
+ "h':'mm' 'a"
+ "H':'mm""midi""Midi""minuit"
@@ -691,8 +692,7 @@
"Coller""Copier l\'URL""Mode de saisie"
-
-
+ "Ajouter \"%s\" au dictionnaire""Modifier le texte""Espace disponible faible""La mémoire du téléphone commence à être pleine."
@@ -700,8 +700,7 @@
"Annuler""OK""Annuler"
-
-
+ "Attention""ON""OFF""Terminer l\'action avec"
@@ -725,8 +724,7 @@
"Volume des médias""Lecture via Bluetooth""Volume des appels entrants"
-
-
+ "Volume d\'appels entrants sur Bluetooth""Volume de l\'alarme""Volume des notifications""Volume"
@@ -762,60 +760,35 @@
"Un problème est survenu lors de l\'utilisation de votre carte SD en tant que périphérique de stockage USB.""Connecté avec un câble USB""Sélectionnez cette option pour copier des fichiers vers/à partir de votre ordinateur."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "Éteindre le périphérique de stockage USB"
+ "Sélectionner pour éteindre le périphérique de stockage USB"
+ "Éteindre le périphérique de stockage USB"
+ "Avant d\'éteindre le périphérique de stockage USB, assurez-vous d\'avoir désactivé l\'hôte USB. Sélectionnez \"Éteindre\" pour éteindre le périphérique de stockage USB."
+ "Éteindre"
+ "Annuler"
+ "Un problème est survenu lors de la mise hors tension du périphérique de stockage USB. Assurez-vous que l\'hôte USB a bien été désactivé, puis essayez à nouveau."
+ "Formater la carte SD"
+ "Voulez-vous vraiment formater la carte SD ? Toutes les données de cette carte seront perdues."
+ "Format""Sélectionner un mode de saisie""ABCDEFGHIJKLMNOPQRSTUVWXYZ""0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "candidats"
+ "Préparation de la carte SD"
+ "Recherche d\'erreurs"
+ "Carte SD vide"
+ "La carte SD est vide ou utilise un système de fichiers non pris en charge."
+ "Carte SD endommagée"
+ "La carte SD est endommagée. Vous devez peut-être reformater votre carte."
+ "Carte SD retirée inopinément"
+ "Désactiver la carte SD avant de la retirer pour éviter toute perte de données."
+ "La carte SD peut être retirée en toute sécurité"
+ "Vous pouvez désormais retirer la carte SD en toute sécurité."
+ "Carte SD manquante"
+ "La carte SD a été retirée. Insérez une autre carte pour augmenter la capacité de stockage de votre appareil."
+ "Aucune activité correspondante trouvée"
+ "mettre à jour les données statistiques du composant"
+ "Permet de modifier les données statistiques collectées du composant. Cette option n\'est pas utilisée par les applications standard."
+
diff --git a/core/res/res/values-it-rIT/arrays.xml b/core/res/res/values-it-rIT/arrays.xml
new file mode 100644
index 0000000000000..92e5260d3c3db
--- /dev/null
+++ b/core/res/res/values-it-rIT/arrays.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+ 41795888
+ 12480469
+
+
+
+ 6
+
+
+
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 2cf7b43b2cf34..2ac9699c5fb97 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -262,10 +262,8 @@
"Consente all\'applicazione di imporre il riavvio del telefono.""montare e smontare filesystem""Consente montaggio e smontaggio da parte dell\'applicazione dei filesystem degli archivi rimovibili."
-
-
-
-
+ "formatta archivio esterno"
+ "Consente all\'applicazione di formattare l\'archivio rimovibile.""controllare la vibrazione""Consente all\'applicazione di controllare la vibrazione.""controllare il flash"
@@ -280,10 +278,8 @@
"Consente l\'attivazione/disattivazione delle notifiche di aggiornamento della posizione. Da non usare per normali applicazioni.""accedere a proprietà di archiviazione""Consente l\'accesso di lettura/scrittura alle proprietà caricate dal servizio di archiviazione. Da non usare per normali applicazioni."
-
-
-
-
+ "scegliere gadget"
+ "Consente all\'applicazione di indicare al sistema quali gadget possono essere utilizzati e da quale applicazione. Con questa autorizzazione, le applicazioni possono consentire ad altre applicazioni di accedere a dati personali. Da non usare per normali applicazioni.""modificare lo stato del telefono""Consente all\'applicazione di controllare le funzioni telefoniche del dispositivo. Un\'applicazione con questa autorizzazione può cambiare rete, accendere e spegnere il modulo radio del telefono e così via, il tutto automaticamente.""leggere lo stato del telefono"
@@ -312,10 +308,8 @@
"Consente a un\'applicazione di modificare le impostazioni APN, come proxy e porta di qualsiasi APN.""cambiare connettività di rete""Consente a un\'applicazione di modificare lo stato di connettività di rete."
-
-
-
-
+ "cambiare l\'impostazione di utilizzo dei dati in background"
+ "Consente a un\'applicazione di cambiare l\'impostazione di utilizzo dei dati in background.""visualizzare lo stato Wi-Fi""Consente a un\'applicazione di visualizzare le informazioni relative allo stato della connessione Wi-Fi.""cambiare stato Wi-Fi"
@@ -336,14 +330,10 @@
"Consente a un\'applicazione di ottenere dettagli sui feed attualmente sincronizzati.""scrivere feed sottoscritti""Consente la modifica da parte di un\'applicazione dei feed attualmente sincronizzati. Le applicazioni dannose potrebbero essere in grado di modificare i feed sincronizzati."
-
-
-
-
-
-
-
-
+ "leggi dizionario definito dall\'utente"
+ "Consente a un\'applicazione di leggere parole, nomi e frasi private che l\'utente potrebbe aver memorizzato nel dizionario utente."
+ "scrivi nel dizionario definito dall\'utente"
+ "Consente a un\'applicazione di scrivere nuove parole nel dizionario utente.""Casa""Cellulare"
@@ -440,12 +430,9 @@
"L\'azione FACTORY_TEST è supportata soltanto per i pacchetti installati in /system/app.""Nessun pacchetto trovato che fornisca l\'azione FACTORY_TEST.""Riavvia"
-
-
-
-
-
-
+ "La pagina all\'indirizzo %s indica:"
+ "JavaScript"
+ "Uscire da questa pagina?"\n\n"%s"\n\n"Seleziona OK per continuare o Annulla per rimanere nella pagina corrente.""Conferma""Memorizzare la password nel browser?""Non ora"
@@ -496,22 +483,38 @@
"domani""tra %d giorni"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ "1 sec fa"
+ "%d sec fa"
+
+
+ "1 min fa"
+ "%d min fa"
+
+
+ "1 ora fa"
+ "%d ore fa"
+
+
+ "ieri"
+ "%d giorni fa"
+
+
+ "tra 1 sec"
+ "tra %d sec"
+
+
+ "tra 1 min"
+ "tra %d min"
+
+
+ "tra 1 ora"
+ "tra %d ore"
+
+
+ "domani"
+ "tra %d giorni"
+ "il %s""alle %s""nel %s"
@@ -553,17 +556,15 @@
"%1$s, %2$s, %3$s""%2$s, %3$s""%1$s, %3$s"
-
-
-
-
+ "%1$s, %2$s"
+ "%1$s, %2$s""%1$s, %2$s"
- "MMMM' 'd', 'yyyy"
- "d' 'MMMM' 'yyyy"
- "MMM' 'd', 'yyyy"
- "d' 'MMM' 'yyyy"
- "h':'mm' 'a"
- "H':'mm"
+ "MMMM' 'd', 'yyyy"
+ "d' 'MMMM' 'yyyy"
+ "MMM' 'd', 'yyyy"
+ "d' 'MMM' 'yyyy"
+ "h':'mm' 'a"
+ "H':'mm""mezzogiorno""Mezzogiorno""mezzanotte"
@@ -691,8 +692,7 @@
"Incolla""Copia URL""Metodo inserimento"
-
-
+ "Aggiungi \"%s\" al dizionario""Modifica testo""Spazio in esaurimento""Spazio di archiviazione del telefono in esaurimento."
@@ -700,8 +700,7 @@
"Annulla""OK""Annulla"
-
-
+ "Attenzione""ON""OFF""Completa l\'azione con"
@@ -725,8 +724,7 @@
"Volume media""Riproduzione tramite Bluetooth""Volume chiamate"
-
-
+ "Volume chiamate Bluetooth""Volume allarme""Volume notifiche""Volume"
@@ -762,60 +760,35 @@
"Problema di utilizzo della scheda SD per l\'archiviazione USB.""USB collegata""Seleziona per copiare file sul/dal computer in uso."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "Disattiva archivio USB"
+ "Seleziona per disattivare archivio USB."
+ "Disattiva archivio USB"
+ "Prima di disattivare l\'archivio USB, verifica di aver smontato l\'host USB. A tale scopo, seleziona \"Disattiva\"."
+ "Disattiva"
+ "Annulla"
+ "Abbiamo riscontrato un problema disattivando l\'archivio USB. Verifica di aver smontato l\'host USB e riprova."
+ "Formatta scheda SD"
+ "Formattare la scheda SD? Tutti i dati sulla scheda verranno persi."
+ "Formatta""Seleziona metodo di inserimento""ABCDEFGHIJKLMNOPQRSTUVWXYZ""0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "candidati"
+ "Preparazione scheda SD"
+ "Ricerca errori"
+ "Scheda SD vuota"
+ "La scheda SD è vuota o utilizza un file system non supportato."
+ "Scheda SD danneggiata"
+ "La scheda SD è danneggiata. Potrebbe essere necessario riformattarla."
+ "Rimozione imprevista della scheda SD"
+ "Smonta scheda SD prima della rimozione per evitare la perdita di dati."
+ "È possibile rimuovere la scheda SD"
+ "È ora possibile rimuovere la scheda SD in modo sicuro."
+ "Scheda SD rimossa"
+ "Scheda SD rimossa. Inserisci una nuova scheda SD per aumentare la memoria del dispositivo."
+ "Nessuna attività corrispondente trovata"
+ "aggiornare le statistiche di utilizzo dei componenti"
+ "Consente la modifica delle statistiche di utilizzo dei componenti raccolte. Da non usare per normali applicazioni."
+
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 24e3cb6e7cad1..1fa3eee762a1f 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -21,10 +21,10 @@
"GB""TB""PB"
- "<無題>"
+ "<新規>""..."
- "(電話番号なし)"
- "(不明)"
+ "(電話番号なし)"
+ "(名前)""ボイスメール""MSISDN1""接続に問題があるか、MMIコードが正しくありません。"
@@ -48,11 +48,11 @@
"発信制限""パスワードの変更""PINの変更"
- "デフォルトでは発信者番号は非通知です。次の通話でも非通知です。"
- "デフォルトでは発信者番号は非通知ですが、次の通話では通知されます。"
- "デフォルトでは発信者番号は通知されますが、次の通話では非通知です。"
- "デフォルトでは発信者番号は通知されます。次の通話でも通知されます。"
- "サービスは提供されません。"
+ "既定: 発信者番号非通知、次の発信: 非通知"
+ "既定: 発信者番号非通知、次の発信: 通知"
+ "既定: 発信者番号通知、次の発信: 非通知"
+ "既定: 発信者番号通知、次の発信: 通知"
+ "提供可能なサービスがありません。""発信者番号の設定は変更できません。""音声""データ"
@@ -90,15 +90,15 @@
"自分""携帯電話オプション""マナーモード"
- "ワイヤレスをオン"
- "ワイヤレスオフ"
+ "ワイヤレス接続をONにする"
+ "ワイヤレス接続をOFFにする""画面をロック""電源オフ""シャットダウン中...""携帯電話の電源をオフにします。""最近使ったアプリケーションはありません。""携帯電話オプション"
- "画面をロック"
+ "画面ロック""電源オフ""マナーモード""音声オフ"
@@ -109,27 +109,27 @@
"送受信したメッセージ""SMS、メールなどのメッセージの読み書き""個人情報"
- "携帯電話に保存した連絡先とカレンダーに直接アクセス"
+ "端末の連絡先とカレンダーに直接アクセス""現在地"
- "現在地を監視"
+ "現在地を追跡""ネットワーク通信""ネットワークのさまざまな機能へのアクセスをアプリケーションに許可します。""Googleアカウント""利用可能なGoogleアカウントへのアクセス""ハードウェアの制御""携帯電話のハードウェアに直接アクセスします。"
- "電話の発信"
+ "電話/通話""通話の監視、記録、処理""システムツール""システムの低レベルのアクセスと制御""開発ツール""アプリケーションのデベロッパーにのみ必要な機能です。"
- "ステータスバーを無効にしたり変更する"
- "ステータスバーの無効化や、システムアイコンの追加や削除をアプリケーションに許可します。"
+ "ステータスバーの無効化や変更"
+ "ステータスバーの無効化やシステムアイコンの追加や削除をアプリケーションに許可します。""ステータスバーの拡大/縮小""ステータスバーの拡大や縮小をアプリケーションに許可します。""発信の傍受"
- "発信を処理して、ダイヤルする番号を変更することをアプリケーションに許可します。悪意のあるアプリケーションが発信を監視、転送、阻止する恐れがあります。"
+ "通話の発信とダイヤルする番号の変更とをアプリケーションに許可します。悪意のあるアプリケーションが発信を監視、転送、阻止する恐れがあります。""SMSの受信""SMSメッセージの受信と処理をアプリケーションに許可します。悪意のあるアプリケーションがメッセージを監視したり、表示せずに削除する恐れがあります。""MMSの受信"
@@ -137,7 +137,7 @@
"SMSメッセージの送信""SMSメッセージの送信をアプリケーションに許可します。悪意のあるアプリケーションが確認なしでメッセージを送信し、料金が発生する恐れがあります。""SMSやMMSの読み取り"
- "携帯電話またはSIMカードに保存したSMSメッセージの読み取りをアプリケーションに許可します。悪意のあるアプリケーションが機密メッセージを読み取る恐れがあります。"
+ "携帯電話やSIMカードに保存したSMSメッセージの読み取りをアプリケーションに許可します。悪意のあるアプリケーションが機密メッセージを読み取る恐れがあります。""SMSやMMSの編集""携帯電話やSIMカードに保存したSMSメッセージへの書き込みをアプリケーションに許可します。悪意のあるアプリケーションがメッセージを削除する恐れがあります。""WAPの受信"
@@ -147,9 +147,9 @@
"実行中のアプリケーションの順序の変更""タスクをフォアグラウンドやバックグラウンドに移動することをアプリケーションに許可します。悪意のあるアプリケーションが優先されて、コントロールできなくなる恐れがあります。""アプリケーションのデバッグを有効にする"
- "別のアプリケーションをデバッグモードにすることをアプリケーションに許可します。これにより悪意のあるアプリケーションが、別のアプリケーションを終了させる恐れがあります。"
+ "別のアプリケーションをデバッグモードにすることをアプリケーションに許可します。悪意のあるアプリケーションが別のアプリケーションを終了させる恐れがあります。""UI設定の変更"
- "ロケールや全体のフォントのサイズなど、現在の設定の変更をアプリケーションに許可します。"
+ "地域/言語やフォントのサイズなど、現在の設定の変更をアプリケーションに許可します。""他のアプリケーションの再起動""他のアプリケーションの強制的な再起動をアプリケーションに許可します。""停止の阻止"
@@ -157,47 +157,47 @@
"アプリケーションの強制終了""フォアグラウンドで実行されている操作を強制終了して戻ることをアプリケーションに許可します。通常のアプリケーションではまったく必要ありません。""システムの内部状態の取得"
- "システムの内部状態の取得をアプリケーションに許可します。悪意のあるアプリケーションが、通常は必要のない、広範囲にわたる非公開の機密情報を取得する恐れがあります。"
+ "システムの内部状態の取得をアプリケーションに許可します。悪意のあるアプリケーションが、通常は必要としない広範囲にわたる非公開の機密情報を取得する恐れがあります。""低レベルサービスの公開""独自の低レベルのシステムサービスを公開することをアプリケーションに許可します。悪意のあるアプリケーションがシステムを乗っ取って、データの盗用や破壊をする恐れがあります。""起動中のすべてのアプリケーションの監視と制御""システムが起動する操作の監視と制御をアプリケーションに許可します。悪意のあるアプリケーションがシステムを完全に破壊する恐れがあります。この許可は開発にのみ必要で、携帯電話の通常の使用にはまったく必要ありません。""パッケージ削除ブロードキャストの送信"
- "アプリケーションパッケージの削除通知を配信することをアプリケーションに許可します。これにより悪意のあるアプリケーションが、他の実行中のアプリケーションを強制終了する恐れがあります。"
+ "アプリケーションパッケージの削除の通知を配信することをアプリケーションに許可します。悪意のあるアプリケーションが他の実行中のアプリケーションを強制終了する恐れがあります。""SMS受信ブロードキャストの送信"
- "SMSメッセージの受信通知の配信をアプリケーションに許可します。これにより悪意のあるアプリケーションが、受信SMSメッセージを偽造する恐れがあります。"
+ "SMSメッセージの受信通知の配信をアプリケーションに許可します。悪意のあるアプリケーションが受信SMSメッセージを偽造する恐れがあります。""WAP-PUSH受信ブロードキャストの送信"
- "WAP PUSHメッセージの受信通知を配信することをアプリケーションに許可します。これにより悪意のあるアプリケーションが、MMS受信メッセージを偽造したり、ウェブページのコンテンツを密かに改ざんしたりする恐れがあります。"
+ "WAP PUSHメッセージの受信の通知を配信することをアプリケーションに許可します。悪意のあるアプリケーションがMMS受信メッセージを偽造したり、ウェブページのコンテンツを密かに改ざんする恐れがあります。""実行中のプロセスの数を制限""実行するプロセス数の上限の制御をアプリケーションに許可します。通常のアプリケーションにはまったく必要ありません。""バックグラウンドアプリケーションをすべて終了する""バックグラウンドになり次第必ず操作を終了させるかどうかの制御をアプリケーションに許可します。通常のアプリケーションではまったく必要ありません。""システムアップデートの自動インストール"
- "保留中のシステムアップデートに関する通知を受信してインストールを開始することをアプリケーションに許可します。これにより悪意のあるアプリケーションが、許可なく更新を行ってシステムを破壊したり、更新処理を妨害する恐れがあります。"
- "バッテリ統計の変更"
- "収集されたバッテリの統計の変更を許可します。通常のアプリケーションでは使用しません。"
+ "保留中のシステムアップデートに関する通知の受信とインストールの開始をアプリケーションに許可します。悪意のあるアプリケーションが許可なく更新を行ってシステムを破壊したり、更新処理を妨害する恐れがあります。"
+ "電池統計情報の変国"
+ "収集した電池統計情報の変更を許可します。通常のアプリケーションでは使用しません。""未許可のウィンドウの表示""内部システムのユーザーインターフェースで使用するためのウィンドウ作成を許可します。通常のアプリケーションでは使用しません。""システムレベルの警告の表示"
- "システムの警告ウィンドウをアプリケーションで表示できるようにします。悪意のあるアプリケーションが携帯電話の画面全体を偽装する恐れがあります。"
- "アニメーション全般の速度の変更"
+ "システムの警告ウィンドウの表示をアプリケーションに許可します。悪意のあるアプリケーションが携帯電話の画面全体を偽装する恐れがあります。"
+ "アニメーションのプリセット速度の変更""いつでもアニメーション全般の速度を変更する (アニメーションを速くまたは遅くする) ことをアプリケーションに許可します。""アプリケーショントークンの管理""通常のZ-orderingを回避して、独自のトークンを作成、管理することをアプリケーションに許可します。通常のアプリケーションではまったく必要ありません。""キーを押してボタンをコントロール""入力イベント (キーを押すなど) を別のアプリケーションに伝えることをアプリケーションに許可します。これにより悪意のあるアプリケーションが、携帯電話を乗っ取る恐れがあります。""入力や操作の記録"
- "別のアプリケーションへの入力 (パスワードなど) でもキー入力を監視することをアプリケーションに許可します。通常のアプリケーションではまったく必要ありません。"
+ "別のアプリケーションへの入力(パスワードなど)でもキー入力を監視することをアプリケーションに許可します。通常のアプリケーションではまったく必要ありません。""入力方法に関連付ける""入力方法のトップレベルインターフェースに関連付けることを所有者に許可します。通常のアプリケーションにはまったく必要ありません。""画面の向きの変更""いつでも画面の回転を変更することをアプリケーションに許可します。通常のアプリケーションにはまったく必要ありません。""Linuxのシグナルをアプリケーションに送信"
- "すべての永続プロセスに特定の信号を送信するリクエストをアプリケーションに許可します。"
+ "受信した電波を継続プロセスに送信することをアプリケーションに許可します。""アプリケーションを常に実行する""自身を部分的に永続させて、他のアプリケーション用にはその領域をシステムに使わせないようにすることをアプリケーションに許可します。""アプリケーションの削除"
- "Androidパッケージの削除をアプリケーションに許可します。これにより悪意のあるアプリケーションが、重要なアプリケーションを削除する恐れがあります。"
+ "Androidパッケージの削除をアプリケーションに許可します。悪意のあるアプリケーションが、重要なアプリケーションを削除する恐れがあります。""他のアプリケーションのデータを削除""ユーザーデータの消去をアプリケーションに許可します。""他のアプリケーションのキャッシュを削除"
@@ -205,46 +205,46 @@
"アプリケーションのメモリ容量の計測""アプリケーションのコード、データ、キャッシュのサイズを取得することを許可します。""アプリケーションを直接インストール"
- "Androidパッケージを新たにインストールまたは更新することをアプリケーションに許可します。これにより悪意のあるアプリケーションが、勝手に強力な権限を持つ新しいアプリケーションを追加する恐れがあります。"
+ "Androidパッケージのインストール/更新をアプリケーションに許可します。悪意のあるアプリケーションが、勝手に強力な権限を持つ新しいアプリケーションを追加する恐れがあります。""アプリケーションキャッシュデータの削除""アプリケーションのキャッシュディレクトリからファイルを削除して携帯電話のメモリを解放することをアプリケーションに許可します。通常、アクセスはシステムプロセスのみに制限されます。""システムログファイルの読み取り""システムのさまざまなログファイルの読み取りをアプリケーションに許可します。これにより携帯電話の使用状況に関する全般情報が取得されますが、個人情報や非公開情報が含まれることはありません。""diagが所有するリソースの読み書き"
- "diagグループが所有するリソース (/dev内のファイルなど) への読み書きをアプリケーションに許可します。これはシステムの安定性とセキュリティに影響する恐れがあります。メーカーまたはオペレータによるハードウェア固有の診断以外には使用しないでください。"
+ "diagグループが所有するリソース(例:/dev内のファイル)への読み書きをアプリケーションに許可します。システムの安定性とセキュリティに影響する恐れがあります。メーカー/オペレーターによるハードウェア固有の診断以外には使用しないでください。""アプリケーションのコンポーネントを有効/無効にする""別アプリケーションのコンポーネントの有効/無効を変更することをアプリケーションに許可します。これにより悪意のあるアプリケーションが、携帯電話の重要な機能を無効にする恐れがあります。アプリケーションコンポーネントが利用できない、整合性が取れない、または不安定な状態になる恐れがあるので、許可には注意が必要です。""優先アプリケーションの設定"
- "優先アプリケーションを変更することをアプリケーションに許可します。これにより悪意のあるアプリケーションが、実行中のアプリケーションを密かに変更し、既存のアプリケーションになりすまして、非公開データを収集する恐れがあります。"
- "システム全般の設定の変更"
+ "優先アプリケーションを変更することをアプリケーションに許可します。悪意のあるアプリケーションが実行中のアプリケーションを密かに変更し、既存のアプリケーションになりすまして非公開データを収集する恐れがあります。"
+ "システムの全般設定の変更""システム設定データの変更をアプリケーションに許可します。悪意のあるアプリケーションがシステム設定を破壊する恐れがあります。""システムのセキュリティ設定の変更""システムのセキュリティ設定の変更をアプリケーションに許可します。通常のアプリケーションでは使用しません。""Googleサービスの地図の変更""Googleサービスマップの変更をアプリケーションに許可します。通常のアプリケーションでは使用しません。""起動時に自動的に開始"
- "システムの起動直後に自動的に起動することをアプリケーションに許可します。これにより携帯電話の起動に時間がかかるようになります。また、アプリケーションが常に実行中となるため、携帯電話の全体的な動作が遅くなります。"
+ "システムの起動後に自動的に起動することをアプリケーションに許可します。携帯電話の起動に時間がかかるようになり、アプリケーションが常に実行されるために携帯電話の全体的な動作が遅くなります。""stickyブロードキャストの配信""配信が終了してもメモリに残るようなstickyブロードキャストをアプリケーションに許可します。悪意のあるアプリケーションがメモリを使いすぎて、携帯電話の動作が遅くなったり、不安定になる恐れがあります。""連絡先データの読み取り"
- "携帯電話に保存した連絡先 (アドレス) データをアプリケーションですべて読み取れるようにします。これにより悪意のあるアプリケーションが、そのデータを他人に送信する恐れがあります。"
+ "端末に保存した連絡先(アドレス)データの読み取りをアプリケーションに許可します。悪意のあるアプリケーションがデータを他人に送信する恐れがあります。""連絡先データの書き込み"
- "携帯電話に保存した連絡先 (アドレス) データの変更をアプリケーションに許可します。これにより悪意のあるアプリケーションが、連絡先データを消去や変更する恐れがあります。"
+ "端末に保存した連絡先(アドレス)データの変更をアプリケーションに許可します。悪意のあるアプリケーションが連絡先データを消去/変更する恐れがあります。""所有者データの書き込み"
- "携帯電話に保存した所有者のデータの変更をアプリケーションに許可します。これにより悪意のあるアプリケーションが、所有者のデータを消去または変更する恐れがあります。"
+ "端末に保存した所有者のデータの変更をアプリケーションに許可します。悪意のあるアプリケーションが所有者のデータを消去/変更する恐れがあります。""所有者データの読み取り"
- "携帯電話に保存した所有者データの読み取りをアプリケーションに許可します。これにより悪意のあるアプリケーションが、所有者データを読み取る恐れがあります。"
+ "携帯電話に保存した所有者データの読み取りをアプリケーションに許可します。悪意のあるアプリケーションが所有者データを読み取る恐れがあります。""カレンダーデータの読み取り"
- "携帯電話に保存したカレンダーのイベントをアプリケーションですべて読み取れるようにします。悪意のあるアプリケーションではこれを利用して、カレンダーのイベントを他人に送信できます。"
+ "端末に保存したカレンダーの予定の読み取りをアプリケーションに許可します。悪意のあるアプリケーションがカレンダーの予定を他人に送信する恐れがあります。""カレンダーデータの書き込み"
- "携帯電話に保存したカレンダーイベントの変更をアプリケーションに許可します。これにより悪意のあるアプリケーションが、カレンダーデータを消去や変更する恐れがあります。"
+ "端末に保存したカレンダーの予定の変更をアプリケーションに許可します。悪意のあるアプリケーションが、カレンダーデータを消去/変更する恐れがあります。""仮の位置情報でテスト""テスト用に仮の位置情報源を作成します。これにより悪意のあるアプリケーションが、GPS、ネットワークプロバイダなどから返される本当の位置情報や状況を改ざんする恐れがあります。""位置情報プロバイダのその他のコマンドへのアクセス"
- "位置情報プロバイダのその他のコマンドにアクセスします。これにより悪意のあるアプリケーションが、GPSなどの位置情報源の動作を妨害する恐れがあります。"
- "正確な (GPS) 位置"
- "GPSなど、携帯電話の正確な位置情報源に、可能な場合アクセスします。これにより悪意のあるアプリケーションが、ユーザーの現在地を特定したり、バッテリの消費を増やしたりする恐れがあります。"
- "おおよその (ネットワーク情報による) 位置"
+ "位置情報提供元の追加コマンドにアクセスします。悪意のあるアプリケーションがGPSなどの位置提供の動作を妨害する恐れがあります。"
+ "精細な位置情報(GPS)"
+ "GPSなど携帯電話の位置情報にアクセスします(可能な場合)。今いる場所が悪意のあるアプリケーションに検出されたり、バッテリーの消費が増える恐れがあります。"
+ "おおよその位置情報(ネットワーク基地局)""セルラーネットワークデータベースなど、携帯電話のおおよその位置を特定する情報源が利用可能な場合にアクセスします。これにより悪意のあるアプリケーションが、ユーザーのおおよその位置を特定できる恐れがあります。""SurfaceFlingerへのアクセス""SurfaceFlingerの低レベルの機能の使用をアプリケーションに許可します。"
@@ -255,41 +255,37 @@
"録音""オーディオ録音パスへのアクセスをアプリケーションに許可します。""写真の撮影"
- "カメラで写真を撮ることをアプリケーションに許可します。これによりアプリケーションは、カメラに写る画像をいつでも収集できます。"
- "携帯電話を永久に使用できなくする"
+ "カメラでの写真撮影をアプリケーションに許可します。アプリケーションはカメラから画像をいつでも収集できます。"
+ "端末を永続的に無効にする""携帯電話全体を永続的に無効にすることをアプリケーションに許可します。この許可は非常に危険です。"
- "携帯電話の再起動"
- "携帯電話の強制的な再起動をアプリケーションに許可します。"
+ "端末の再起動"
+ "端末の強制的な再起動をアプリケーションに許可します。""ファイルシステムのマウントとマウント解除""リムーバブルメモリのファイルシステムのマウントとマウント解除をアプリケーションに許可します。"
-
-
-
-
- "バイブレータの制御"
- "バイブレータのコントロールをアプリケーションに許可します。"
+ "外部ストレージのフォーマット"
+ "アプリケーションがリムーバブルストレージをフォーマットすることを許可します。"
+ "バイブレーション制御"
+ "バイブレーションの制御をアプリケーションに許可します。""ライトのコントロール""ライトの制御をアプリケーションに許可します。""ハードウェアのテスト""ハードウェアのテストのためにさまざまな周辺機器を制御することをアプリケーションに許可します。"
- "電話番号に直接発信"
- "電話を自動でかけることをアプリケーションに許可します。悪意のあるアプリケーションが予想外の電話をかけて、料金が発生する恐れがあります。緊急電話番号への通話は許可しません。"
- "あらゆる電話番号に直接発信"
- "緊急電話を含めてあらゆる電話番号に自動発信することをアプリケーションに許可します。悪意のあるアプリケーションが緊急サービスに不要かつ不正な通話をする恐れがあります。"
- "位置の更新通知の制御"
+ "電話番号発信"
+ "アプリケーションが電話を自動発信することを許可します。悪意のあるアプリケーションが意図しない電話をかけて料金が発生する恐れがあります。緊急呼への発信は許可しません。"
+ "電話番号発信"
+ "緊急呼を含めあらゆる電話番号に自動発信することをアプリケーションに許可します。悪意のあるアプリケーションが緊急サービスに不正な通報をする恐れがあります。"
+ "位置情報の更新通知""無線通信からの位置更新通知を有効/無効にすることを許可します。通常のアプリケーションでは使用しません。""チェックインプロパティへのアクセス""チェックインサービスがアップロードしたプロパティへの読み書きを許可します。通常のアプリケーションでは使用しません。"
-
-
-
-
- "携帯電話の状態の変更"
- "携帯端末の電話機能のコントロールをアプリケーションに許可します。この許可を受けたアプリケーションは、ネットワークの切り替え、携帯電話の無線通信のオン/オフなどを通知せずに行うことができます。"
- "携帯電話の状態の読み取り"
- "携帯端末の電話機能へのアクセスをアプリケーションに許可します。これを許可されたアプリケーションは、この携帯電話の電話番号、通話中かどうか、通話相手の電話番号などを特定できます。"
- "携帯電話をスリープ状態にしない"
- "携帯電話をスリープ状態にしないようにすることをアプリケーションに許可します。"
+ "ガジェットの選択"
+ "特定のアプリケーションで使用可能なガジェットをシステムに指定することをアプリケーションに許可します。この許可を受けたアプリケーションは、他のアプリケーションに個人データへのアクセスを許可することができます。通常のアプリケーションでは使用しません。"
+ "端末ステータスの変更"
+ "端末の電話機能のコントロールをアプリケーションに許可します。アプリケーションは、ネットワークの切り替え、携帯電話の無線通信のオン/オフなどを通知せずに行うことができます。"
+ "端末ステータスの読み取り"
+ "端末の電話機能へのアクセスをアプリケーションに許可します。アプリケーションは、この携帯電話の電話番号、通話中かどうか、通話相手の電話番号などを特定できます。"
+ "端末のスリープを無効にする"
+ "端末のスリープを無効にすることをアプリケーションに許可します。""携帯電話の電源のオン/オフ""携帯電話の電源のオン/オフをアプリケーションに許可します。""出荷時試験モードでの実行"
@@ -298,82 +294,76 @@
"システムの壁紙の設定をアプリケーションに許可します。""壁紙サイズのヒントの設定""システムの壁紙サイズのヒントの設定をアプリケーションに許可します。"
- "システムを出荷時のデフォルトにリセット"
+ "システムを出荷時設定にリセット""データ、設定、インストールしたアプリケーションをすべて消去して、完全に出荷時の設定にシステムをリセットすることをアプリケーションに許可します。""タイムゾーンの設定"
- "携帯電話のタイムゾーンの変更をアプリケーションに許可します。"
+ "端末のタイムゾーンの変更をアプリケーションに許可します。""既知のアカウントの取得"
- "携帯端末内にあるアカウントのリストの取得をアプリケーションに許可します。"
+ "端末内にあるアカウントのリストの取得をアプリケーションに許可します。""ネットワーク状態の表示""すべてのネットワーク状態の表示をアプリケーションに許可します。"
- "インターネットへの完全なアクセス権"
+ "完全なインターネットアクセス""ネットワークソケットの作成をアプリケーションに許可します。""アクセスポイント名設定の書き込み""APNのプロキシやポートなどのAPN設定の変更をアプリケーションに許可します。""ネットワーク接続の変更""ネットワークの接続状態の変更をアプリケーションに許可します。"
-
-
-
-
+ "バックグラウンドデータ使用の設定の変更"
+ "バックグラウンドデータ使用の設定の変更をアプリケーションに許可します。""Wi-Fi状態の表示""Wi-Fi状態に関する情報の表示をアプリケーションに許可します。""Wi-Fi状態の変更""Wi-Fiアクセスポイントへの接続や接続の切断、設定されたWi-Fiネットワークの変更をアプリケーションに許可します。""Bluetoothの管理"
- "ローカルのBluetooth電話を設定し、リモートデバイスを検出してペアに設定することをアプリケーションに許可します。"
+ "このBluetooth端末の設定、およびリモート端末を検出してペアに設定することをアプリケーションに許可します。""Bluetooth接続の作成"
- "ローカルBluetooth電話の設定を表示し、デバイスをペアとして設定して接続を承認することをアプリケーションに許可します。"
+ "このBluetooth端末の設定表示、および別の端末をペアとして設定し接続を承認することをアプリケーションに許可します。""キーロックを無効にする""キーロックや関連するパスワードセキュリティを無効にすることをアプリケーションに許可します。正当な利用の例では、かかってきた電話を受信する際にキーロックを無効にし、通話の終了時にキーロックを有効にし直します。""同期設定の読み取り"
- "連絡先の同期が有効かどうかなど、同期設定の読み取りをアプリケーションに許可します。"
+ "連絡先の同期の有効/無効など、同期設定の読み取りをアプリケーションに許可します。""同期設定の書き込み"
- "連絡先の同期が有効かどうかなど、同期設定の変更をアプリケーションに許可します。"
+ "連絡先の同期の有効/無効など、同期設定の変更をアプリケーションに許可します。""同期統計の読み取り"
- "同期状態 (同期履歴など) の読み取りをアプリケーションに許可します。"
+ "同期状態(同期履歴など)の読み取りをアプリケーションに許可します。""登録したフィードの読み取り""現在同期しているフィードの詳細の取得をアプリケーションに許可します。""登録したフィードの書き込み""現在同期しているフィードの変更をアプリケーションに許可します。悪意のあるアプリケーションが同期フィードを変更する恐れがあります。"
-
-
-
-
-
-
-
-
+ "ユーザー定義辞書の読み込み"
+ "アプリケーションがユーザー辞書に登録されている個人的な語句や名前を読み込むことを許可します。"
+ "ユーザー定義辞書への書き込み"
+ "アプリケーションがユーザー辞書に新しい語句を書き込むことを許可します。""自宅""携帯"
- "勤務先"
- "勤務先FAX"
- "自宅FAX"
+ "仕事"
+ "FAX(仕事)"
+ "FAX(自宅)""ポケベル""その他""カスタム""自宅"
- "勤務先"
+ "仕事""その他""カスタム""自宅"
- "勤務先"
+ "仕事""その他""カスタム""自宅"
- "勤務先"
+ "仕事""その他""カスタム"
- "勤務先"
+ "仕事""その他""カスタム"
@@ -389,31 +379,31 @@
"PINコードを入力""PINコードが正しくありません。"
- "ロックを解除するには、Menu、0キーの順に押します。"
- "緊急電話番号"
- "(サービスなし)"
- "画面がロックされています。"
- "Menuキーを押してロックを解除するか、緊急電話をかけます。"
- "ロックを解除するにはMenuキーを押します。"
+ "ロックを解除するにはMENU、0キーの順に押します。"
+ "緊急呼番号"
+ "(サービス登録なし)"
+ "画面ロック中"
+ "MENUキーでロック解除(または緊急呼)"
+ "MENUキーでロック解除""ロックを解除するパターンを入力"
- "緊急電話"
+ "緊急呼""一致しました"
- "もう一度試してください"
+ "やり直してください""充電中 (%d%%)""充電してください。"
- "SIMカードがありません。"
- "SIMカードが携帯電話に挿入されていません。"
+ "SIMカードが挿入されていません"
+ "SIMカードが挿入されていません""SIMカードを挿入してください。""ネットワークがロックされました""SIMカードはPUKでロックされています。""お客様サポートにお問い合わせください。""SIMカードはロックされています。"
- "SIMカードのロックを解除中..."
+ "SIMカードのロック解除中...""ロック解除のパターンは%d回とも正しく指定されていません。"\n\n"%d秒後にもう一度指定してください。""指定したパターンは%d回とも正しくありません。あと%d回指定に失敗すると、携帯電話のロックの解除にGoogleへのログインが必要になります。"\n\n"%d秒後にもう一度指定してください。"
- "%d秒後にもう一度試してください。"
+ "%d秒後にやり直してください。""パターンを忘れた場合"
- "パターンの指定回数が多すぎる"
+ "パターンのエラーが多すぎます""ロックを解除するには、"\n"Googleアカウントでログインしてください。""ユーザー名 (メール)""パスワード"
@@ -434,27 +424,24 @@
"充電中...""充電してください"
- "バッテリの残量が少なくなっています。"
+ "電池が残り少なくなっています:""残り%d%%未満""出荷時試験が失敗""FACTORY_TEST操作は、/system/appにインストールされたパッケージのみが対象です。""FACTORY_TEST操作を行うパッケージは見つかりませんでした。""再起動"
-
-
-
-
-
-
+ "ページ「%s」の記述:"
+ "JavaScript"
+ "このページから移動しますか?"\n\n"%s"\n\n"続行する場合は[OK]、今のページに残る場合は[キャンセル]を選択してください。""確認""このパスワードをブラウザで保存しますか?""今は保存しない""保存""保存しない""このページへのアクセスは許可されていません。"
- "テキストがクリップボードにコピーされました。"
+ "テキストをクリップボードにコピーしました。""その他"
- "Menu+"
+ "MENU+""Space""Enter""Del"
@@ -496,22 +483,38 @@
"明日""%d日後"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ "1秒前"
+ "%d秒前"
+
+
+ "1分前"
+ "%d分後"
+
+
+ "1時間前"
+ "%d時間前"
+
+
+ "昨日"
+ "%d日前"
+
+
+ "1秒後"
+ "%d秒後"
+
+
+ "1分後"
+ "%d分後"
+
+
+ "1時間後"
+ "%d時間後"
+
+
+ "明日"
+ "%d日後"
+ "%s""%s""%s年"
@@ -527,14 +530,14 @@
"週間""年""年"
- "日曜"
- "月曜"
- "火曜"
- "水曜"
- "木曜"
- "金曜"
- "土曜"
- "平日の毎日 (月~金)"
+ "日曜日"
+ "月曜日"
+ "火曜日"
+ "水曜日"
+ "木曜日"
+ "金曜日"
+ "土曜日"
+ "平日(月~金)""毎日""毎週%s""毎月"
@@ -545,25 +548,23 @@
"AM""PM""%Y/%m/%d"
- "%2$s (%1$s) %3$s~%5$s (%4$s) %6$s"
- "%2$s (%1$s)~%5$s (%4$s)"
+ "%2$s%1$s%3$s~%5$s%4$s%6$s"
+ "%2$s%1$s~%5$s%4$s""%2$s%3$s~%5$s%6$s""%2$s~%5$s""%1$s~%2$s"
- "%3$s (%2$s) %1$s"
- "%3$s (%2$s)"
+ "%3$s%2$s%1$s"
+ "%3$s%2$s""%3$s、%1$s"
-
-
-
-
+ "%1$s、%2$s"
+ "%1$s、%2$s""%2$s、%1$s"
- "yyyy'\'\'年\'\''MMMMd'\'\'日\'\''"
- "yyyy'\'\'年\'\''MMMMd'\'\'日\'\''"
- "yyyy'\'\'年\'\''MMMd'\'\'日\'\''"
- "yyyy'\'\'年\'\''MMMd'\'\'日\'\''"
- "h':'mm' 'a"
- "H':'mm"
+ "yyyy'/'MMMM'/'d"
+ "yyyy'年'MMMM'月'd'日'"
+ "MMM'/'d' 'yyyy'年'"
+ "d'/'MMM'/'yyyy"
+ "h':'mm' 'a"
+ "H':'mm""正午""正午""午前0時"
@@ -576,66 +577,66 @@
"%H:%M:%S"
- "%Y年%B%-d日%H:%M:%S"
- "%2$s%3$s日~%7$s%8$s日"
- "%2$s%3$s日 (%1$s)~%7$s%8$s日 (%6$s)"
- "%9$s年%2$s%3$s日~%7$s%8$s日"
- "%9$s年%2$s%3$s日 (%1$s)~%7$s%8$s日 (%6$s)"
- "%2$s%3$s日%5$s~%7$s%8$s日%10$s"
- "%2$s%3$s日 (%1$s) %5$s~%7$s%8$s日 (%6$s) %10$s"
- "%4$s年%2$s%3$s日%5$s~%9$s年%7$s%8$s日%10$s"
- "%4$s年%2$s%3$s日 (%1$s) %5$s~%9$s年%7$s%8$s日 (%6$s) %10$s"
+ "%Y/%B/%-d%H:%M:%S"
+ "%2$s月%3$s日~%7$s月%8$s日"
+ "%2$s/%3$s%1$s~%7$s/%8$s%6$s"
+ "%9$s年%2$s月%3$s日~%7$s月%8$s日"
+ "%9$s/%2$s/%3$s%1$s~%7$s/%8$s%6$s"
+ "%2$s月%3$s日%5$s~%7$s月%8$s日%10$s"
+ "%2$s/%3$s%1$s%5$s~%7$s/%8$s%6$s%10$s"
+ "%4$s年%2$s月%3$s日 %5$s~%9$s年%7$s月%8$s日 %10$s"
+ "%4$s/%2$s/%3$s%1$s%5$s~%9$s/%7$s/%8$s%6$s%10$s""%2$s/%3$s~%7$s/%8$s"
- "%2$s/%3$s (%1$s)~%7$s/%8$s (%6$s)"
+ "%2$s/%3$s%1$s~%7$s/%8$s%6$s""%4$s/%2$s/%3$s~%9$s/%7$s/%8$s"
- "%4$s/%2$s/%3$s (%1$s)~%9$s/%7$s/%8$s (%6$s)"
+ "%4$s/%2$s/%3$s%1$s~%9$s/%7$s/%8$s%6$s""%2$s/%3$s%5$s~%7$s/%8$s%10$s"
- "%2$s/%3$s (%1$s) %5$s~%7$s/%8$s (%6$s) %10$s"
+ "%2$s/%3$s%1$s%5$s~%7$s/%8$s%6$s%10$s""%4$s/%2$s/%3$s%5$s~%9$s/%7$s/%8$s%10$s"
- "%4$s/%2$s/%3$s (%1$s) %5$s~%9$s/%7$s/%8$s (%6$s) %10$s"
- "%2$s%3$s日~%8$s日"
- "%2$s%3$s日 (%1$s)~%7$s%8$s日 (%6$s)"
- "%9$s年%2$s%3$s日~%8$s日"
- "%4$s年%2$s%3$s日 (%1$s)~%9$s年%7$s%8$s日 (%6$s)"
- "%2$s%3$s日%5$s~%7$s%8$s日%10$s"
- "%2$s%3$s日 (%1$s) %5$s~%7$s%8$s日 (%6$s) %10$s"
- "%4$s年%2$s%3$s日%5$s~%9$s年%7$s%8$s日%10$s"
- "%4$s年%2$s%3$s日 (%1$s) %5$s~%9$s年%7$s%8$s日 (%6$s) %10$s"
- "%Y年%b%-d日"
+ "%4$s/%2$s/%3$s%1$s%5$s~%9$s/%7$s/%8$s%6$s%10$s"
+ "%2$s月%3$s日~%8$s日"
+ "%2$s/%3$s%1$s~%7$s/%8$s%6$s"
+ "%9$s年%2$s月%3$s日~%8$s日"
+ "%4$s/%2$s/%3$s%1$s~%9$s/%7$s/%8$s%6$s"
+ "%2$s/%3$s%5$s~%7$s/%8$s%10$s"
+ "%2$s/%3$s%1$s%5$s~%7$s/%8$s%6$s%10$s"
+ "%4$s/%2$s/%3$s%5$s~%9$s/%7$s/%8$s%10$s"
+ "%4$s/%2$s/%3$s%1$s%5$s~%9$s/%7$s/%8$s%6$s%10$s"
+ "%Y/%b/%-d"
- "日曜"
- "月曜"
- "火曜"
- "水曜"
- "木曜"
- "金曜"
- "土曜"
- "日"
- "月"
- "火"
- "水"
- "木"
- "金"
- "土"
- "日"
- "月"
- "火"
- "水"
- "木"
- "金"
- "土"
- "日"
+ "日曜日"
+ "月曜日"
+ "火曜日"
+ "水曜日"
+ "木曜日"
+ "金曜日"
+ "土曜日"
+ "(日)"
+ "(月)"
+ "(火)"
+ "(水)"
+ "(木)"
+ "(金)"
+ "(土)"
+ "(日)"
+ "(月)"
+ "(火)"
+ "(水)"
+ "(木)"
+ "(金)"
+ "(土)"
+ "(日)""月"
- "火"
+ "(火)""水"
- "木"
+ "(木)""金"
- "土"
+ "(土)""日""月""火"
@@ -669,7 +670,7 @@
"12月""1""2"
- "月"
+ "3""4""5""6"
@@ -691,8 +692,7 @@
"貼り付け""URLをコピー""入力方法"
-
-
+ "辞書に「%s」を追加""テキストを編集""空き容量低下""携帯電話の空き容量が少なくなっています。"
@@ -700,44 +700,42 @@
"キャンセル""OK""キャンセル"
-
-
+ "注意""オン""オフ""操作の完了に使用"
- "この操作にデフォルトで使用します。"
- "ホームの[設定]>[アプリケーション]>[アプリケーションを管理]で、デフォルトをクリアします。"
+ "常にこの操作で使用する"
+ "ホームの[設定]>[アプリケーション]>[アプリケーションの管理]でデフォルト設定をクリアします。""操作の選択""この操作を実行できるアプリケーションはありません。""エラー"
- "アプリケーション%1$s (%2$sプロセス) が予期せず停止しました。もう一度試してください。"
- "%1$sプロセスが予期せず停止しました。もう一度試してください。"
+ "%1$s(%2$s)が予期せず停止しました。やり直してください。"
+ "%1$sが予期せず停止しました。やり直してください。""エラー"
- "%1$s操作 (アプリケーション%2$s) は応答していません。"
- "%1$s操作 (プロセス:%2$s) は応答していません。"
- "アプリケーション%1$s (%2$sプロセス) は応答していません。"
- "%1$sプロセスは応答していません。"
+ "%1$s(%2$s)は応答していません。"
+ "%1$s(プロセス: %2$s)は応答していません。"
+ "%1$s(%2$s)は応答していません。"
+ "%1$sは応答していません。""強制終了""待機""デバッグ"
- "テキストの操作の選択"
+ "テキストの操作""着信音の音量""メディアの音量""Bluetooth経由で再生中です""着信音の音量"
-
-
+ "Bluetooth着信音の音量""アラームの音量""通知音の音量""音量""デフォルトの着信音"
- "デフォルトの着信音 (%1$s)"
+ "端末既定の着信音(%1$s)""無音""着信音"
- "不明時着信音"
+ "不明な着信音"
- "Wi-Fiネットワークが利用可能"
- "Wi-Fiネットワークが利用可能"
+ "Wi-Fiを利用できます"
+ "Wi-Fiを利用できます""Wi-Fiオープンネットワークが利用できます"
@@ -746,12 +744,12 @@
"文字を挿入""不明なアプリケーション""SMSメッセージの送信中"
- "大量のSMSメッセージが送信されます。送信するには[OK]、中止するには[キャンセル]を選択します。"
+ "大量のSMSメッセージを送信しようとしています。[OK]で送信、[キャンセル]で中止します。""OK""キャンセル""設定"
- "デフォルト"
- "許可は必要ありません"
+ "端末既定"
+ "権限付与の必要はありません""隠す""すべて表示""読み込み中..."
@@ -762,60 +760,35 @@
"USBメモリにSDカードを使用する際に問題が発生しました。""USB接続""パソコンとの間でファイルをコピーします。"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "USBストレージをOFFにする"
+ "USBストレージをOFFにする場合に選択します。"
+ "USBストレージをOFFにする"
+ "USBストレージをOFFにする前にUSBホストのマウントを解除したことを確認してください。USBストレージをOFFにするには[OFF]を選択します。"
+ "OFF"
+ "キャンセル"
+ "USBストレージをOFFにする際に問題が発生しました。USBホストのマウントが解除されていることを確認してからもう一度お試しください。"
+ "SDカードをフォーマット"
+ "SDカードをフォーマットしてもよろしいですか?カード内のすべてのデータが失われます。"
+ "フォーマット""入力方法の選択""ABCDEFGHIJKLMNOPQRSTUVWXYZ""0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "候補"
+ "SDカードの準備中"
+ "エラーを確認中"
+ "空のSDカード"
+ "SDカードが空か、サポート対象外のファイルシステムを使用しています。"
+ "破損したSDカード"
+ "SDカードが破損しています。カードのフォーマットが必要な可能性があります。"
+ "SDカードが予期せず取り外されました"
+ "データの喪失を防ぐためSDカードを取り外す前にマウントを解除してください。"
+ "SDカードを安全に取り外しました"
+ "SDカードを安全に取り外せます。"
+ "SDカードが取り外されています"
+ "SDカードが取り外されました。新しいSDカードを挿入して端末のメモリを増やしてください。"
+ "一致するアクティビティが見つかりません"
+ "コンポーネント使用状況に関する統計情報の更新"
+ "収集されたコンポーネント使用状況に関する統計情報の変更を許可します。通常のアプリケーションでは使用しません。"
+
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 140f32f16527c..311f50110af7a 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -262,10 +262,8 @@
"응용프로그램이 전화기를 강제로 다시 부팅할 수 있습니다.""파일시스템 마운트 및 마운트 해제""응용프로그램이 이동식 저장소의 파일시스템을 마운트하고 마운트 해제할 수 있습니다."
-
-
-
-
+ "외부 저장소 포맷"
+ "응용프로그램이 제거 가능한 저장소를 포맷하도록 합니다.""진동 제어""응용프로그램이 진동을 제어할 수 있습니다.""손전등 제어"
@@ -280,10 +278,8 @@
"무선의 위치 업데이트 알림을 활성화하거나 비활성화할 수 있습니다. 일반 응용프로그램에서는 사용하지 않습니다.""체크인 속성 액세스""체크인 서비스에서 업로드한 속성에 대한 읽기/쓰기 액세스를 허용합니다. 일반 응용프로그램에서는 사용하지 않습니다."
-
-
-
-
+ "가젯 선택"
+ "어느 응용프로그램이 어느 가젯을 사용할 수 있는지 시스템에 알려 주는 권한을 본 응용프로그램에 부여합니다. 이 권한을 사용하면 응용프로그램이 개인 데이터에 대한 액세스 권한을 다른 응용프로그램에 제공할 수 있습니다. 일반 응용프로그램은 이 권한을 사용할 수 없습니다.""전화기 상태 수정""응용프로그램이 장치의 전화 기능을 제어할 수 있습니다. 이 권한을 갖는 응용프로그램은 사용자에게 알리지 않고 네트워크를 전환하거나, 전화 무선 기능을 켜고 끌 수 있습니다.""전화기 상태 읽기"
@@ -312,10 +308,8 @@
"응용프로그램이 APN의 프록시 및 포트 같은 APN 설정을 수정할 수 있습니다.""네트워크 연결 변경""응용프로그램이 네트워크 연결 상태를 변경할 수 있습니다."
-
-
-
-
+ "백그라운드 데이터 사용 설정 변경"
+ "백그라운드 데이터 사용 설정을 변경할 수 있는 권한을 응용프로그램에 부여합니다.""Wi-Fi 상태 보기""응용프로그램이 Wi-Fi의 상태에 대한 정보를 볼 수 있습니다.""Wi-Fi 상태 변경"
@@ -336,14 +330,10 @@
"응용프로그램이 현재 동기화된 피드에 대한 상세정보를 가져올 수 있습니다.""가입 피드 작성""응용프로그램이 현재 동기화된 피드를 수정할 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 동기화된 피드를 변경할 수 있습니다."
-
-
-
-
-
-
-
-
+ "상용자 정의 사전 읽기"
+ "응용프로그램이 사용자 사전에 보관되어 있을 수 있는 비공개 단어, 이름 및 구문을 읽도록 합니다."
+ "상용자 정의 사전에 작성"
+ "응용프로그램이 사용자 사전에 새 단어를 입력할 수 있습니다.""집""휴대전화"
@@ -440,12 +430,9 @@
"FACTORY_TEST 작업은 /system/app 디렉토리에 설치된 패키지에 대해서만 지원됩니다.""FACTORY_TEST 작업을 제공하는 패키지가 없습니다.""다시 부팅"
-
-
-
-
-
-
+ "\'%s\' 페이지 내용:"
+ "자바스크립트"
+ "다른 페이지를 탐색하시겠습니까?"\n\n"%s"\n\n"계속하려면 \'확인\'을 선택하고 현재 페이지에 그대로 있으려면 \'취소\'를 선택하세요.""확인""브라우저에 이 비밀번호를 저장하시겠습니까?""나중에"
@@ -496,22 +483,38 @@
"내일""%d일 후"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ "1초 전"
+ "%d 초 전"
+
+
+ "1분 전"
+ "%d분 전"
+
+
+ "1시간 전"
+ "%d시간 전"
+
+
+ "어제"
+ "%d일 전"
+
+
+ "1초 후"
+ "%d 초 후"
+
+
+ "1분 후"
+ "%d분 후"
+
+
+ "1시간 후"
+ "%d시간 후"
+
+
+ "내일"
+ "%d일 후"
+ "%s""%s""%s년"
@@ -553,17 +556,15 @@
"%3$s, %2$s, %1$s""%2$s, %3$s""%3$s, %1$s"
-
-
-
-
+ "%1$s, %2$s"
+ "%1$s, %2$s""%2$s, %1$s"
- "yyyy' 'MMMM', 'd"
- "yyyy' 'MMMM', 'd"
- "MMM' 'd', 'yyyy"
- "d' 'MMM', 'yyyy"
- "h':'mm' 'a"
- "H':'mm"
+ "yyyy' 'MMMM', 'd"
+ "yyyy' 'MMMM', 'd"
+ "MMM' 'd', 'yyyy"
+ "d' 'MMM', 'yyyy"
+ "h':'mm' 'a"
+ "H':'mm""정오""정오""자정"
@@ -691,8 +692,7 @@
"붙여넣기""URL 복사""입력 방법"
-
-
+ "사전에 \'%s\' 추가""텍스트 수정""저장공간 부족""전화기 저장공간이 부족합니다."
@@ -700,8 +700,7 @@
"취소""확인""취소"
-
-
+ "주의""켜짐""끄기""작업을 수행할 때 사용하는 권한"
@@ -725,8 +724,7 @@
"미디어 볼륨""Bluetooth를 통해 재생""통화볼륨"
-
-
+ "Bluetooth 통화 볼륨""알람 볼륨""알림 볼륨""볼륨"
@@ -762,60 +760,35 @@
"USB 저장소에 SD 카드를 사용하는 동안 문제가 발생했습니다.""USB 연결됨""컴퓨터에 파일을 복사하거나 컴퓨터의 파일을 복사하려면 선택합니다."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "USB 저장소 끄기"
+ "USB 저장소 끄기를 선택하세요."
+ "USB 저장소 끄기"
+ "USB 저장소를 끄기 전에 반드시 USB 호스를 마운트 해제하세요. USB 저장소를 끄려면 \'끄기\'를 선택하세요."
+ "USB 저장소 끄기"
+ "취소"
+ "USB 저장소를 끄는 동안 Weve에 문제가 발행했습니다. USB 호스트를 마운트 해제했는지 확인한 후 다시 시도하세요."
+ "SD 카드 포맷"
+ "SD 카드를 포맷하시겠습니까? 포맷하면 카드의 모든 데이터를 잃게 됩니다."
+ "포맷""입력 방법 선택""ABCDEFGHIJKLMNOPQRSTUVWXYZ""0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "가능한 원인"
+ "SD 카드 준비 중"
+ "오류 확인 중"
+ "빈 SD 카드"
+ "SD 카드가 비어 있거나 지원되지 않는 파일시스템입니다."
+ "손상된 SD 카드"
+ "SD 카드가 손상되었습니다. 카드를 다시 포맷하시기 바랍니다."
+ "SD 카드가 예상치 않게 제거되었습니다."
+ "데이터 손실을 피하려면 SD 카드를 제거하기 전에 마운트 해제합니다."
+ "SD 카드를 안전하게 제거할 수 있습니다."
+ "이제 SD 카드를 안전하게 제거할 수 있습니다."
+ "SD 카드를 제거했습니다."
+ "SD가 제거되었습니다. 기기의 저장 용량을 늘리려면 새 SD 카드를 삽입하세요."
+ "일치하는 활동이 없습니다."
+ "구성요소 사용 통계 업데이트"
+ "수집된 구성요소 사용 통계를 수정할 수 있는 권한을 부여합니다. 일반 응용프로그램은 이 권한을 사용할 수 없습니다."
+
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 466f2b175619d..9ee553fc7caf4 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -559,12 +559,12 @@
"%1$s, %2$s""%1$s, %2$s""%1$s, %2$s"
- "MMMM'\\\'\'\\\'\' \\\'\'\\\'\''d'\\\'\'\\\'\'., \\\'\'\\\'\''yyyy"
- "d'\\\'\'\\\'\'. \\\'\'\\\'\''MMMM'\\\'\'\\\'\' \\\'\'\\\'\''yyyy"
- "MMM'\\\'\'\\\'\' \\\'\'\\\'\''d'\\\'\'\\\'\', \\\'\'\\\'\''yyyy"
- "d'\\\'\'\\\'\'. \\\'\'\\\'\''MMM'\\\'\'\\\'\' \\\'\'\\\'\''yyyy"
- "h'\\\'\'\\\'\':\\\'\'\\\'\''mm'\\\'\'\\\'\' \\\'\'\\\'\''a"
- "H'\\\'\'\\\'\':\\\'\'\\\'\''mm"
+ "MMMM'\\\'\'\\\'\' \\\'\'\\\'\''d'\\\'\'\\\'\'., \\\'\'\\\'\''yyyy"
+ "d'\\\'\'\\\'\'. \\\'\'\\\'\''MMMM'\\\'\'\\\'\' \\\'\'\\\'\''yyyy"
+ "MMM'\\\'\'\\\'\' \\\'\'\\\'\''d'\\\'\'\\\'\', \\\'\'\\\'\''yyyy"
+ "d'\\\'\'\\\'\'. \\\'\'\\\'\''MMM'\\\'\'\\\'\' \\\'\'\\\'\''yyyy"
+ "h'\\\'\'\\\'\':\\\'\'\\\'\''mm'\\\'\'\\\'\' \\\'\'\\\'\''a"
+ "H'\\\'\'\\\'\':\\\'\'\\\'\''mm""middag""Middag""midnatt"
@@ -789,4 +789,6 @@
"Fant ingen tilsvarende aktiviteter""oppdater statistikk over komponentbruk""Tillater endring av innsamlet data om bruk av komponenter. Ikke ment for vanlige applikasjoner."
+
+
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index a2810a1f15270..a1446f594bfb0 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -262,10 +262,8 @@
"Hiermee kan de toepassing de telefoon gedwongen opnieuw opstarten.""bestandssystemen koppelen en ontkoppelen""Hiermee kan de toepassing bestandssystemen koppelen en ontkoppelen voor verwisselbare opslagruimte."
-
-
-
-
+ "externe opslag formatteren"
+ "Hiermee kan de toepassing de externe opslag formatteren.""trilstand beheren""Hiermee kan de toepassing de trilstand beheren.""zaklamp bedienen"
@@ -280,10 +278,8 @@
"Hiermee kunnen updatemeldingen voor locaties van de radio worden ingeschakeld/uitgeschakeld. Niet voor gebruik door normale toepassingen.""toegang tot checkin-eigenschappen""Hiermee wordt lees-/schrijftoegang gegeven tot eigenschappen die door de checkin-service zijn geüpload. Niet voor gebruik door normale toepassingen."
-
-
-
-
+ "gadgets kiezen"
+ "Hiermee kan een toepassing het systeem melden welke gadgets door welke toepassing kunnen worden gebruikt. Met deze toestemming kunnen toepassingen andere toepassingen toegang geven tot persoonlijke gegevens. Niet voor gebruik door normale toepassingen.""telefoonstatus wijzigen""Hiermee kan de toepassing de telefoonfuncties van het apparaat beheren. Een toepassing met deze machtiging kan schakelen tussen netwerken, de radio van de telefoon in- of uitschakelen en dergelijke zonder dat u hiervan op de hoogte wordt gesteld.""telefoonstatus lezen"
@@ -312,10 +308,8 @@
"Hiermee kan een toepassing de APN-instellingen, zoals proxy en poort, van elke APN wijzigen.""netwerkverbinding wijzigen""Hiermee kan een toepassing de verbindingsstatus van het netwerk wijzigen."
-
-
-
-
+ "instelling voor gebruik van achtergrondgegevens van gegevens wijzigen"
+ "Hiermee kan een toepassing de instelling voor gebruik van achtergrondgegevens wijzigen.""Wi-Fi-status bekijken""Hiermee kan een toepassing informatie over de Wi-Fi-status bekijken.""Wi-Fi-status wijzigen"
@@ -336,14 +330,10 @@
"Hiermee kan een toepassing details over de huidige gesynchroniseerde feeds achterhalen.""geabonneerde feeds schrijven""Hiermee kan een toepassing uw huidige gesynchroniseerde feeds wijzigen. Een schadelijke toepassing kan op deze manier uw gesynchroniseerde feeds wijzigen."
-
-
-
-
-
-
-
-
+ "door gebruiker gedefinieerd woordenboek lezen"
+ "Hiermee kan een toepassing privéwoorden, namen en woordcombinaties lezen die de gebruiker heeft opgeslagen in het gebruikerswoordenboek."
+ "schrijven naar door gebruiker gedefinieerd woordenboek"
+ "Hiermee kan een toepassing nieuwe woorden schrijven naar het gebruikerswoordenboek.""Thuis""Mobiel"
@@ -440,12 +430,9 @@
"De actie FACTORY_TEST wordt alleen ondersteund voor pakketten die zijn geïnstalleerd in /system/app.""Er is geen pakket gevonden dat de actie FACTORY_TEST levert.""Opnieuw opstarten"
-
-
-
-
-
-
+ "De pagina op \'%s\' zegt:"
+ "JavaScript"
+ "Wilt u deze pagina verlaten?"\n\n"%s"\n\n"Kies OK om door te gaan of Annuleren om op de huidige pagina te blijven.""Bevestigen""Wilt u dat de browser dit wachtwoord onthoudt?""Niet nu"
@@ -496,22 +483,38 @@
"morgen""over %d dagen"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ "1 seconde geleden"
+ "%d seconden geleden"
+
+
+ "1 minuut geleden"
+ "%d minuten geleden"
+
+
+ "1 uur geleden"
+ "%d uur geleden"
+
+
+ "gisteren"
+ "%d dagen geleden"
+
+
+ "over 1 seconde"
+ "over %d seconden"
+
+
+ "over 1 minuut"
+ "over %d minuten"
+
+
+ "over 1 uur"
+ "over %d uur"
+
+
+ "morgen"
+ "over %d dagen"
+ "op %s""om %s""in %s"
@@ -553,17 +556,15 @@
"%1$s, %2$s, %3$s""%2$s, %3$s""%1$s, %3$s"
-
-
-
-
+ "%1$s, %2$s"
+ "%1$s, %2$s""%1$s, %2$s"
- "MMMM' 'd', 'yyyy"
- "d' 'MMMM', 'yyyy"
- "MMM' 'd', 'yyyy"
- "d' 'MMM', 'yyyy"
- "h':'mm' 'a"
- "H':'mm"
+ "MMMM' 'd', 'yyyy"
+ "d' 'MMMM', 'yyyy"
+ "MMM' 'd', 'yyyy"
+ "d' 'MMM', 'yyyy"
+ "h':'mm' 'a"
+ "H':'mm""twaalf uur \'s middags""Twaalf uur \'s middags""middernacht"
@@ -691,8 +692,7 @@
"Plakken""URL kopiëren""Invoermethode"
-
-
+ "\'%s\' toevoegen aan woordenboek""Tekst bewerken""Weinig ruimte""Opslagruimte van telefoon raakt op."
@@ -700,8 +700,7 @@
"Annuleren""OK""Annuleren"
-
-
+ "Let op""AAN""UIT""Actie voltooien met"
@@ -725,8 +724,7 @@
"Mediavolume""Afspelen via Bluetooth""Volume inkomende oproep"
-
-
+ "Volume tijdens gesprek in Bluetooth-modus""Alarmvolume""Meldingsvolume""Volume"
@@ -762,60 +760,35 @@
"Er is een probleem bij het gebruik van uw SD-kaart voor USB-opslag.""USB-verbinding""Selecteer dit om bestanden naar/van uw computer te kopiëren."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "USB-opslag uitschakelen"
+ "Selecteer dit om USB-opslag uit te schakelen."
+ "USB-opslag uitschakelen"
+ "Voordat u de USB-opslag uitschakelt, moet u de koppeling met de USB-host verbreken. Selecteer \'Uitschakelen\' om USB-opslag uit te schakelen."
+ "Uitschakelen"
+ "Annuleren"
+ "Er is een probleem opgetreden tijdens het uitschakelen van USB-opslag. Controleer of u de USB-host heeft losgekoppeld en probeer het opnieuw."
+ "SD-kaart formatteren"
+ "Weet u zeker dat u de SD-kaart wilt formatteren? Alle gegevens op uw kaart gaan dan verloren."
+ "Formatteren""Invoermethode selecteren""ABCDEFGHIJKLMNOPQRSTUVWXYZ""0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "kandidaten"
+ "SD-kaart voorbereiden"
+ "Controleren op fouten"
+ "Lege SD-kaart"
+ "De SD-kaart is leeg of gebruikt een niet-ondersteund bestandssysteem."
+ "Beschadigde SD-kaart"
+ "De SD-kaart is beschadigd. U moet de kaart mogelijk opnieuw formatteren."
+ "SD-kaart onverwachts verwijderd"
+ "Ontkoppel de SD-kaart voordat u deze verwijdert om gegevensverlies te voorkomen."
+ "De SD-kaart kan veilig worden verwijderd"
+ "De SD-kaart kan nu veilig worden verwijderd."
+ "SD-kaart is verwijderd"
+ "De SD-kaart is verwijderd. Plaats een nieuwe SD-kaart om de opslagcapaciteit van uw apparaat te vergroten."
+ "Geen overeenkomende activiteiten gevonden"
+ "gebruiksstatistieken van component bijwerken"
+ "Hiermee kunnen verzamelde gebruiksstatistieken van een component worden gewijzigd. Niet voor gebruik door normale toepassingen."
+
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 12f16163e210b..a49b8243614ea 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -262,10 +262,8 @@
"Pozwala aplikacji na wymuszenie ponownego uruchomienia telefonu.""montowanie i odmontowanie systemów plików""Pozwala aplikacjom na podłączanie i odłączanie systemów plików w pamięciach przenośnych."
-
-
-
-
+ "formatowanie pamięci zewnętrznej"
+ "Zezwala aplikacji na formatowanie wymiennych nośników.""kontrolowanie wibracji""Pozwala aplikacjom na kontrolowanie wibracji.""kontrolowanie latarki"
@@ -280,10 +278,8 @@
"Pozwala włączyć/wyłączyć powiadomienia o aktualizacji położenia przez radio. Nie wykorzystywane przez normalne aplikacje.""dostęp do właściwości usługi rezerwacji""Pozwala na dostęp z uprawnieniami do odczytu/zapisu do właściwości przesłanych przez usługę rezerwacji. Nie wykorzystywane przez normalne aplikacje."
-
-
-
-
+ "wybieranie gadżetów"
+ "Zezwala aplikacjom na wskazywanie systemowi, które gadżety mogą być używane przez inne aplikacje. Z użyciem tego pozwolenia aplikacje mogą udzielać dostępu do danych osobistych innym aplikacjom. Nie jest ono przeznaczone dla zwykłych aplikacji.""zmiana stanu telefonu""Pozwala aplikacji na kontrolowanie funkcji telefonu w urządzeniu. Aplikacja z tymi uprawnieniami może przełączać sieci, włączać i wyłączać radio itp. bez informowania użytkownika.""czytanie stanu telefonu"
@@ -312,10 +308,8 @@
"Pozwala aplikacji na zmianę ustawień APN, takich jak serwer proxy oraz port dowolnego APN.""zmienianie połączeń sieci""Pozwala aplikacji na zmianę stanu połączeń sieciowych."
-
-
-
-
+ "zmienianie ustawienia używania danych w tle"
+ "Zezwala aplikacji na zmianę ustawień użycia danych w tle.""wyświetlanie stanu Wi-Fi""Pozwala aplikacji na wyświetlanie informacji o stanie Wi-Fi.""zmiana stanu Wi-Fi"
@@ -336,14 +330,10 @@
"Pozwala aplikacjom na pobieranie informacji szczegółowych na temat obecnie zsynchronizowanych źródeł.""zapisywanie subskrybowanych źródeł""Umożliwia aplikacji zmianę obecnie zsynchronizowanych źródeł. Może to pozwolić szkodliwej aplikacji na zmianę zsynchronizowanych źródeł."
-
-
-
-
-
-
-
-
+ "odczytywanie słownika zdefiniowanego przez użytkownika"
+ "Zezwala aplikacji na odczytywanie wszelkich prywatnych słów, nazw i wyrażeń zapisanych przez użytkownika w swoim słowniku."
+ "zapisywanie w słowniku zdefiniowanym przez użytkownika"
+ "Zezwala aplikacjom na zapisywanie nowych słów w słowniku użytkownika.""Dom""Komórka"
@@ -440,12 +430,9 @@
"Czynność FACTORY_TEST jest obsługiwana tylko dla pakietów zainstalowanych w katalogu /system/app.""Nie znaleziono żadnego pakietu, który zapewnia działanie FACTORY_TEST.""Uruchom ponownie"
-
-
-
-
-
-
+ "Komunikat ze strony pod adresem „%s”:"
+ "JavaScript"
+ "Czy opuścić tę stronę?"\n\n"%s"\n\n"Wybierz opcję OK, aby kontynuować, lub opcję Anuluj, aby pozostać na tej stronie.""Potwierdź""Czy chcesz, aby zapamiętać to hasło w przeglądarce?""Nie teraz"
@@ -496,22 +483,38 @@
"jutro""za %d dni"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ "sekundę temu"
+ "%d sek. temu"
+
+
+ "minutę temu"
+ "%d min temu"
+
+
+ "godzinę temu"
+ "%d godz. temu"
+
+
+ "wczoraj"
+ "%d dni temu"
+
+
+ "za sekundę"
+ "za %d sek."
+
+
+ "za minutę"
+ "za %d min"
+
+
+ "za godzinę"
+ "za %d godz."
+
+
+ "jutro"
+ "za %d dni"
+ "dnia %s""o %s""w %s"
@@ -553,17 +556,15 @@
"%1$s, %2$s, %3$s""%2$s, %3$s""%1$s, %3$s"
-
-
-
-
+ "%1$s, %2$s"
+ "%1$s, %2$s""%1$s, %2$s"
- "MMMM' 'd', 'yyyy"
- "d' 'MMMM', 'yyyy"
- "MMM' 'd', 'yyyy"
- "d' 'MMM', 'yyyy"
- "h':'mm' 'a"
- "H':'mm"
+ "MMMM' 'd', 'yyyy"
+ "d' 'MMMM', 'yyyy"
+ "MMM' 'd', 'yyyy"
+ "d' 'MMM', 'yyyy"
+ "h':'mm' 'a"
+ "H':'mm""południe""Południe""północ"
@@ -691,8 +692,7 @@
"Wklej""Kopiuj adres URL""Metoda wejściowa"
-
-
+ "Dodaj „%s” do słownika""Edytuj tekst""Mało miejsca""Maleje ilość dostępnej pamięci telefonu."
@@ -700,8 +700,7 @@
"Anuluj""OK""Anuluj"
-
-
+ "Uwaga""Włącz""Wyłącz""Zakończ działanie, korzystając z"
@@ -725,8 +724,7 @@
"Głośność multimediów""Odtwarzanie przez Bluetooth""Głośność podczas połączenia"
-
-
+ "Głośność Bluetooth w czasie połączenia""Głośność alarmu""Głośność powiadomienia""Głośność"
@@ -762,60 +760,35 @@
"Wystąpił problem z wykorzystaniem karty SD dla pamięci USB.""Połączenie przez USB""Wybierz, aby skopiować pliki do/z komputera"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "Wyłącz nośnik USB"
+ "Wybierz, aby wyłączyć nośnik USB."
+ "Wyłącz nośnik USB"
+ "Przed wyłączeniem nośnika USB upewnij się, że odłączono go od hosta USB. Wybierz „Wyłącz”, aby wyłączyć nośnik USB."
+ "Wyłącz"
+ "Anuluj"
+ "Napotkano problem przy wyłączaniu nośnika USB. Sprawdź, czy host USB został odłączony i spróbuj ponownie."
+ "Formatuj kartę SD"
+ "Czy na pewno sformatować kartę SD? Wszystkie dane na karcie zostaną utracone."
+ "Formatuj""Wybierz metodę wejściową""AĄBCĆDEĘFGHIJKLŁMNŃOÓPQRSŚTUVWXYZŹŻ""0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "kandydaci"
+ "Przygotowywanie karty SD"
+ "Sprawdzanie w poszukiwaniu błędów"
+ "Pusta karta SD"
+ "Karta SD jest pusta lub używa nieobsługiwanego systemu plików."
+ "Uszkodzona karta SD"
+ "Karta SD jest uszkodzona. Konieczne może być przeformatowanie karty."
+ "Karta SD została nieoczekiwanie wyjęta"
+ "Odłącz kartę SD przed jej wyjęciem, aby uniknąć utraty danych."
+ "Można bezpiecznie usunąć kartę SD"
+ "Można teraz bezpiecznie usunąć kartę SD."
+ "Usunięta karta SD"
+ "Karta SD została usunięta. Włóż nową kartę SD, aby zwiększyć pamięć urządzenia."
+ "Nie znaleziono pasujących działań"
+ "aktualizowanie statystyk użycia komponentu"
+ "Zezwala na modyfikacje zebranych statystyk użycia komponentu. Nieprzeznaczone dla zwykłych aplikacji."
+
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 76a358dddc21f..612a18505fabb 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -262,10 +262,8 @@
"Разрешает приложению принудительно перезагружать телефон.""подключаться и отключаться от файловых систем""Разрешает приложению подключаться и отключаться от файловых систем съемных устройств хранения."
-
-
-
-
+ "форматировать внешний накопитель"
+ "Позволяет приложению форматировать съемный накопитель.""управлять вибрацией""Разрешает приложению управлять вибровызовом.""управлять фонарем"
@@ -280,10 +278,8 @@
"Разрешает включение/отключение уведомлений о местоположении по радиосвязи. Не используется обычными приложениями.""открывать свойства проверки""Разрешает доступ на чтение и запись к свойствам, загруженным службой проверки. Не используется обычными приложениями."
-
-
-
-
+ "выбирать гаджеты"
+ "Позволяет приложению сообщить системе, какие приложения могут использовать какие гаджеты. Это разрешение позволяет приложениям предоставлять другим приложениям доступ к личной информации. Не предназначено для использования обычными приложениями.""изменять состояние телефона""Позволяет приложению управлять телефонными функциями устройства. Приложение с такими полномочиями может переключать сети, включать и выключать радиосвязь и т.д., не сообщая вам об этом.""считывать состояние телефона"
@@ -312,10 +308,8 @@
"Разрешает приложению изменять настройки APN, например прокси и порт любого APN.""изменять подключение к сети""Позволяет приложению изменять подключение к сети."
-
-
-
-
+ "изменить настройку использования фоновых данных"
+ "Позволяет приложению изменять настройку использования фоновых данных.""просматривать состояние Wi-Fi""Разрешает приложению просматривать сведения о состоянии Wi-Fi.""изменять состояние Wi-Fi"
@@ -336,14 +330,10 @@
"Позволяет приложению получать сведения о синхронизированных фидах.""записывать фиды с подпиской""Разрешает приложению изменять ваши синхронизированные фиды. Это может позволить вредоносному ПО изменять ваши синхронизированные фиды."
-
-
-
-
-
-
-
-
+ "выполнять чтение из пользовательского словаря"
+ "Позволяет приложению считывать любые слова, имена и фразы личного пользования, которые могут храниться в пользовательском словаре."
+ "записывать в пользовательский словарь"
+ "Позволяет приложению записывать новые слова в пользовательский словарь.""Домашний""Мобильный"
@@ -440,12 +430,9 @@
"Действие FACTORY_TEST поддерживается только для пакетов, установленных в папке /system/app.""Пакет, предоставляющий действие FACTORY_TEST, не найден.""Перезагрузить"
-
-
-
-
-
-
+ "На странице по адресу \"%s\" сказано:"
+ "JavaScript"
+ "Перейти с этой страницы?"\n\n"%s"\n\n"Нажмите \"ОК\", чтобы продолжить, или \"Отмена\", чтобы остаться на текущей странице.""Подтверждение""Сохранить этот пароль в браузере?""Не сейчас"
@@ -496,22 +483,38 @@
"завтра""через %d дн."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ "1 сек. назад"
+ "%d сек. назад"
+
+
+ "1 мин. назад"
+ "%d мин. назад"
+
+
+ "1 час назад"
+ "%d ч. назад"
+
+
+ "вчера"
+ "%d дн. назад"
+
+
+ "через 1 сек."
+ "через %d сек."
+
+
+ "через 1 мин."
+ "через %d мин."
+
+
+ "через 1 час"
+ "через %d час."
+
+
+ "завтра"
+ "через %d дн."
+ "%s""в %s""в %s"
@@ -553,17 +556,15 @@
"%1$s, %2$s, %3$s""%2$s, %3$s""%1$s, %3$s"
-
-
-
-
+ "%1$s, %2$s"
+ "%1$s, %2$s""%1$s, %2$s"
- "d' 'MMMM' 'yyyy"
- "d' 'MMMM' 'yyyy"
- "d' 'MMM' 'yyyy"
- "d' 'MMM' 'yyyy"
- "h':'mm' 'a"
- "H':'mm"
+ "d' 'MMMM' 'yyyy"
+ "d' 'MMMM' 'yyyy"
+ "d' 'MMM' 'yyyy"
+ "d' 'MMM' 'yyyy"
+ "h':'mm' 'a"
+ "H':'mm""полдень""Полдень""полночь"
@@ -691,8 +692,7 @@
"Вставить""Копировать URL""Способ ввода"
-
-
+ "Добавить \"%s\" в словарь""Правка текста""Недостаточно места""В памяти телефона осталось мало места."
@@ -700,8 +700,7 @@
"Отмена""ОК""Отмена"
-
-
+ "Внимание""ВКЛ""ВЫКЛ""Выполнить действие с помощью"
@@ -725,8 +724,7 @@
"Громкость звука мультимедиа""Воспроизводится через Bluetooth""Громкость звонка"
-
-
+ "Громкость входящего вызова Bluetooth""Громкость будильника""Громкость уведомления""Громкость"
@@ -762,60 +760,35 @@
"Не удается использовать карту SD в качестве USB-хранилища.""Подключение через USB""Выберите для копирования файлов на/с компьютера."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "Выключить USB-накопитель"
+ "Выберите, чтобы выключить USB-накопитель."
+ "Выключить USB-накопитель"
+ "Перед выключением USB-накопителя обязательно отключите USB-хост. Выберите \"Выключить\", чтобы выключить USB-накопитель."
+ "Выключить"
+ "Отмена"
+ "При выключении USB-накопителя произошла проблема. Убедитесь, что USB-хост отключен, и повторите попытку."
+ "Форматировать карту SD"
+ "Отформатировать карту SD? Все данные, находящиеся на карте, будут уничтожены."
+ "Формат""Выбор способа ввода""АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЫЭЮЯ""0123456789АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЫЭЮЯ"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "кандидаты"
+ "Подготовка карты SD"
+ "Поиск ошибок"
+ "Пустая карта SD"
+ "Карта SD пуста или использует неподдерживаемую файловую систему."
+ "Поврежденная карта SD"
+ "Карта SD повреждена. Может потребоваться переформатировать ее."
+ "Карта SD неожиданно извлечена"
+ "Перед извлечением карты SD отключите ее во избежание потери данных."
+ "Безопасное удаление карты SD"
+ "Теперь карту SD можно безопасно удалить."
+ "Карта SD удалена"
+ "Карта SD была удалена. Для увеличения емкости устройства вставьте новую карту SD."
+ "Подходящих действий не найдено"
+ "обновлять статистику использования компонентов"
+ "Позволяет изменять собранную статистику использования компонентов. Не предназначено для использования обычными приложениями."
+
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 13d4e9c696979..fbd58e8f93eb7 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -262,10 +262,8 @@
"允许应用程序强制手机重新引导。""装载和卸载文件系统""允许应用程序装载和卸载文件系统以进行可移动存储。"
-
-
-
-
+ "格式化外部存储设备"
+ "允许应用程序格式化可移除的存储设备。""控制振动器""允许应用程序控制振动器。""控制闪光灯"
@@ -280,10 +278,8 @@
"允许启用/禁用来自收音机的位置更新通知。普通应用程序不能使用此权限。""访问检入属性""允许对检入服务上传的属性进行读/写访问。普通应用程序不能使用此权限。"
-
-
-
-
+ "选择小工具"
+ "允许应用程序告诉系统哪些应用程序可以使用哪些小工具。应用程序可以借此授予其他应用程序访问个人数据的权限。普通应用程序不能使用此权限。""修改手机状态""允许应用程序控制设备的手机功能。具有此权限的应用程序可能会切换网络,打开和关闭手机收音机以及类似操作,而不会通知您。""读取手机状态"
@@ -312,10 +308,8 @@
"允许应用程序修改 APN 设置,例如任何 APN 的代理和端口。""更改网络连接性""允许应用程序更改状态网络连接性。"
-
-
-
-
+ "更改背景数据使用设置"
+ "允许应用程序更改背景数据使用设置。""查看 Wi-Fi 状态""允许应用程序查看有关 Wi-Fi 状态的信息。""更改 Wi-Fi 状态"
@@ -336,14 +330,10 @@
"允许应用程序获取有关当前同步的供稿的详情。""写入订阅的供稿""允许应用程序修改您当前同步的供稿。这样恶意程序可以更改您同步的供稿。"
-
-
-
-
-
-
-
-
+ "读取用户定义的词典"
+ "允许应用程序读取用户在用户词典中存储的任意私有字词、名称和短语。"
+ "写入用户定义的词典"
+ "允许应用程序向用户词典中写入新词。""家庭""手机"
@@ -440,12 +430,9 @@
"只有在 /system/app 中安装的包支持 FACTORY_TEST 操作。""未发现支持 FACTORY_TEST 操作的包。""重新引导"
-
-
-
-
-
-
+ "“%s”处的页面表明:"
+ "JavaScript"
+ "是否从该页面导航至它处?"\n\n"%s"\n\n"选择“确定”继续,或选择“取消”留在当前页面。""确认""是否希望浏览器记住此密码?""暂不保存"
@@ -496,22 +483,38 @@
"明天""%d 天后"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ "1 秒前"
+ "%d 秒前"
+
+
+ "1 分钟前"
+ "%d 分钟前"
+
+
+ "1 小时前"
+ "%d 小时前"
+
+
+ "昨天"
+ "%d 天前"
+
+
+ "1 秒后"
+ "%d 秒后"
+
+
+ "1 分钟后"
+ "%d 分钟后"
+
+
+ "1 小时后"
+ "%d 小时后"
+
+
+ "明天"
+ "%d 天后"
+ "在 %s""在 %s""%s 年内"
@@ -553,17 +556,15 @@
"%3$s%2$s%1$s""%3$s%2$s""%3$s%1$s"
-
-
-
-
+ "%1$s%2$s"
+ "%1$s%2$s""%2$s%1$s"
- "yyyy' 年 'MMMM' 月 'd' 日'"
- "yyyy' 年 'MMMM' 月 'd' 日'"
- "yyyy' 年 'MMM' 月 'd' 日'"
- "yyyy' 年 'd' 月 'MMM' 日'"
- "h':'mm' 'a"
- "H':'mm"
+ "yyyy' 年 'MMMM' 月 'd' 日'"
+ "yyyy' 年 'MMMM' 月 'd' 日'"
+ "yyyy' 年 'MMM' 月 'd' 日'"
+ "yyyy' 年 'd' 月 'MMM' 日'"
+ "h':'mm' 'a"
+ "H':'mm""中午""中午""午夜"
@@ -691,8 +692,7 @@
"粘贴""复制网址""输入方法"
-
-
+ "将“%s”添加到词典""编辑文本""存储空间不足""手机存储空间在减少。"
@@ -700,8 +700,7 @@
"取消""正常""取消"
-
-
+ "注意事项""开启""关闭""使用以下内容完成操作"
@@ -725,8 +724,7 @@
"媒体音量""正通过蓝牙播放""来电音量"
-
-
+ "使用蓝牙时的通话音量""警告音量""通知音量""音量"
@@ -762,60 +760,35 @@
"使用 SD 卡进行 USB 存储时出现问题。""USB 已连接""选择以将文件复制到计算机或从计算机复制文件。"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "关闭 USB 存储设备"
+ "选中以关闭 USB 存储设备。"
+ "关闭 USB 存储设备"
+ "在关闭 USB 存储设备前,请确保您已卸载了 USB 主设备。选择“关闭”关闭 USB 存储设备。"
+ "关闭"
+ "取消"
+ "关闭 USB 存储设备时遇到问题。请检查是否卸载了 USB 主设备,然后重试。"
+ "格式化 SD 卡"
+ "您确定要格式化 SD 卡?卡上的所有数据都会丢失。"
+ "格式化""选择输入方法""ABCDEFGHIJKLMNOPQRSTUVWXYZ""0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "候选"
+ "正在准备 SD 卡"
+ "检查是否有错误"
+ "空 SD 卡"
+ "SD 卡为空或使用不支持的文件系统。"
+ "SD 卡受损"
+ "SD 卡受损。您可能需要重新格式化您的卡。"
+ "SD 卡被意外拔除"
+ "先卸载 SD 卡再拔除,以避免数据丢失。"
+ "SD 卡已安全移除"
+ "现在可以安全移除 SD 卡。"
+ "已移除 SD 卡"
+ "SD 卡已移除。请插入新 SD 卡来增加您的设备存储空间。"
+ "找不到匹配的活动"
+ "更新组件使用情况统计"
+ "允许修改收集的组件使用情况统计。普通应用程序不能使用此权限。"
+
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 419e8c2eb4b8a..18d6711831eb1 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -262,10 +262,8 @@
"允許應用程式強制重開機。""掛載/卸載檔案系統""允許應用程式掛載/卸載抽取式儲存設備的檔案系統。"
-
-
-
-
+ "將外接式儲存裝置格式化"
+ "允許應用程式將可移除式儲存裝置格式化。""控制震動器""允許應用程式控制震動器。""控制閃光燈"
@@ -280,10 +278,8 @@
"允許啟用/停用無線通訊位置更新通知。一般應用程式不會使用此功能。""存取登機選項""允許讀寫登機服務上傳的資料。一般應用程式不會使用此功能。"
-
-
-
-
+ "選擇小工具"
+ "允許應用程式告知系統哪些應用程式可以使用哪些小工具。擁有此權限的應用程式可以讓其他應用程式使用個人資料。一般應用程式不會使用此功能。""修改手機狀態""允許應用程式控制電話功能。擁有此權限的程式可自行切換網路、開關無線通訊功能。""讀取手機狀態"
@@ -312,10 +308,8 @@
"允許應用程式修改 APN 設定,例如:Proxy 及 APN 的連接埠。""變更網路連線""允許應用程式變更網路連線狀態。"
-
-
-
-
+ "變更背景資料使用設定"
+ "允許應用程式變更背景資料使用設定。""檢視 Wi-Fi 狀態""允許應用程式檢視 Wi-Fi 狀態資訊。""變更 Wi-Fi 狀態"
@@ -336,14 +330,10 @@
"允許應用程式取得目前已同步處理的資訊提供。""寫入訂閱資訊提供""允許應用程式修改已同步處理的資訊提供。惡意程式可使用此功能變更已同步處理的資訊提供。"
-
-
-
-
-
-
-
-
+ "讀取使用者定義的字典"
+ "允許應用程式讀取使用者儲存在使用者字典內的任何私人字詞、名稱和詞組。"
+ "寫入使用者定義的字典"
+ "允許應用程式將新字詞寫入使用者的字典。""首頁""行動"
@@ -440,12 +430,9 @@
"FACTORY_TEST 動作只支援安裝在 /system/app 裡的程式。""找不到提供 FACTORY_TEST 的程式。""重新開機"
-
-
-
-
-
-
+ "「%s」的網頁指出:"
+ "JavaScript"
+ "離開此頁?"\n\n"%s"\n\n" 選取 [確定] 離開此頁;或 [取消] 留在此頁。""確認""是否記憶此密碼?""現在不要"
@@ -496,22 +483,38 @@
"明天""%d 天內"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ "1 秒以前"
+ "%d 秒以前"
+
+
+ "1 分鐘以前"
+ "%d 分鐘以前"
+
+
+ "1 小時以前"
+ "%d 小時以前"
+
+
+ "昨天"
+ "%d 天以前"
+
+
+ "1 秒內"
+ "%d 秒內"
+
+
+ "1 分鐘內"
+ "%d 分鐘內"
+
+
+ "1 小時內"
+ "%d 小時內"
+
+
+ "明天"
+ "%d 天內"
+ "%s""%s""%s"
@@ -553,17 +556,15 @@
"%1$s,%2$s,%3$s""%2$s,%3$s""%1$s,%3$s"
-
-
-
-
+ "%1$s,%2$s"
+ "%1$s,%2$s""%1$s,%2$s"
- "MMMM' 'd','yyyy"
- "d' 'MMMM','yyyy"
- "MMM' 'd','yyyy"
- "d' 'MMM','yyyy"
- "h':'mm' 'a"
- "H':'mm"
+ "MMMM' 'd','yyyy"
+ "d' 'MMMM','yyyy"
+ "MMM' 'd','yyyy"
+ "d' 'MMM','yyyy"
+ "h':'mm' 'a"
+ "H':'mm""中午""中午""午夜"
@@ -691,8 +692,7 @@
"貼上""複製網址""輸入法"
-
-
+ "將「%s」新增到字典""編輯文字""儲存空間太少""手機儲存空間即將不足。"
@@ -700,8 +700,7 @@
"取消""確定""取消"
-
-
+ "注意""開啟""關閉""選取...完成動作"
@@ -725,8 +724,7 @@
"媒體音量""透過藍牙播放""來電音量"
-
-
+ "藍牙通話音量""鬧鐘音量""通知音量""音量"
@@ -762,60 +760,35 @@
"把 SD 卡當成 USB 儲存裝置時發生問題。""USB 已連接""選取此項將檔案複製到電腦,或從電腦複製。"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "關閉 USB 儲存裝置"
+ "選取此處關閉 USB 儲存裝置。"
+ "關閉 USB 儲存裝置"
+ "關閉 USB 儲存裝置之前,請確定先從 USB Host 卸載。選取 [關閉] 即可關閉 USB 儲存裝置。"
+ "關閉"
+ "取消"
+ "關閉 USB 儲存裝置時發生問題。請檢查確認您是否已卸載 USB Host,然後再試一次。"
+ "將 SD 卡格式化"
+ "確定要將 SD 卡格式化嗎?該 SD 卡中的所有資料將會遺失。"
+ "格式化""選取輸入法""ABCDEFGHIJKLMNOPQRSTUVWXYZ""0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "待選項目"
+ "正在準備 SD 卡"
+ "正在檢查錯誤"
+ "SD 卡為空白"
+ "SD 卡為空白或使用不支援的檔案系統。"
+ "SD 卡已損壞"
+ "SD 卡已損壞。您可能需要將 SD 卡重新格式化。"
+ "SD 卡未預期移除"
+ "請先卸載 SD 卡,再將其移除,以免資料遺失。"
+ "可安全移除 SD 卡"
+ "現在可以安全移除 SD 卡。"
+ "已移除 SD 卡"
+ "已移除 SD 卡。請插入新的 SD 卡來增加裝置的儲存容量。"
+ "找不到符合的活動"
+ "更新元件使用統計資料"
+ "允許修改收集到的元件使用統計資料。一般應用程式不會使用此功能。"
+
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 593d1ff2a8a22..6e6e074a93c57 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -224,15 +224,18 @@
-
+
+
+
-
+
-
+
+
+
+
Safe mode
+
+ Android System
+
Services that cost you money
@@ -2265,6 +2268,3 @@
Double tap to zoom
-
-
-
diff --git a/data/sounds/Android.mk b/data/sounds/Android.mk
index dd0dcaa2ee248..9e3697f258483 100644
--- a/data/sounds/Android.mk
+++ b/data/sounds/Android.mk
@@ -64,9 +64,6 @@ ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/Ring_Synth_02.ogg
$(TARGET_OUT)/media/audio/ringtones/Ring_Synth_02.ogg : $(LOCAL_PATH)/Ring_Synth_02.ogg | $(ACP)
$(transform-prebuilt-to-target)
-ALL_PREBUILT += $(TARGET_OUT)/sounds/test.mid
-$(TARGET_OUT)/sounds/test.mid : $(LOCAL_PATH)/test.mid | $(ACP)
- $(transform-prebuilt-to-target)
#
# --- New Wave Labs ringtones
#
@@ -204,10 +201,6 @@ ALL_PREBUILT += $(TARGET_OUT)/media/audio/notifications/Voila.ogg
$(TARGET_OUT)/media/audio/notifications/Voila.ogg : $(LOCAL_PATH)/newwavelabs/Voila.ogg | $(ACP)
$(transform-prebuilt-to-target)
-ALL_PREBUILT += $(TARGET_OUT)/media/audio/ui/Effect_Tick.ogg
-$(TARGET_OUT)/media/audio/ui/Effect_Tick.ogg : $(LOCAL_PATH)/Effect_Tick.ogg | $(ACP)
- $(transform-prebuilt-to-target)
-
ALL_PREBUILT += $(TARGET_OUT)/media/audio/notifications/Beat_Box_Android.ogg
$(TARGET_OUT)/media/audio/notifications/Beat_Box_Android.ogg : $(LOCAL_PATH)/notifications/Beat_Box_Android.ogg | $(ACP)
$(transform-prebuilt-to-target)
@@ -223,3 +216,25 @@ $(TARGET_OUT)/media/audio/notifications/TaDa.ogg : $(LOCAL_PATH)/notifications/T
ALL_PREBUILT += $(TARGET_OUT)/media/audio/notifications/Tinkerbell.ogg
$(TARGET_OUT)/media/audio/notifications/Tinkerbell.ogg : $(LOCAL_PATH)/notifications/Tinkerbell.ogg | $(ACP)
$(transform-prebuilt-to-target)
+
+# UI effects
+ALL_PREBUILT += $(TARGET_OUT)/media/audio/ui/Effect_Tick.ogg
+$(TARGET_OUT)/media/audio/ui/Effect_Tick.ogg : $(LOCAL_PATH)/effects/Effect_Tick.ogg | $(ACP)
+ $(transform-prebuilt-to-target)
+
+ALL_PREBUILT += $(TARGET_OUT)/media/audio/ui/KeypressStandard.ogg
+$(TARGET_OUT)/media/audio/ui/KeypressStandard.ogg : $(LOCAL_PATH)/effects/KeypressStandard.ogg | $(ACP)
+ $(transform-prebuilt-to-target)
+
+ALL_PREBUILT += $(TARGET_OUT)/media/audio/ui/KeypressSpacebar.ogg
+$(TARGET_OUT)/media/audio/ui/KeypressSpacebar.ogg : $(LOCAL_PATH)/effects/KeypressSpacebar.ogg | $(ACP)
+ $(transform-prebuilt-to-target)
+
+ALL_PREBUILT += $(TARGET_OUT)/media/audio/ui/KeypressDelete.ogg
+$(TARGET_OUT)/media/audio/ui/KeypressDelete.ogg : $(LOCAL_PATH)/effects/KeypressDelete.ogg | $(ACP)
+ $(transform-prebuilt-to-target)
+
+ALL_PREBUILT += $(TARGET_OUT)/media/audio/ui/KeypressReturn.ogg
+$(TARGET_OUT)/media/audio/ui/KeypressReturn.ogg : $(LOCAL_PATH)/effects/KeypressReturn.ogg | $(ACP)
+ $(transform-prebuilt-to-target)
+
diff --git a/data/sounds/Effect_Tick.ogg b/data/sounds/effects/Effect_Tick.ogg
similarity index 100%
rename from data/sounds/Effect_Tick.ogg
rename to data/sounds/effects/Effect_Tick.ogg
diff --git a/data/sounds/effects/KeypressDelete.ogg b/data/sounds/effects/KeypressDelete.ogg
new file mode 100644
index 0000000000000..b35ea65b17a7b
Binary files /dev/null and b/data/sounds/effects/KeypressDelete.ogg differ
diff --git a/data/sounds/effects/KeypressDelete.wav b/data/sounds/effects/KeypressDelete.wav
new file mode 100644
index 0000000000000..5903f7f165d31
Binary files /dev/null and b/data/sounds/effects/KeypressDelete.wav differ
diff --git a/data/sounds/effects/KeypressReturn.ogg b/data/sounds/effects/KeypressReturn.ogg
new file mode 100644
index 0000000000000..1b0fd566cce00
Binary files /dev/null and b/data/sounds/effects/KeypressReturn.ogg differ
diff --git a/data/sounds/effects/KeypressReturn.wav b/data/sounds/effects/KeypressReturn.wav
new file mode 100644
index 0000000000000..9558fcf0c4ac3
Binary files /dev/null and b/data/sounds/effects/KeypressReturn.wav differ
diff --git a/data/sounds/effects/KeypressSpacebar.ogg b/data/sounds/effects/KeypressSpacebar.ogg
new file mode 100644
index 0000000000000..5299337f4d91c
Binary files /dev/null and b/data/sounds/effects/KeypressSpacebar.ogg differ
diff --git a/data/sounds/effects/KeypressSpacebar.wav b/data/sounds/effects/KeypressSpacebar.wav
new file mode 100644
index 0000000000000..1226a217e0d2b
Binary files /dev/null and b/data/sounds/effects/KeypressSpacebar.wav differ
diff --git a/data/sounds/effects/KeypressStandard.ogg b/data/sounds/effects/KeypressStandard.ogg
new file mode 100644
index 0000000000000..8a152d11fc3de
Binary files /dev/null and b/data/sounds/effects/KeypressStandard.ogg differ
diff --git a/data/sounds/effects/KeypressStandard.wav b/data/sounds/effects/KeypressStandard.wav
new file mode 100644
index 0000000000000..0c9aa2a383977
Binary files /dev/null and b/data/sounds/effects/KeypressStandard.wav differ
diff --git a/data/sounds/test.mid b/data/sounds/testfiles/test.mid
similarity index 100%
rename from data/sounds/test.mid
rename to data/sounds/testfiles/test.mid
diff --git a/docs/html/_build_id.cs b/docs/html/_build_id.cs
deleted file mode 100644
index 139c216c755cc..0000000000000
--- a/docs/html/_build_id.cs
+++ /dev/null
@@ -1,2 +0,0 @@
-
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
-
-
-
-
\ No newline at end of file
diff --git a/docs/html/goodies/index.jd b/docs/html/goodies/index.jd
deleted file mode 100644
index c12609816f8f1..0000000000000
--- a/docs/html/goodies/index.jd
+++ /dev/null
@@ -1,85 +0,0 @@
-page.title=Goodies
-@jd:body
-
-
Sometimes you may want to manually interact with your applications to verify that a particular feature or behavior is working properly; why not automate this verification with a JUnit TestCase that can instrument applications?
-
Instrumentation testing allows you to verify a particular feature or behavior with an automated JUnit TestCase. You can launch activities and providers within an application, send key events, and make assertions about various UI elements.
-
-This document provides an overview of how to use instrumentation on Android and covers these topics:
-
-
The following classes help glue together Instrumentation with JUnit testing.
-
-
-
Class
-
Description
-
-
InstrumentationTestCase
-
-
This extends the standard JUnit TestCase and offers access to an Instrumentation class. Write tests inside your instrumentation class any way you see fit. For example, your test might launch activities and send key events. For this to work properly, the instrumentation needs to be injected into the test case.
-
-
-
-
InstrumentationTestRunner
-
The instrumentation test runner is an instrumentation that runs instrumentation test cases and injects itself into each test case. Instrumentation test cases need to be grouped together with an instrumentation test runner with the appropriate target package.
-
-
-
InstrumentationTestSuite
-
The instrumentation test suite is a simple extension of the standard JUnit TestSuite that keeps a member Instrumentation variable on hand to inject into each TestCase before running them. It is used by InstrumentationTestRunner.
-
-
-
Three additional base classes extend InstrumentationTestCase to allow you to test Activity and Provider classes:
-
-
-
Class
-
Description
-
-
-
ActivityTestCase
-
This class can be used to write tests for a specific activity. An activity is launched in its setUp() method and finished with tearDown. If you write a test case that extends ActivityTestCase, you can write tests that access the activity using getActivity() and assume it has been set up properly.
-
-
-
SingleLaunchActivityTestCase
-
This class is similar to ActivityTestCase except that the activity is launched once per class instead of every time the test case calls setup.
-
-
-
ProviderTestCase
-
This class is similar to ActivityTestCase except that it will setup, tear down, and provide access to the Provider of your choice.
-
-
-
-
-
Running Tests
-
-
To run your tests, use the am instrument command with your InstrumentationTestRunner as its argument. Results are printed as a result of the instrumentation. For example, the following snippet displays the output after running the framework tests with one test failing (note the unusual syntax caused by how instrumentations are run via am):
-
-$ adb shell am instrument -w com.google.android.frameworktest/.tests.FrameworkInstrumentationTestRunner
-INSTRUMENTATION_RESULT: test results:=.......F.......
-Time: 6.837
-There was 1 failure:
-1) testSetUpConditions(com.google.android.frameworktest.tests.focus.RequestFocusTest)junit.framework.AssertionFailedError: requestFocus() should work from onCreate.
- at com.google.android.frameworktest.tests.focus.RequestFocusTest.testSetUpConditions(RequestFocusTest.java:66)
- at java.lang.reflect.Method.invokeNative(Native Method)
- at android.test.InstrumentationTestSuite.runTest(InstrumentationTestSuite.java:73)
- at android.test.InstrumentationTestSuite.runTest(InstrumentationTestSuite.java:73)
- at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:151)
- at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1088)
-
-FAILURES!!!
-Tests run: 14, Failures: 1, Errors: 0
-
-<RETURN> to continue
-
-INSTRUMENTATION_CODE: -1
-$
-
-
-
-
All Tests
-
-
-$ adb shell am instrument -w MyInstrumentationTestRunner
-
-
-
-
A Single Test Case
-
-
-$ adb shell am instrument \
- -e class MyInstrumentationTestCase \
- -w MyInstrumentationTestRunner
-
-
-
-
A Single Test
-
-
-$ adb shell am instrument \
- -e class MyInstrumentationTestCase#myTestMethod \
- -w MyInstrumentationTestRunner
-
-
-
-
Creating Tests
-
-
-
-
-
-
New Instrumentation TestRunner
-
-
-public class FrameworkInstrumentationTestRunner extends InstrumentationTestRunner {
-
- @Override
- public TestSuite getAllTests() {
- InstrumentationTestSuite suite = new InstrumentationTestSuite(this);
-
- suite.addTestSuite(FocusAfterRemovalTest.class);
- suite.addTestSuite(RequestFocusTest.class);
- suite.addTestSuite(RequestRectangleVisibleTest.class);
- return suite;
- }
-
- @Override
- public ClassLoader getLoader() {
- return FrameworkInstrumentationTestRunner.class.getClassLoader();
- }
-}
-
-
-
Next, in an appropriate AndroidManifest.xml, define the instrumentation for the derived class with the appropriate android:targetPackage set. For example, the snippet below defines the instrumentation runner for the framework tests.
To create a new test case, write a class that extends InstrumentationTestCase in the same application archive as your test runner. The following snippet illustrates an example ActivityTestCase that tests an activity named MyActivity.
-
-public class ButtonPressTest extends ActivityTestCase<MyActivity> {
-
- Button mLeftButton;
-
- public ButtonPressTest() {
- super("com.example", MyActivity.class);
- }
-
- @Override
- public void setUp() throws Exception {
- super.setUp();
- mLeftButton = (Button) getActivity().findViewById(R.id.leftButton);
- }
-
- public void testFocusMovesToRight() throws Exception {
- assertTrue(mLeftButton.hasFocus());
- getInstrumentation().sendCharacterSync(KeyEvent.KEYCODE_DPAD_RIGHT);
-
- Button rightButton = (Button) getActivity().findViewById(R.id.rightButton);
- assertTrue(rightButton.hasFocus());
- }
-
- // could have several more tests...
-}
-
-
-
-
Aliases for Running Framework Instrumentation Tests
-
-
-# compiles and installs FrameworkTests
-alias deploytests="(cd tests/FrameworkTests/ && mm) && adb install out/target/product/dream/system/app/FrameworkTest.apk"
-
-# runs all of FrameworkTests unit tests
-alias runtests="adb shell am instrument -w com.google.android.frameworktest/.tests.FrameworkInstrumentationTestRunner"
-
-# runtest TEST: runs a single unit test, for instance runtest view.VisibilityTest
-# -- for convenience, you don't have to type the com.google.android.frameworktest.tests.
-function runtest {
- adb shell am instrument -e class com.google.android.frameworktest.tests.$1 -w com.google.android.frameworktest/.tests.FrameworkInstrumentationTestRunner
-}
-
-# debugtest TEST: runs a single unit test in debug mode, for instance runtest view.VisibilityTest
-function debugtest {
- adb shell am instrument -e debug true -e class com.google.android.frameworktest.tests.$1 -w com.google.android.frameworktest/.tests.FrameworkInstrumentationTestRunner
-}
-
-
-
diff --git a/docs/html/guide/developing/tools/emulator.jd b/docs/html/guide/developing/tools/emulator.jd
index dd367b708938e..769491b4f14bd 100644
--- a/docs/html/guide/developing/tools/emulator.jd
+++ b/docs/html/guide/developing/tools/emulator.jd
@@ -812,7 +812,7 @@ in the default directory, or in a custom location (if you specified a path with
userdata-qemu.img
An image to which the emulator writes runtime user-data for a unique user.
-
Override using -data <;filepath>, where <filepath> is the
+
Override using -data <filepath>, where <filepath> is the
path the image, relative to the current working directory. If you supply a filename only,
the emulator looks for the file in the current working directory. If the file at <filepath> does
not exist, the emulator creates an image from the default userdata.img, stores it under the name you
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index ee56ebb4e9f99..77d3522ce72ae 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -34,7 +34,7 @@
2. Consider adding an End User License Agreement in your
-application
+application
To protect your person, organization, and intellectual property, you may want
to provide an End User License Agreement (EULA) with your application.
-
3. Specify an icon and label in the application's manifest
+
3. Specify an icon and label in the application's manifest
The icon and label that you specify in an application's manifest are
important because they are displayed to users as your application's icon and
@@ -114,7 +114,7 @@ display the icon and label to users.
As regards the design of your icon, you should try to make it match as much
as possible the style used by the built-in Android applications.
-
4. Turn off logging and debugging and clean up data/files
+
4. Turn off logging and debugging and clean up data/files
For release, you should make sure that debug facilities are turned off and
that debug and other unnecessary data/files are removed from your application
@@ -129,9 +129,9 @@ application project.
code.
-
Before you do the final compile of your application
+
Before you do the final compile of your application
-
5. Version Your Application
+
5. Version Your Application
Before you compile your application, you must make sure that you have defined
a version number for your application, specifying an appropriate value for both
@@ -149,7 +149,7 @@ element in the application's manifest file, using appropriate values.
For detailed information about how to define version information for your
application, see Versioning Your Applications.
-
6. Obtain a suitable cryptographic key
+
6. Obtain a suitable cryptographic key
If you have read and followed all of the preparation steps up to this point,
your application is compiled and ready for signing. Inside the .apk, the
@@ -222,20 +222,20 @@ to download Maps data.
href="#signing">Signing Your Applications.
-
Compile Your Application
+
Compile Your Application
When you've prepared your application as described in the previous sections,
you can compile your application for release.
-
After Compiling Your Application
+
After Compiling Your Application
-
8. Sign Your Application
+
8. Sign Your Application
Sign your application using your private key. Signing your application
correctly is critically important. Please see Signing Your
Applications for complete information.
-
9. Test Your Compiled and Signed Application
+
9. Test Your Compiled and Signed Application
Before you release your compiled application, you should thoroughly test it
on the target mobile device (and target network, if possible). In particular,
diff --git a/docs/html/guide/publishing/versioning.jd b/docs/html/guide/publishing/versioning.jd
index d10626698a69e..d0eafcd58d990 100644
--- a/docs/html/guide/publishing/versioning.jd
+++ b/docs/html/guide/publishing/versioning.jd
@@ -125,7 +125,7 @@ applications use the
{@link android.content.pm.PackageManager#getPackageInfo(java.lang.String, int)}
method of {@link android.content.pm.PackageManager PackageManager}.
-
Specifying Minimum System API Version
.
+
Specifying Minimum System API Version
If your application requires a specific minimum version of the Android
platform, you can specify that version as an API Level identifier
@@ -152,4 +152,4 @@ that your application is compatible with all platform versions.
<manifest>, then define the
android:minSdkVersion as an attribute.
-
Sometimes, the best way to learn how things are done is to just look at some code.
-So here we've provided the source code for some simple Android applications.
+
Sometimes, the best way to learn how things are done is to just look at some code. So here
+ we've provided links to let you browse the source of some some simple Android applications.
+
The source code for these applications is included in the Android SDK, in this location:
+
+
<sdk>/samples/
+
+
You can easily add these applications as projects in your development environment, so that you
+can modify them and watch them execute.
An application for saving notes. Similar (but not identical) to the
Notepad tutorial.
-
\ No newline at end of file
+
diff --git a/docs/html/guide/topics/fundamentals.jd b/docs/html/guide/topics/fundamentals.jd
index 3e1501cb79fa5..3c7f419713f87 100644
--- a/docs/html/guide/topics/fundamentals.jd
+++ b/docs/html/guide/topics/fundamentals.jd
@@ -42,6 +42,7 @@ page.title=Application Fundamentals
+
@@ -401,7 +402,7 @@ components. For example, an activity might be declared as follows:
</activity>
. . .
</application>
-</manifest>
+</manifest>
The {@code name} attribute of the
@@ -469,7 +470,7 @@ two intent filters to the activity:
</activity>
. . .
</application>
-</manifest>
+</manifest>
The first filter in the example — the combination of the action
@@ -769,9 +770,9 @@ return to what that instance was doing before the new intent arrived.
If this attribute is set to "{@code true}" in the root activity of a task,
the default behavior just described does not happen.
The task retains all activities in its stack even after a long period.
If this attribute is set to "{@code true}" in the root activity of a task,
the stack is cleared down to the root activity whenever the user leaves the task
and returns to it. In other words, it's the polar opposite of
{@code alwaysRetainTaskState}. The user always returns to the task in its
initial state, even after a momentary absence.
This attribute is like {@code clearTaskOnLaunch}, but it operates on a
single activity, not an entire task. And it can cause any activity to go
away, including the root activity. When it's set to "{@code true}", the
@@ -999,7 +1006,7 @@ in the following diagram:
-
+
@@ -1173,7 +1180,7 @@ to commit data changes and otherwise prepare to stop interacting with the user.
-
+
Calling into the superclass
An implementation of any activity lifecycle method should always first
@@ -1235,18 +1242,18 @@ to perform operations when the activity transitions between states.
+alt="State diagram for an Android activity lifecycle." />
The following table describes each of these methods in more detail and
locates it within the activity's overall lifecycle:
-
-
-
-
-
+
+
+
+
+
Method
Description
Killable?
Next
@@ -1254,7 +1261,7 @@ locates it within the activity's overall lifecycle:
-
{@link android.app.Activity#onCreate onCreate()}
+
{@link android.app.Activity#onCreate onCreate()}
Called when the activity is first created.
This is where you should do all of your normal static set up —
create views, bind data to lists, and so on. This method is passed
@@ -1268,7 +1275,7 @@ locates it within the activity's overall lifecycle:
Called after the activity has been stopped, just prior to it being
started again.
@@ -1278,7 +1285,7 @@ onRestart()}
-
{@link android.app.Activity#onStart onStart()}
+
{@link android.app.Activity#onStart onStart()}
Called just before the activity becomes visible to the user.
Followed by {@code onResume()} if the activity comes
to the foreground, or {@code onStop()} if it becomes hidden.
@@ -1288,7 +1295,7 @@ onRestart()}
-
{@link android.app.Activity#onResume onResume()}
+
{@link android.app.Activity#onResume onResume()}
Called just before the activity starts
interacting with the user. At this point the activity is at
the top of the activity stack, with user input going to it.
@@ -1298,7 +1305,7 @@ onRestart()}
-
{@link android.app.Activity#onPause onPause()}
+
{@link android.app.Activity#onPause onPause()}
Called when the system is about to start resuming another
activity. This method is typically used to commit unsaved changes to
persistent data, stop animations and other things that may be consuming
@@ -1307,24 +1314,24 @@ onRestart()}
Followed either by {@code onResume()} if the activity
returns back to the front, or by {@code onStop()} if it becomes
invisible to the user.
-
Yes
+
Yes
{@code onResume()} or {@code onStop()}
-
{@link android.app.Activity#onStop onStop()}
+
{@link android.app.Activity#onStop onStop()}
Called when the activity is no longer visible to the user. This
may happen because it is being destroyed, or because another activity
(either an existing one or a new one) has been resumed and is covering it.
Followed either by {@code onRestart()} if
the activity is coming back to interact with the user, or by
{@code onDestroy()} if this activity is going away.
Called before the activity is destroyed. This is the final call
that the activity will receive. It could be called either because the
@@ -1333,7 +1340,7 @@ onDestroy()}
instance of the activity to save space. You can distinguish
between these two scenarios with the {@link
android.app.Activity#isFinishing isFinishing()} method.
-
Yes
+
Yes
nothing
@@ -1346,7 +1353,7 @@ whether or not the system can kill the process hosting the activity
line of the activity's code. Three methods ({@code onPause()},
{@code onStop()}, and {@code onDestroy()}) are marked "Yes." Because
{@code onPause()} is the first of the three, it's the only one that's
-guaranteed to be called before the process is killed &mdash
+guaranteed to be called before the process is killed —
{@code onStop()} and {@code onDestroy()} may not be. Therefore, you
should use {@code onPause()} to write any persistent data (such as user
edits) to storage.
@@ -1380,7 +1387,7 @@ previous state.
To capture that state before the activity is killed, you can implement
an {@link android.app.Activity#onSaveInstanceState
onSaveInstanceState()} method for the activity. Android calls this
-method before making the activity vulnerable to being destroyed &mdash
+method before making the activity vulnerable to being destroyed —
that is, before {@code onPause()} is called. It
passes the method a {@link android.os.Bundle} object where you can record
the dynamic state of the activity as name-value pairs. When the activity is
@@ -1552,7 +1559,7 @@ so any service may receive {@code onBind()} and {@code onUnbind()} calls.
+alt="State diagram for Service callbacks." />
Broadcast receiver lifecycle
@@ -1615,7 +1622,7 @@ in the foreground if any of the following conditions hold:
It is running an activity that the user is interacting with
(the Activity object's {@link android.app.Activity#onResume
-onResume()} method has been called).
+onResume()} method has been called).
It hosts a service that's bound
to the activity that the user is interacting with.
An intent filter cannot be relied on for security. While it opens a
component to receiving only certain kinds of implicit intents, it does
diff --git a/docs/html/guide/topics/manifest/action-element.jd b/docs/html/guide/topics/manifest/action-element.jd
new file mode 100644
index 0000000000000..bc2e1d3a27666
--- /dev/null
+++ b/docs/html/guide/topics/manifest/action-element.jd
@@ -0,0 +1,46 @@
+page.title=<action>
+@jd:body
+
+
Adds an action to an intent filter.
+An <intent-filter> element must contain
+one or more {@code <action>} elements. If it doesn't contain any, no
+Intent objects will get through the filter. See
+Intents and
+Intent Filters for details on intent filters and the role of action
+specifications within a filter.
+
+
+
attributes:
+
+
{@code android:name}
+
The name of the action. Some standard actions are defined in the
+{@link android.content.Intent#ACTION_CHOOSER Intent} class as
+{@code ACTION_string} constants. To assign one of these actions to
+this attribute, prepend "{@code android.intent.action.}" to the
+{@code string} that follows {@code ACTION_}.
+For example, for {@code ACTION_MAIN}, use "{@code android.intent.action.MAIN}"
+and for {@code ACTION_WEB_SEARCH}, use "{@code android.intent.action.WEB_SEARCH}".
+
+
+For actions you define, it's best to use the package name as a prefix to
+ensure uniqueness. For example, a {@code TRANSMOGRIFY} action might be specified
+as follows:
+
\ No newline at end of file
diff --git a/docs/html/guide/topics/manifest/activity-alias-element.jd b/docs/html/guide/topics/manifest/activity-alias-element.jd
new file mode 100644
index 0000000000000..9d81d502e46d1
--- /dev/null
+++ b/docs/html/guide/topics/manifest/activity-alias-element.jd
@@ -0,0 +1,129 @@
+page.title=<activity-alias>
+@jd:body
+
+
An alias for an activity, named by the {@code targetActivity}
+attribute. The target must be in the same application as the
+alias and it must be declared before the alias in the manifest.
+
+
+The alias presents the target activity as a independent entity.
+It can have its own set of intent filters, and they, rather than the
+intent filters on the target activity itself, determine which intents
+can activate the target through the alias and how the system
+treats the alias. For example, the intent filters on the alias may
+specify the "{@link android.content.Intent#ACTION_MAIN
+android.intent.action.MAIN}"
+and "{@link android.content.Intent#CATEGORY_LAUNCHER
+android.intent.category.LAUNCHER}" flags, causing it to be
+represented in the application launcher, even though none of the
+filters on the target activity itself set these flags.
+
+
+
+With the exception of {@code targetActivity}, {@code <activity-alias>}
+attributes are a subset of <activity> attributes.
+For attributes in the subset, none of the values set for the target carry over
+to the alias. However, for attributes not in the subset, the values set for
+the target activity also apply to the alias.
+
+
+
attributes:
+
+
{@code android:enabled}
+
Whether or not the target activity can be instantiated by the system through
+this alias — "{@code true}" if it can be, and "{@code false}" if not.
+The default value is "{@code true}".
+
+
+The <application> element has its own
+enabled attribute that applies to all
+application components, including activity aliases. The
+<application> and {@code <activity-alias>}
+attributes must both be "{@code true}" for the system to be able to instantiate
+the target activity through the alias. If either is "{@code false}", the alias
+does not work.
+
+
+
{@code android:exported}
+
Whether or not components of other applications can launch the target activity
+through this alias — "{@code true}" if they can, and "{@code false}" if not.
+If "{@code false}", the target activity can be launched through the alias only by
+components of the same application as the alias or applications with the same user ID.
+
+
+The default value depends on whether the alias contains intent filters. The
+absence of any filters means that the activity can be invoked through the alias
+only by specifying the exact name of the alias. This implies that the alias
+is intended only for application-internal use (since others would not know its name)
+— so the default value is "{@code false}".
+On the other hand, the presence of at least one filter implies that the alias
+is intended for external use — so the default value is "{@code true}".
+
+
+
{@code android:icon}
+
An icon for the target activity when presented to users through the alias.
+See the <activity> element's
+icon attribute for more information.
+
+
{@code android:label}
+
A user-readable label for the alias when presented to users through the alias.
+See the the <activity> element's
+label attribute for more information.
+
A unique name for the alias. The name should resemble a fully
+qualified class name. But, unlike the name of the target activity,
+the alias name is arbitrary; it does not refer to an actual class.
+
+
+
{@code android:permission}
+
The name of a permission that clients must have to launch the target activity
+or get it to do something via the alias. If a caller of
+{@link android.content.Context#startActivity startActivity()} or
+{@link android.app.Activity#startActivityForResult startActivityForResult()}
+has not been granted the specified permission, the target activity will not be
+activated.
+
+
This attribute supplants any permission set for the target activity itself. If
+it is not set, a permission is not needed to activate the target through the alias.
+
+
+
+For more information on permissions, see the
+Permissions
+section in the introduction.
+
+
+
{@code android:targetActivity}
+
The name of the activity that can be activated through the alias.
+This name must match the {@code name} attribute of an
+<activity> element that precedes
+the alias in the manifest.
+
\ No newline at end of file
diff --git a/docs/html/guide/topics/manifest/activity-element.jd b/docs/html/guide/topics/manifest/activity-element.jd
new file mode 100644
index 0000000000000..aba89d72cd6cf
--- /dev/null
+++ b/docs/html/guide/topics/manifest/activity-element.jd
@@ -0,0 +1,565 @@
+page.title=<activity>
+@jd:body
+
+
Declares an activity (an {@link android.app.Activity} subclass) that
+implements part of the application's visual user interface. All activities
+must be represented by {@code <activity>}
+elements in the manifest file. Any that are not declared there will not be seen
+by the system and will never be run.
+
+
attributes:
+
+
{@code android:allowTaskReparenting}
+
Whether or not the activity can move from the task that started it to
+the task it has an affinity for when that task is next brought to the
+front — "{@code true}" if it can move, and "{@code false}" if it
+must remain with the task where it started.
+
+
+If this attribute is not set, the value set by the corresponding
+allowTaskReparenting
+attribute of the <application> element
+applies to the activity. The default value is "{@code false}".
+
+
+
+Normally when an activity is started, it's associated with the task of
+the activity that started it and it stays there for its entire lifetime.
+You can use this attribute to force it to be re-parented to the task it
+has an affinity for when its current task is no longer displayed.
+Typically, it's used to cause the activities of an application to move
+to the main task associated with that application.
+
+
+
+For example, if an e-mail message contains a link to a web page, clicking
+the link brings up an activity that can display the page. That activity
+is defined by the browser application, but is launched as part of the e-mail
+task. If it's reparented to the browser task, it will be shown when the
+browser next comes to the front, and will be absent when the e-mail task
+again comes forward.
+
+
+
+The affinity of an activity is defined by the
+taskAffinity attribute. The affinity
+of a task is determined by reading the affinity of its root activity.
+Therefore, by definition, a root activity is always in a task with the
+same affinity. Since activities with "{@code singleTask}" or
+"{@code singleInstance}" launch modes can only be at the root of a task,
+re-parenting is limited to the "{@code standard}" and "{@code singleTop}"
+modes. (See also the launchMode
+attribute.)
+
+
+
{@code android:alwaysRetainTaskState}
+
Whether or not the state of the task that the activity is in will always
+be maintained by the system — "{@code true}" if it will be, and
+"{@code false}" if the system is allowed to reset the task to its initial
+state in certain situations. The default value is "{@code false}". This
+attribute is meaningful only for the root activity of a task; it's ignored
+for all other activities.
+
+
+Normally, the system clears a task (removes all activities from the stack
+above the root activity) in certain situations when the user re-selects that
+task from the home screen. Typically, this is done if the user hasn't visited
+the task for a certain amount of time, such as 30 minutes.
+
+
+
+However, when this attribute is "{@code true}", users will always return
+to the task in its last state, regardless of how they get there. This is
+useful, for example, in an application like the web browser where there is
+a lot of state (such as multiple open tabs) that users would not like to lose.
+
+
+
{@code android:clearTaskOnLaunch}
+
Whether or not all activities will be removed from the task, except for
+the root activity, whenever it is re-launched from the home screen —
+"{@code true}" if the task is always stripped down to its root activity, and
+"{@code false}" if not. The default value is "{@code false}". This attribute
+is meaningful only for activities that start a new task (the root activity);
+it's ignored for all other activities in the task.
+
+
+When the value is "{@code true}", every time users start the task again, they
+are brought to its root activity, regardless of what they were last doing in
+the task and regardless of whether they used BACK or HOME to last leave it.
+When the value is "{@code false}", the task may be cleared of activities in
+some situations (see the
+alwaysRetainTaskState attribute), but not always.
+
+
+
+Suppose, for example, that someone launches activity P from the home screen,
+and from there goes to activity Q. The user next presses HOME, and then returns
+to activity P. Normally, the user would see activity Q, since that is what they
+were last doing in P's task. However, if P set this flag to "{@code true}", all
+of the activities on top of it (Q in this case) were removed when the user pressed
+HOME and the task went to the background. So the user sees only P when returning
+to the task.
+
+
+
+If this attribute and allowTaskReparenting
+are both "{@code true}", any activities that can be re-parented are moved to
+the task they share an affinity with; the remaining activities are then dropped,
+as described above.
+
+
+
{@code android:configChanges}
+
Lists configuration changes that the activity will handle itself. When
+changes that are not listed occur, the activity is shut down and restarted.
+When a listed change occurs, the activity remains running and its {@link android.app.Activity#onConfigurationChanged onConfigurationChanged()}
+method is called.
+
+
+Any or all of the following strings can be used to set this attribute. Values are
+separated by '{@code |}' — for example, "{@code locale|navigation|orientation}".
+
+
+
+
+
Value
+
Description
+
+
"{@code mcc}"
+
The IMSI mobile country code (MCC) has changed —
+ that is, a SIM has been detected and updated the MCC.
+
+
"{@code mnc}"
+
The IMSI mobile network code (MNC) has changed —
+ that is, a SIM has been detected and updated the MNC.
+
+
"{@code locale}"
+
The locale has changed — for example, the user has selected a new
+ language that text should be displayed in.
+
+
"{@code touchscreen}"
+
The touchscreen has changed. (This should never normally happen.)
+
+
"{@code keyboard}"
+
The keyboard type has changed — for example, the user has
+ plugged in an external keyboard.
+
+
"{@code keyboardHidden}"
+
The keyboard accessibility has changed — for example, the
+ user has slid the keyboard out to expose it.
+
+
"{@code navigation}"
+
The navigation type has changed. (This should never normally happen.)
+
+
"{@code orientation}"
+
The screen orientation has changed — that is, the user has rotated
+ the device.
+
+
"{@code fontScale}"
+
The font scaling factor has changed — that is, the user has selected
+ a new global font size.
+
+
+
+
+All of these configuration changes can impact the resource values seen by the
+application. Therefore, when {@link android.app.Activity#onConfigurationChanged
+onConfigurationChanged()} is called, it will generally be necessary to again
+retrieve all resources (including view layouts, drawables, and so on) to correctly
+handle the change.
+
+
+
{@code android:enabled}
+
Whether or not the activity can be instantiated by the system —
+"{@code true}" if it can be, and "{@code false}" if not. The default value
+is "{@code true}".
+
+
+The <application> element has its own
+enabled attribute that applies to all
+application components, including activities. The
+<application> and {@code <activity>}
+attributes must both be "{@code true}" (as they both are by default) for
+the system to be able to instantiate the activity. If either is
+"{@code false}", it cannot be instantiated.
+
+
+
{@code android:excludeFromRecents}
+
Whether or not the activity should be excluded from the list of recently
+launched activities that can be displayed to users — "{@code true}" if
+it should be excluded, and "{@code false}" if it should be included.
+The default value is "{@code false}".
+
+
+
{@code android:exported}
+
Whether or not the activity can be launched by components of other
+applications — "{@code true}" if it can be, and "{@code false}" if not.
+If "{@code false}", the activity can be launched only by components of the
+same application or applications with the same user ID.
+
+
+The default value depends on whether the activity contains intent filters. The
+absence of any filters means that the activity can be invoked only by specifying
+its exact class name. This implies that the activity is intended only for
+application-internal use (since others would not know the class name). So in
+this case, the default value is "{@code false}".
+On the other hand, the presence of at least one filter implies that the activity
+is intended for external use, so the default value is "{@code true}".
+
+
+
+This attribute is not the only way to limit an activity's exposure to other
+applications. You can also use a permission to limit the external entities that
+can invoke the activity (see the permission
+attribute).
+
+
+
{@code android:finishOnTaskLaunch}
+
Whether or not an existing instance of the activity should be shut down
+(finished) whenever the user again launches its task (chooses the task on the
+home screen) — "{@code true}" if it should be shut down, and "{@code false}"
+if not. The default value is "{@code false}".
+
+
+If this attribute and allowTaskReparenting
+are both "{@code true}", this attribute trumps the other. The affinity of the
+activity is ignored. The activity is not re-parented, but destroyed.
+
+
+
{@code android:icon}
+
An icon representing the activity. The icon is displayed to users when
+a representation of the activity is required on-screen. For example, icons
+for activities that initiate tasks are displayed in the launcher window.
+The icon is often accompanied by a label (see the {@code label} attribute).
+
+
+
+This attribute must be set as a reference to a drawable resource containing
+the image definition. If it is not set, the icon specified for the application
+as a whole is used instead (see the <application>
+element's icon attribute).
+
+
+
+The activity's icon — whether set here or by the
+<application> element — is also the
+default icon for all the activity's intent filters (see the
+<intent-filter> element's
+icon attribute).
+
+
+
{@code android:label}
+
A user-readable label for the activity. The label is displayed on-screen
+when the activity must be represented to the user. It's often displayed along
+with the activity icon.
+
+
+If this attribute is not set, the label set for the application as a whole is
+used instead (see the <application> element's
+label attribute).
+
+
+
+The activity's label — whether set here or by the
+<application> element — is also the
+default label for all the activity's intent filters (see the
+<intent-filter> element's
+label attribute).
+
+
+
+The label should be set as a reference to a string resource, so that
+it can be localized like other strings in the user interface.
+However, as a convenience while you're developing the application,
+it can also be set as a raw string.
+
+
+
{@code android:launchMode}
+
An instruction on how the activity should be launched. There are four modes
+that work in conjunction with activity flags ({@code FLAG_ACTIVITY_*} constants)
+in {@link android.content.Intent} objects to determine what should happen when
+the activity is called upon to handle an intent. They are:
+
+
+The modes fall into two main groups, with "{@code standard}" and
+"{@code singleTop}" activities on one side, and "{@code singleTask}" and
+"{@code singleInstance}" activities on the other. An activity with the
+"{@code standard}" or "{@code singleTop}" launch mode can be instantiated
+multiple times. The instances can belong to any task and can be located
+anywhere in the activity stack. Typically, they're launched into the task
+that called
+{@link android.content.Context#startActivity startActivity()}
+(unless the Intent object contains a
+{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}
+instruction, in which case a different task is chosen — see the
+taskAffinity attribute).
+
+
+
+In contrast, "{@code singleTask}" and "{@code singleInstance}" activities
+can only begin a task. They are always at the root of the activity stack.
+Moreover, the device can hold only one instance of the activity at a time
+— only one such task.
+
+
+
+The "{@code standard}" and "{@code singleTop}" modes differ from each other
+in just one respect: Every time there's new intent for a "{@code standard}"
+activity, a new instance of the class is created to respond to that intent.
+Each instance handles a single intent.
+Similarly, a new instance of a "{@code singleTop}" activity may also be
+created to handle a new intent. However, if the target task already has an
+existing instance of the activity at the top of its stack, that instance
+will receive the new intent (in an
+{@link android.app.Activity#onNewIntent onNewIntent()} call);
+a new instance is not created.
+In other circumstances — for example, if an existing instance of the
+"{@code singleTop}" activity is in the target task, but not at the top of
+the stack, or if it's at the top of a stack, but not in the target task
+— a new instance would be created and pushed on the stack.
+
+
+
+The "{@code singleTask}" and "{@code singleInstance}" modes also differ from
+each other in only one respect: A "{@code singleTask}" activity allows other
+activities to be part of its task. It's at the root of the activity stack,
+but other activities (necessarily "{@code standard}" and "{@code singleTop}"
+activities) can be launched into the same task. A "{@code singleInstance}"
+activity, on the other hand, permits no other activities to be part of its
+task. It's the only activity in the task. If it starts another activity,
+that activity is assigned to a different task — as if {@code
+FLAG_ACTIVITY_NEW_TASK} was in the intent.
+
Whether an instance of the activity can be launched into the process of the component
+that started it — "{@code true}" if it can be, and "{@code false}" if not.
+The default value is "{@code false}".
+
+
+Normally, a new instance of an activity is launched into the process of the
+application that defined it, so all instances of the activity run in the same
+process. However, if this flag is set to "{@code true}", instances of the
+activity can run in multiple processes, allowing the system to create instances
+wherever they are used (provided permissions allow it), something that is almost
+never necessary or desirable.
+
+
+
{@code android:name}
+
The name of the class that implements the activity, a subclass of
+{@link android.app.Activity}. The attribute value should be a fully qualified
+class name (such as, "{@code com.example.project.ExtracurricularActivity}").
+However, as a shorthand, if the first character of the name is a period
+(for example, "{@code .ExtracurricularActivity}"), it is appended to the
+package name specified in the
+<manifest>
+element.
+
+
+There is no default. The name must be specified.
+
+
+
{@code android:permission}
+
The name of a permission that clients must have to launch the activity
+or otherwise get it to respond to an intent. If a caller of
+{@link android.content.Context#startActivity startActivity()} or
+{@link android.app.Activity#startActivityForResult startActivityForResult()}
+has not been granted the specified permission, its intent will not be
+delivered to the activity.
+
+
+If this attribute is not set, the permission set by the
+<application> element's
+permission attribute applies
+to the activity. If neither attribute is set, the activity is
+not protected by a permission.
+
The name of the process in which the activity should run. Normally,
+all components of an application run in the default process created for the
+application. It has the same name as the application package. The <application> element's
+process attribute can set a different
+default for all components. But each component can override the default,
+allowing you to spread your application across multiple processes.
+
+
+If the name assigned to this attribute begins with a colon (':'), a new
+process, private to the application, is created when it's needed and
+the activity runs in that process.
+If the process name begins with a lowercase character, the activity will run
+in a global process of that name, provided that it has permission to do so.
+This allows components in different applications to share a process, reducing
+resource usage.
+
+
+
{@code android:screenOrientation}
+
The orientation of the activity's display on the device.
+The value can be any one of the following strings:
+
+
+
+
"{@code unspecified}"
+
The default value. The system chooses the orientation. The policy it
+ uses, and therefore the choices made in specific contexts, may differ
+ from device to device.
+
+
"{@code landscape}"
+
Landscape orientation (the display is wider than it is tall).
+
+
"{@code portrait}"
+
Portrait orientation (the display is taller than it is wide).
+
+
"{@code user}"
+
The user's current preferred orientation.
+
+
"{@code behind}"
+
The same orientation as the activity that's immediately beneath it in
+ the activity stack.
+
+
"{@code sensor}"
+
The orientation determined by a physical orientation sensor. The
+ orientation of the display depends on how the user is holding the device;
+ it changes when the user rotates the device.
+
+
"{@code nosensor}"
+
An orientation determined without reference to a physical orientation sensor.
+ The sensor is ignored, so the display will not rotate based on how the user
+ moves the device. Except for this distinction, the system chooses the
+ orientation using the same policy as for the "{@code unspecified}" setting.
+
+
+
+
{@code android:stateNotNeeded}
+
Whether or not the activity can be killed and successfully restarted
+without having saved its state — "{@code true}" if it can be restarted
+without reference to its previous state, and "{@code false}" if its previous
+state is required. The default value is "{@code false}".
+
+
+Normally, before an activity is temporarily shut down to save resources, its
+{@link android.app.Activity#onSaveInstanceState onSaveInstanceState()}
+method is called. This method stores the current state of the activity in a
+{@link android.os.Bundle} object, which is then passed to
+{@link android.app.Activity#onCreate onCreate()} when the activity
+is restarted. If this attribute is set to "{@code true}",
+{@code onSaveInstanceState()} may not be called and {@code onCreate()} will
+be passed {@code null} instead of the Bundle — just as it was when the
+activity started for the first time.
+
+
+
+A "{@code true}" setting ensures that the activity can be restarted in the
+absence of retained state. For example, the activity that displays the
+home screen uses this setting to make sure that it does not get removed if it
+crashes for some reason.
+
+
+
{@code android:taskAffinity}
+
The task that the activity has an affinity for. Activities with
+the same affinity conceptually belong to the same task (to the same
+"application" from the user's perspective). The affinity of a task
+is determined by the affinity of its root activity.
+
+
+The affinity determines two things — the task that the activity is re-parented
+to (see the allowTaskReparenting
+attribute) and the task that will house the activity when it is launched
+with the {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}
+flag.
+
+
+
+By default, all activities in an application have the same affinity. You
+can set this attribute to group them differently, and even place
+activities defined in different applications within the same task. To
+specify that the activity does not have an affinity for any task, set
+it to an empty string.
+
+
+If this attribute is not set, the activity inherits the affinity set
+for the application (see the <application>
+element's taskAffinity attribute).
+The name of the default affinity for an application is the package name set
+by the <manifest> element.
+
+
+
{@code android:theme}
+
A reference to a style resource defining an overall theme for the activity.
+This automatically sets the activity's context to use this theme (see
+{@link android.content.Context#setTheme setTheme()}, and may also
+cause "starting" animations prior to the activity being launched (to better
+match what the activity actually looks like).
+
+
+If this attribute is not set, the activity inherits the theme set for the
+application as a whole — see the <application>
+element's theme attribute. If that attribute is
+also not set, the default system theme is used.
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/html/guide/topics/manifest/application-element.jd b/docs/html/guide/topics/manifest/application-element.jd
new file mode 100644
index 0000000000000..362c205880f9f
--- /dev/null
+++ b/docs/html/guide/topics/manifest/application-element.jd
@@ -0,0 +1,226 @@
+page.title=<application>
+@jd:body
+
+
The declaration of the application. This element contains subelements
+that declare each of the application's components and has attributes
+that can affect all the components. Many of these attributes (such as
+{@code icon}, {@code label}, {@code permission}, {@code process},
+{@code taskAffinity}, and {@code allowTaskReparenting}) set default values
+for corresponding attributes of the component elements. Others (such as
+{@code debuggable}, {@code enabled}, {@code description}, and
+{@code allowClearUserData}) set values for the application as a whole and
+cannot be overridden by the components.
+
+
attributes
+
+
{@code android:allowClearUserData}
+
Whether or not users are given the option to remove user data —
+"{@code true}" if they are, and "{@code false}" if not. If the value is
+"{@code true}", as it is by default, the application manager includes an
+option that allows users to clear the data.
+
+
{@code android:allowTaskReparenting}
+
Whether or not activities that the application defines can move from
+the task that started them to the task they have an affinity for when that task
+is next brought to the front — "{@code true}" if they can move, and
+"{@code false}" if they must remain with the task where they started.
+The default value is "{@code false}".
+
+
+The
+<activity>
+element has its own
+allowTaskReparenting
+attribute that can override the value set here. See that attribute for more
+information.
+
+
+
{@code android:debuggable}
+
Whether or not the application can be debugged, even when running
+on a device in user mode — "{@code true}" if it can be, and "{@code false}"
+if not. The default value is "{@code false}".
+
+
{@code android:description}
+
User-readable text about the application, longer and more descriptive than the application label. The value must be set as a reference to a string resource. Unlike the label, it cannot be a raw string. There is no default value.
+
+
{@code android:enabled}
+
Whether or not the Android system can instantiate components of
+the application — "{@code true}" if it can, and "{@code false}"
+if not. If the value is "{@code true}", each component's
+{@code enabled} attribute determines whether that component is enabled
+or not. If the value is "{@code false}", it overrides the
+component-specific values; all components are disabled.
+
+
+The default value is "{@code true}".
+
+
+
{@code android:hasCode}
+
Whether or not the application contains any code — "{@code true}"
+if it does, and "{@code false}" if not. When the value is "{@code false}",
+the system does not try to load any application code when launching components.
+The default value is "{@code true}".
+
+
+An application would not have any code of its own only if it's using nothing
+but built-in component classes, such as an activity that uses the {@link
+android.app.AliasActivity} class, a rare occurrence.
+
+
{@code android:icon}
+
An icon for the application as whole, and the default icon for
+each of the application's components. See the individual
+{@code icon} attributes for
+<activity>,
+<activity-alias>,
+<service>,
+<receiver>, and
+<provider> elements.
+
+
+This attribute must be set as a reference to a drawable resource containing
+the image definition. There is no default icon.
+
+
+
{@code android:label}
+
A user-readable label for the application as a whole, and a default
+label for each of the application's components. See the individual
+{@code label} attributes for
+<activity>,
+<activity-alias>,
+<service>,
+<receiver>, and
+<provider> elements.
+
+
+The label should be set as a reference to a string resource, so that
+it can be localized like other strings in the user interface.
+However, as a convenience while you're developing the application,
+it can also be set as a raw string.
+
+
+
{@code android:manageSpaceActivity}
+
The fully qualified name of an Activity subclass that the system
+can launch to let users manage the memory occupied by the application
+on the device. The activity should also be declared with an
+<activity> element.
+
+
+
{@code android:name}
+
The fully qualified name of an {@link android.app.Application}
+subclass implemented for the application. When the application process
+is started, this class is instantiated before any of the application's
+components.
+
+
+The subclass is optional; most applications won't need one.
+In the absence of a subclass, Android uses an instance of the base
+Application class.
+
+
+
{@code android:permission}
+
The name of a permission that clients must have in order to interact
+with the application. This attribute is a convenient way to set a
+permission that applies to all of the application's components. It can
+be overwritten by setting the {@code permission} attributes of individual
+components.
+
+
Whether or not the application should remain running at all times —
+"{@code true}" if it should, and "{@code false}" if not. The default value
+is "{@code false}". Applications should not normally set this flag;
+persistence mode is intended only for certain system applications.
+
+
{@code android:process}
+
The name of a process where all components of the application should run.
+Each component can override this default by setting its own {@code process}
+attribute.
+
+
+By default, Android creates a process for an application when the first
+of its components needs to run. All components then run in that process.
+The name of the default process matches the package name set by the
+<manifest> element.
+
+
+
By setting this attribute to a process name that's shared with another
+application, you can arrange for components of both applications to run in
+the same process — but only if the two applications also share a
+user ID and be signed with the same certificate.
+
+
+
+If the name assigned to this attribute begins with a colon (':'), a new
+process, private to the application, is created when it's needed.
+If the process name begins with a lowercase character, a global process
+of that name is created. A global process can be shared with other
+applications, reducing resource usage.
+
+
+
{@code android:taskAffinity}
+
An affinity name that applies to all activities within the application,
+except for those that set a different affinity with their own
+taskAffinity
+attributes. See that attribute for more information.
+
+
+By default, all activities within an application share the same
+affinity. The name of that affinity is the same as the package name
+set by the
+<manifest> element.
+
+
+
{@code android:theme}
+
A reference to a style resource defining a default theme for all
+activities in the application. Individual activities can override
+the default by setting their own theme
+attributes; see that attribute for more information.
Adds a category name to an intent filter. See
+Intents and
+Intent Filters for details on intent filters and the role of category
+specifications within a filter.
+
+
attributes:
+
+
{@code android:name}
+
The name of the category. Standard categories are defined in the
+{@link android.content.Intent} class as {@code CATEGORY_name}
+constants. The name assigned here can be derived from those constants
+by prefixing "{@code android.intent.category.}" to the
+{@code name} that follows {@code CATEGORY_}. For example,
+the string value for {@code CATEGORY_LAUNCHER} is
+"{@code android.intent.category.LAUNCHER}".
+
+
+Custom categories should use the package name as a prefix, to ensure
+that they are unique.
+
Adds a data specification to an intent filter. The specification can
+be just a data type (the mimeType attribute),
+just a URI, or both a data type and a URI. A URI is specified by separate
+attributes for each of its parts:
+
+
{@code scheme://host:port/path} or
+{@code pathPrefix} or {@code pathPattern}
+
+
+These attributes are optional, but also mutually dependent:
+If a scheme is not specified for the
+intent filter, all the other URI attributes are ignored. If a
+host is not specified for the filer,
+the {@code port} attribute and all the path attributes are ignored.
+
+
+
+All the {@code <data>} elements contained within the same
+<intent-filter> element contribute to
+the same filter. So, for example, the following filter specification,
+
+You can place any number of <data> elements inside an
+<intent-filter> to give it multiple data
+options. None of its attributes have default values.
+
+
+
+Information on how intent filters work, including the rules for how Intent objects
+are matched against filters, can be found in another document,
+Intents and
+Intent Filters. See also the
+Intent Filters
+section in the introduction.
+
+
+
attributes:
+
+
{@code android:host}
+
The host part of a URI authority. This attribute is meaningless
+unless a scheme attribute is also
+specified for the filter.
+
+
+
{@code android:mimeType}
+
A MIME media type, such as {@code image/jpeg} or {@code audio/mpeg4-generic}.
+The subtype can be the asterisk wildcard ({@code *}) to indicate that any
+subtype matches.
The path part of a URI. The {@code path} attribute specifies a complete
+path that is matched against the complete path in an Intent object. The
+{@code pathPrefix} attribute specifies a partial path that is matched against
+only the initial part of the path in the Intent object. The {@code pathPattern}
+attribute specifies a complete path that is matched against the complete path
+in the Intent object, but it can contain the following wildcards:
+
+
+
An asterisk ('{@code *}') matches a sequence of 0 to many occurrences of
+the immediately preceding character.
+
+
A period followed by an asterisk ("{@code .*}") matches any sequence of
+0 to many characters.
+
+
+
+Because '{@code \}' is used as an escape character when the string is read
+from XML (before it is parsed as a pattern), you will need to double-escape:
+For example, a literal '{@code *}' would be written as "{@code \\*}" and a
+literal '{@code \}' would be written as "{@code \\\\}". This is basically
+the same as what you would need to write if constructing the string in Java code.
+
+
+
+For more information on these three types of patterns, see the descriptions of
+{@link android.os.PatternMatcher#PATTERN_LITERAL},
+{@link android.os.PatternMatcher#PATTERN_PREFIX}, and
+{@link android.os.PatternMatcher#PATTERN_SIMPLE_GLOB} in the
+{@link android.os.PatternMatcher} class.
+
+
+
These attributes are meaningful only if the
+scheme and host
+attributes are also specified for the filter.
+
+
+
{@code android:port}
+
The port part of a URI authority. This attribute is meaningful only
+if the scheme and
+host attributes are also specified for
+the filter.
+
+
{@code android:scheme}
+
The scheme part of a URI. This is the minimal essential attribute for
+specifying a URI; at least one {@code scheme} attribute must be set
+for the filter, or none of the other URI attributes are meaningful.
+
+
+A scheme is specified without the trailing colon (for example,
+{@code http}, rather than {@code http:}).
+
+
+
+If the filter has a data type set (the mimeType
+attribute) but no scheme, the {@code content:} and {@code file:} schemes are
+assumed.
+
Specifies which data subsets of the parent content provider permission
+can be granted for. Data subsets are indicated by the path part of a
+{@code content:} URI. (The authority part of the URI identifies the
+content provider.)
+Granting permission is a way of enabling clients of the provider that don't
+normally have permission to access its data to overcome that restriction on
+a one-time basis.
+
+
+If a content provider's grantUriPermissions
+attribute is "{@code true}", permission can be granted for any the data under
+the provider's purview. However, if that attribute is "{@code false}", permission
+can be granted only to data subsets that are specified by this element.
+A provider can contain any number of {@code <grant-uri-permission>} elements.
+Each one can specify only one path (only one of the three possible attributes).
+
A path identifying the data subset or subsets that permission can be
+granted for. The {@code path} attribute specifies a complete path;
+permission can be granted only to the particular data subset identified
+by that path.
+The {@code pathPrefix} attribute specifies the initial part of a path;
+permission can be granted to all data subsets with paths that share that
+initial part.
+The {@code pathPattern} attribute specifies a complete path, but one
+that can contain the following wildcards:
+
+
+
An asterisk ('{@code *}') matches a sequence of 0 to many occurrences of
+the immediately preceding character.
+
+
A period followed by an asterisk ("{@code .*}") matches any sequence of
+0 to many characters.
+
+
+
+Because '{@code \}' is used as an escape character when the string is read
+from XML (before it is parsed as a pattern), you will need to double-escape:
+For example, a literal '{@code *}' would be written as "{@code \\*}" and a
+literal '{@code \}' would be written as "{@code \\\\}". This is basically
+the same as what you would need to write if constructing the string in Java code.
+
+
+
+For more information on these types of patterns, see the descriptions of
+{@link android.os.PatternMatcher#PATTERN_LITERAL},
+{@link android.os.PatternMatcher#PATTERN_PREFIX}, and
+{@link android.os.PatternMatcher#PATTERN_SIMPLE_GLOB} in the
+{@link android.os.PatternMatcher} class.
+
Declares an {@link android.app.Instrumentation} class that enables you
+to monitor an application's interaction with the system. The Instrumentation
+object is instantiated before any of the application's components.
+
+
attributes:
+
+
{@code android:functionalTest}
+
Whether or not the Instrumentation class should run as a functional test
+— "{@code true}" if it should, and "{@code false}" if not. The
+default value is "{@code false}".
+
+
{@code android:handleProfiling}
+
Whether or not the Instrumentation object will turn profiling on and
+off — "{@code true}" if it determines when profiling starts and
+stops, and "{@code false}" if profiling continues the entire time it is
+running. A value of "{@code true}" enables the object to target profiling
+at a specific set of operations. The default value is "{@code false}".
+
+
{@code android:icon}
+
An icon that represents the Instrumentation class. This attribute must
+be set as a reference to a drawable resource.
+
+
{@code android:label}
+
A user-readable label for the Instrumentation class. The label can
+be set as a raw string or a reference to a string resource.
+
+
{@code android:name}
+
The name of the {@link android.app.Instrumentation} subclass.
+This should be a fully qualified class name (such as,
+"{@code com.example.project.StringInstrumentation}"). However, as a shorthand,
+if the first character of the name is a period, it is appended to the package
+name specified in the <manifest> element.
+
+
+There is no default. The name must be specified.
+
+
+
{@code android:targetPackage}
+
The application that the Instrumentation object will run against.
+An application is identified by the package name assigned in its manifest
+file by the <manifest> element.
Specifies the types of intents that an activity, service, or broadcast
+receiver can respond to. An intent filter declares the capabilities of its
+parent component — what an activity or service can do and what types
+of broadcasts a receiver can handle. It opens the component to receiving
+intents of the advertised type, while filtering out those that are not
+meaningful for the component.
+
+
+Most of the contents of the filter are described by its
+<action>,
+<category>, and
+<data> subelements.
+
An icon that represents the parent activity, service, or broadcast
+receiver when that component is presented to the user as having the
+capability described by the filter.
+
+
+This attribute must be set as a reference to a drawable resource
+containing the image definition. The default value is the icon set
+by the parent component's {@code icon} attribute. If the parent
+does not specify an icon, the default is the icon set by the
+<application> element.
+
+
+
+For more on intent filter icons, see
+Icons and Labels
+in the introduction.
+
+
+
{@code android:label}
+
A user-readable label for the parent component. This label, rather than
+the one set by the parent component, is used when the component is presented
+to the user as having the capability described by the filter.
+
+
+The label should be set as a reference to a string resource, so that
+it can be localized like other strings in the user interface.
+However, as a convenience while you're developing the application,
+it can also be set as a raw string.
+
+
+
+The default value is the label set by the parent component. If the
+parent does not specify a label, the default is the label set by the
+<application> element's
+ label attribute.
+
+
+
+For more on intent filter labels, see
+Icons and Labels
+in the introduction.
+
+
+
{@code android:priority}
+
The priority that should be given to the parent component with regard
+to handling intents of the type described by the filter. This attribute has
+meaning for both activities and broadcast receivers:
+
+
+
It provides information about how able an activity is to respond to
+an intent that matches the filter, relative to other activities that could
+also respond to the intent. When an intent could be handled by multiple
+activities with different priorities, Android will consider only those with
+higher priority values as potential targets for the intent.
+
+
It controls the order in which broadcast receivers are executed to
+receive broadcast messages. Those with higher priority
+values are called before those with lower values. (The order applies only
+to synchronous messages; it's ignored for asynchronous messages.)
+
+
+
+Use this attribute only if you really need to impose a specific order in
+which the broadcasts are received, or want to force Android to prefer
+one activity over others.
+
+
+
+The value must be an integer, such as "{@code 100}". Higher numbers have a
+higher priority.
+
The root element of the AndroidManifest.xml file. It must
+contain an <application> element
+and specify {@code xlmns:android} and {@code package} attributes.
+
+
attributes:
+
+
{@code xmlns:android}
+
Defines the Android namespace. This attribute should always be set
+to "{@code http://schemas.android.com/apk/res/android}".
+
+
{@code package}
+
A full Java package name for the application. The name should
+be unique. For example, applications published by Google could have
+names in the form com.google.app.application_name.
+
+
+The package name serves as a unique identifier for the application.
+It's also the default name for the application process (see the
+<application>
+element's
+process
+process attribute) and the default task affinity of an activity
+(see the
+<activity>
+element's
+taskAffinity attribute).
+
+
+
{@code android:sharedUserId}
+
The name of a Linux user ID that will be shared with other applications.
+By default, Android assigns each application its own unique user ID.
+However, if this attribute is set to the same value for two or more applications,
+they will all share the same ID — provided that they are also signed
+by the same certificate. Application with the same user ID can access each
+other's data and, if desired, run in the same process.
+
+
{@code android:versionCode}
+
An internal version number. This number is used only to determine whether
+one version is more recent than another, with higher numbers indicating more
+recent versions. This is not the version number shown to users; that number
+is set by the {@code versionName} attribute.
+
+
+The value must be set as an integer, such as "100". You can define it however
+you want, as long as each successive version has a higher number. For example,
+it could be a build number. Or you could translate a version number in "x.y"
+format to an integer by encoding the "x" and "y" separately in the lower and
+upper 16 bits. Or you could simply increase the number by one each time a new
+version is released.
+
+
+
{@code android:versionName}
+
The version number shown to users. This attribute can be set as a raw
+string or as a reference to a string resource. The string has no other purpose
+than to be displayed to users. The {@code versionCode} attribute holds
+the significant version number used internally.
+
+Every application must have an AndroidManifest.xml file (with precisely that
+name) in its root directory. The manifest presents essential information about
+the application to the Android system, information the system must have before
+it can run any of the application's code. Among other things, the manifest
+does the following:
+
+
+
+
It names the Java package for the application.
+The package name serves as a unique identifier for the application.
+
+
It describes the components of the application — the activities,
+services, broadcast receivers, and content providers that the application is
+composed of. It names the classes that implement each of the components and
+publishes their capabilities (for example, which {@link android.content.Intent
+Intent} messages they can handle). These declarations let the Android system
+know what the components are and under what conditions they can be launched.
+
+
It determines which processes will host application components.
+
+
It declares which permissions the application must have in order to
+access protected parts of the API and interact with other applications.
+
+
It also declares the permissions that others are required to have in
+order to interact with the application's components.
+
+
It lists the {@link android.app.Instrumentation} classes that provide
+profiling and other information as the application is running. These declarations
+are present in the manifest only while the application is being developed and
+tested; they're removed before the application is published.
+
+
It declares the minimum version of the Android API that the application
+requires.
+
+
It lists the libraries that the application must be linked against.
+
+
+
+
Structure of the Manifest File
+
+
+The diagram below shows the general structure of the manifest file and
+every element that it can contain. Each element, along with all of its
+attributes, is documented in full in a separate file. To view detailed
+information about any element, click on the element name in the diagram,
+in the alphabetical list of elements that follows the diagram, or on any
+other mention of the element name.
+
+All the elements that can appear in the manifest file are listed below
+in alphabetical order. These are the only legal elements; you cannot
+add your own elements or attributes.
+
+Some conventions and rules apply generally to all elements and attributes
+in the manifest:
+
+
+
+
Elements
+
Only the
+<manifest> and
+<application>
+elements are required, they each must be present and can occur only once.
+Most of the others can occur many times or not at all — although at
+least some of them must be present for the manifest to accomplish anything
+meaningful.
+
+
+If an element contains anything at all, it contains other elements.
+All values are set through attributes, not as character data within an element.
+
+
+
+Elements at the same level are generally not ordered. For example,
+<activity>,
+<provider>, and
+<service>
+elements can be intermixed in any sequence. (An
+<activity-alias>
+element is the exception to this rule: It must follow the
+<activity>
+it is an alias for.)
+
+
+
Attributes
+
In a formal sense, all attributes are optional. However, there are some
+that must be specified for an element to accomplish its purpose. Use the
+documentation as a guide. For truly optional attributes, it mentions a default
+value or states what happens in the absence of a specification.
+
+
Except for some attributes of the root
+<manifest>
+element, all attribute names begin with an {@code android:} prefix —
+for example, {@code android:alwaysRetainTaskState}. Because the prefix is
+universal, the documentation generally omits it when referring to attributes
+by name.
+
+
Declaring class names
+
Many elements correspond to Java objects, including elements for the
+application itself (the
+<application>
+element) and its principal components — activities
+(<activity>),
+services
+(<service>),
+broadcast receivers
+(<receiver>),
+and content providers
+(<provider>).
+
+
+If you define a subclass, as you almost always would for the component classes
+({@link android.app.Activity}, {@link android.app.Service},
+{@link android.content.BroadcastReceiver}, and {@link android.content.ContentProvider}),
+the subclass is declared through a {@code name} attribute. The name must include
+the full package designation.
+For example, an {@link android.app.Service} subclass might be declared as follows:
+
+However, as a shorthand, if the first character of the string is a period, the
+string is appended to the application's package name (as specified by the
+<manifest>
+element's
+package
+attribute). The following assignment is the same as the one above:
+
+When starting a component, Android creates an instance of the named subclass.
+If a subclass isn't specified, it creates an instance of the base class.
+
+
+
Multiple values
+
If more than one value can be specified, the element is almost always
+repeated, rather than listing multiple values within a single element.
+For example, an intent filter can list several actions:
+
+
Some attributes have values that can be displayed to users — for
+example, a label and an icon for an activity. The values of these attributes
+should be localized and therefore set from a resource or theme. Resource
+values are expressed in the following format,
+
+
{@code @[package:]type:name}
+
+
+where the package name can be omitted if the resource is in the same package
+as the application, type is a type of resource — such as "string" or
+"drawable" — and name is the name that identifies the specific resource.
+For example:
+
+Values from a theme are expressed in a similar manner, but with an initial '{@code ?}'
+rather than '{@code @}':
+
+
+
{@code ?[package:]type:name}
+
+
+
String values
+
Where an attribute value is a string, double backslashes ('{@code \\}')
+must be used to escape characters — for example, '{@code \\n}' for
+a newline or '{@code \\uxxxx}' for a Unicode character.
+
+
+
+
File Features
+
+
+The following sections describe how some Android features are reflected
+in the manifest file.
+
+
+
+
Intent Filters
+
+
+The core components of an application (its activities, services, and broadcast
+receivers) are activated by intents. An intent is a
+bundle of information (an {@link android.content.Intent} object) describing a
+desired action — including the data to be acted upon, the category of
+component that should perform the action, and other pertinent instructions.
+Android locates an appropriate component to respond to the intent, launches
+a new instance of the component if one is needed, and passes it the
+Intent object.
+
+
+
+Components advertise their capabilities — the kinds of intents they can
+respond to — through intent filters. Since the Android system
+must learn which intents a component can handle before it launches the component,
+intent filters are specified in the manifest as
+<intent-filter>
+elements. A component may have any number of filters, each one describing
+a different capability.
+
+
+
+An intent that explicitly names a target component will activate that component;
+the filter doesn't play a role. But an intent that doesn't specify a target by
+name can activate a component only if it can pass through one of the component's
+filters.
+
+
+
+For information on how Intent objects are tested against intent filters,
+see a separate document,
+Intents
+and Intent Filters.
+
+
+
+
Icons and Labels
+
+
+A number of elements have {@code icon} and {@code label} attributes for a
+small icon and a text label that can be displayed to users. Some also have a
+{@code description} attribute for longer explanatory text that can also be
+shown on-screen. For example, the
+<permission>
+element has all three of these attributes, so that when the user is asked whether
+to grant the permission to an application that has requested it, an icon representing
+the permission, the name of the permission, and a description of what it
+entails can all be presented to the user.
+
+
+
+In every case, the icon and label set in a containing element become the default
+{@code icon} and {@code label} settings for all of the container's subelements.
+Thus, the icon and label set in the
+<application>
+element are the default icon and label for each of the application's components.
+Similarly, the icon and label set for a component — for example, an
+<activity>
+element — are the default settings for each of the component's
+<intent-filter>
+elements. If an
+<application>
+element sets a label, but an activity and its intent filter do not,
+the application label is treated as the label for both the activity and
+the intent filter.
+
+
+
+The icon and label set for an intent filter are used to represent a component
+whenever the component is presented to the user as fulfilling the function
+advertised by the filter. For example, a filter with
+"{@code android.intent.action.MAIN}" and
+"{@code android.intent.category.LAUNCHER}" settings advertises an activity
+as one that initiates an application — that is, as
+one that should be displayed in the application launcher. The icon and label
+set in the filter are therefore the ones displayed in the launcher.
+
+
+
+
Permissions
+
+
+A permission is a restriction limiting access to a part of the code
+or to data on the device. The limitation is imposed to protect critical
+data and code that could be misused to distort or damage the user experience.
+
+
+
+Each permission is identified by a unique label. Often the label indicates
+the action that's restricted. For example, here are some permissions defined
+by Android:
+
+A feature can be protected by at most one permission.
+
+
+
+If an application needs access to a feature protected by a permission,
+it must declare that it requires that permission with a
+<uses-permission>
+element in the manifest. Then, when the application is installed on
+the device, the installer determines whether or not to grant the requested
+permission by checking the authorities that signed the application's
+certificates and, in some cases, asking the user.
+If the permission is granted, the application is able to use the protected
+features. If not, its attempts to access those features will simply fail
+without any notification to the user.
+
+
+
+An application can also protect its own components (activities, services,
+broadcast receivers, and content providers) with permissions. It can employ
+any of the permissions defined by Android (listed in
+{@link android.Manifest.permission android.Manifest.permission}) or declared
+by other applications. Or it can define its own. A new permission is declared
+with the
+<permission>
+element. For example, an activity could be protected as follows:
+
+Note that, in this example, the {@code DEBIT_ACCT} permission is not only
+declared with the
+<permission>
+element, its use is also requested with the
+<uses-permission>
+element. Its use must be requested in order for other components of the
+application to launch the protected activity, even though the protection
+is imposed by the application itself.
+
+
+
+If, in the same example, the {@code permission} attribute was set to a
+permission declared elsewhere
+(such as {@code android.permission.CALL_EMERGENCY_NUMBERS}, it would not
+have been necessary to declare it again with a
+<permission>
+element. However, it would still have been necessary to request its use with
+<uses-permission>.
+
+
+
+The
+<permission-tree>
+element declares a namespace for a group of permissions that will be defined in
+code. And
+<permission-group>
+defines a label for a set of permissions (both those declared in the manifest with
+<permission>
+elements and those declared elsewhere). It affects only how the permissions are
+grouped when presented to the user. The
+<permission-group>
+element does not specify which permissions belong to the group;
+it just gives the group a name. A permission is placed in the group
+by assigning the group name to the
+<permission>
+element's
+permissionGroup
+attribute.
+
+
+
+
Libraries
+
+
+Every application is linked against the default Android library, which
+includes the basic packages for building applications (with common classes
+such as Activity, Service, Intent, View, Button, Application, ContentProvider,
+and so on).
+
+
+
+However, some packages reside in their own libraries. If your application
+uses code from any of these packages, it must explicitly asked to be linked
+against them. The manifest must contain a separate
+<uses-library>
+element to name each of the libraries. (The library name can be found in the
+documentation for the package.)
+
-Every application must have an AndroidManifest.xml file (with precisely that
-name) in its root directory. The manifest presents essential information about
-the application to the Android system, information the system must have before
-it can run any of the application's code. Among other things, the manifest
-does the following:
-
-
-
-
It names the Java package for the application.
-The package name serves as a unique identifier for the application.
-
-
It describes the components of the application — the activities,
-services, broadcast receivers, and content providers that the application is
-composed of. It names the classes that implement each of the components and
-publishes their capabilities (for example, which {@link android.content.Intent
-Intent} messages they can handle). These declarations let the Android system
-know what the components are and under what conditions they can be launched.
-
-
It determines which processes will host application components.
-
-
It declares which permissions the application must have in order to
-access protected parts of the API and interact with other applications.
-
-
It also declares the permissions that others are required to have in
-order to interact with the application's components.
-
-
It lists the {@link android.app.Instrumentation} classes that provide
-profiling and other information as the application is running. These declarations
-are present in the manifest only while the application is being developed and
-tested; they're removed before the application is published.
-
-
It declares the minimum version of the Android API that the application
-requires.
-
-
It lists the libraries that the application must be linked against.
-
-
-
-
Structure of the Manifest File
-
-
-A later section of this document, "Elements of the Manifest
-File", describes all of the elements that can appear in the manifest file
-and each of their attributes. The diagram below shows the general structure of
-the file and every element it can contain.
-
-Some conventions and rules apply generally to all elements and attributes
-in the manifest:
-
-
-
-
Elements
-
Only the {@code <manifest>} and
-{@code <application>} elements are required, they each
-must be present and can occur only once. Most of the others can occur many times
-or not at all — although at least some of them must be present for the
-manifest to accomplish anything meaningful.
-
-
-If an element contains anything at all, it contains other elements.
-All values are set through attributes, not as character data within an element.
-
-
-
-Elements at the same level are generally not ordered. For example,
-{@code <activity>},
-{@code <provider>}, and
-{@code <service>} elements can be intermixed in
-any sequence. (An {@code <activity-alias>} is the
-exception to this rule: It must follow the {@code <activity>}
-it is an alias for.)
-
-
Attributes
-
In a formal sense, all attributes are optional. However, there are some
-that must be specified for an element to accomplish its purpose. Use the
-documentation as a guide. For truly optional attributes, it mentions a default
-value or states what happens in the absence of a specification.
-
-
Except for some attributes of
-the root {@code <manifest>} element,
-all attribute names begin with an {@code android:} prefix —
-for example, {@code android:alwaysRetainTaskState}. Because the prefix is
-universal, this documentation generally omits it when referring to attributes
-by name.
-
-
Declaring class names
-
Many elements correspond to Java objects, including elements for the
-application itself (the {@code <application>} element)
-and its principal components —
-activities ({@code <activity>}),
-services ({@code <service>}),
-broadcast receivers ({@code <receiver>}),
-and content providers ({@code <provider>}).
-
-
-If you define a subclass, as you almost always would for the component classes
-({@link android.app.Activity}, {@link android.app.Service},
-{@link android.content.BroadcastReceiver},
-and {@link android.content.ContentProvider}), the subclass is declared through
-a {@code name} attribute. The name must include the full package designation.
-For example, an {@link android.app.Service} subclass might be declared as follows:
-
-However, as a shorthand, if the first character of the string is a period, the
-string is appended to the application's package name (as specified by the
-{@code <manifest>} element's
-{@code package} attribute). The following assignment
-is the same as the one above:
-
-When starting a component, Android creates an instance of the named subclass.
-If a subclass isn't specified, it creates an instance of the base class.
-
-
-
Multiple values
-
If more than one value can be specified, the element is almost always repeated,
-rather than listing multiple values within a single element.
-For example, an intent filter can list several actions:
-
-
Some attributes have values that can be displayed to users — for
-example, a label and an icon for an activity. The values of these attributes
-should be localized and therefore set from a resource or theme. Resource values
-are expressed in the following format,
-
-
{@code @[package:]type:name}
-
-
-where the package name can be omitted if the resource is in the same package
-as the application, type is a type of resource — such as "string" or
-"drawable" — and name is the name that identifies the specific resource.
-For example:
-
-Values from a theme are expressed in a similar manner, but with an initial '?'
-rather than '@':
-
-
-
{@code ?[package:]type:name}
-
-
-
String values
-
Where an attribute value is a string, double backslashes ('{@code \\}')
-must be used to escape characters — for example, '{@code \\n}' for
-a newline or '{@code \\uxxxx}' for a Unicode character.
-
-
-
-
File Features
-
-
-The following sections describe how some Android features are reflected
-in the manifest file.
-
-
-
-
Intent Filters
-
-
-The core components of an application (its activities, services, and broadcast
-receivers) are activated by intents. An intent is a
-bundle of information (an {@link android.content.Intent} object) describing a
-desired action — including the data to be acted upon, the category of
-component that should perform the action, and other pertinent instructions.
-Android locates an appropriate component to respond to the intent, launches
-a new instance of the component if one is needed, and passes it the
-Intent object.
-
-
-
-Components advertise their capabilities — the kinds of intents they can
-respond to — through intent filters. Since the Android system
-must learn which intents a component can handle before it launches the component,
-intent filters are specified in the manifest as
-{@code <intent-filter>} elements. A component may
-have any number of filters, each one describing a different capability.
-
-
-
-An intent that explicitly names a target component will activate that component;
-the filter doesn't play a role. But an intent that doesn't specify a target by
-name can activate a component only if it can pass through one of the component's
-filters.
-
-
-
-For information on how Intent objects are tested against intent filters,
-a separate document,
-Intents
-and Intent Filters.
-
-
-
-
Icons and Labels
-
-
-A number of elements have {@code icon} and {@code label} attributes for an
-icon and a text label that can displayed to users. Some also have a
-{@code description} attribute for longer explanatory text that can also be
-shown on-screen. For example, the {@code <permission>}
-element has all three of these attributes, so that when the user is asked whether
-to grant the permission to an application that has requested it, an icon representing
-the permission, the name of the permission, and a description of what it
-entails can all be presented to the user.
-
-
-
-In every case, the icon and label set in a containing element become the default
-{@code icon} and {@code label} settings for all of the container's subelements.
-Thus, the icon and label set in the {@code <application>}
-element are the default icon and label for each of the application's components.
-Similarly, the icon and label set for a component — for example, an
-{@code <activity>} element — are the default
-settings for each of the component's
-{@code <intent-filter>} elements. If an
-{@code <application>} element sets a label, but
-an activity and its intent filter do not, the application label is treated
-as the label for both the activity and the intent filter.
-
-
-
-The icon and label set for an intent filter are used to represent a component
-whenever the component is presented to the user as fulfilling the function
-advertised by the filter. For example, a filter with
-"{@code android.intent.action.MAIN}" and
-"{@code android.intent.category.LAUNCHER}" settings advertises an activity
-as one that initiates an application — that is, as
-one that should be displayed in the application launcher. The icon and label
-set in the filter are therefore the ones displayed in the launcher.
-
-
-
-
Permissions
-
-
-A permission is a restriction limiting access to a part of the code
-or to data on the device. The limitation is imposed to protect critical
-data and code that could be misused to distort or damage the user experience.
-
-
-
-Each permission is identified
-by a unique label. Often the label indicates the action that's restricted.
-For example, here are some permissions defined by Android:
-
-A feature can be protected by at most one permission.
-
-
-
-If an application needs access to a feature protected by a permission, it must
-declare that it requires that permission with a
-{@code <uses-permission>} element in the manifest.
-Then, when the application is installed on the device, the installer determines
-whether or not to grant the requested permission by checking the authorities that
-signed the application's certificates and, in some cases, asking the user.
-If the permission is granted, the application is able to use the protected
-features. If not, its attempts to access those features will simply fail
-without any notification to the user.
-
-
-
-An application can also protect its own components (activities, services,
-broadcast receivers, and content providers) with permissions. It can employ
-any of the permissions defined by Android (listed in
-{@link android.Manifest.permission android.Manifest.permission}) or declared
-by other applications. Or it can define its own. A new permission is declared
-with the {@code <permission>} element.
-For example, an activity could be protected as follows:
-
-Note that, in this example, the {@code DEBIT_ACCT} permission is not only
-declared with the {@code <permission>}
-element, its use is also requested with
-the {@code <uses-permission>} element. Its use
-must be requested in order for other components of the application to launch
-the protected activity, even though the protection is imposed by the
-application itself.
-
-
-
-If, in the same example, the {@code permission} attribute was set to a
-permission declared elsewhere
-(such as {@code android.permission.CALL_EMERGENCY_NUMBERS}, it would not
-have been necessary to declare it again with the
-{@code <permission>} element.
-However, it would still have been necessary to request its use with
-{@code <uses-permission>}.
-
-
-
-The {@code <permission-tree>} element declares
-a namespace for a group of permissions that will be defined in code.
-And {@code <permission-group>}
-defines a label for a set of permissions (both those declared in the
-manifest with {@code <permission>} elements and
-those declared elsewhere). It affects only how the permissions are grouped
-when presented to the user.
-
-
-
-
Libraries
-
-
-Every application is linked against the default Android library, which
-includes the basic packages for building applications (with common classes
-such as Activity, Service, Intent, View, Button, Application, ContentProvider,
-and so on).
-
-
-
-However, some packages reside in their own libraries. If your application
-uses code from any of these packages, it must explicitly asked to be linked
-against them. The manifest must contain a separate
-{@code <uses-library>} element to name each
-of the libraries. (The library name can be found in the documentation
-for the package.)
-
-
-
-
Elements of the Manifest File
-
-
-This section describes all the elements that can appear in the manifest and each
-of their attributes in more detail. Only the elements listed here are legal.
-The list is alphabetical.
-
Adds an action to an intent filter.
-An {@code <intent-filter>} element must contain
-one or more {@code <action>} elements. If it doesn't contain any, no
-Intent objects will get through the filter. See
-Intents and
-Intent Filters for details on intent filters and the role of action
-specifications within a filter.
-
-
-
attributes:
-
-
{@code android:name}
-
The name of the action. Some standard actions are defined in the
-{@link android.content.Intent#ACTION_CHOOSER Intent} class as
-{@code ACTION_string} constants. To assign one of these actions to
-this attribute, prepend "{@code android.intent.action.}" to the
-{@code string} that follows {@code ACTION_}.
-For example, for {@code ACTION_MAIN}, use "{@code android.intent.action.MAIN}"
-and for {@code ACTION_WEB_SEARCH}, use "{@code android.intent.action.WEB_SEARCH}".
-
-
-For actions you define, it's best to use the package name as a prefix to
-ensure uniqueness. For example, a {@code TRANSMOGRIFY} action might be specified
-as follows:
-
Declares an activity (an {@link android.app.Activity} subclass) that
-implements part of the application's visual user interface. All activities
-must be represented by {@code <activity>}
-elements in the manifest file. Any that are not declared there will not be seen
-by the system and will never be run.
-
-
attributes:
-
-
{@code android:allowTaskReparenting}
-
Whether or not the activity can move from the task that started it to
-the task it has an affinity for when that task is next brought to the
-front — "{@code true}" if it can move, and "{@code false}" if it
-must remain with the task where it started.
-
-
-If this attribute is not set, the value set by the corresponding
-{@code allowTaskReparenting}
-attribute of the {@code <application>} element
-applies to the activity. The default value is "{@code false}".
-
-
-
-Normally when an activity is started, it's associated with the task of
-the activity that started it and it stays there for its entire lifetime.
-You can use this attribute to force it to be re-parented to the task it
-has an affinity for when its current task is no longer displayed.
-Typically, it's used to cause the activities of an application to move
-to the main task associated with that application.
-
-
-
-For example, if an e-mail message contains a link to a web page, clicking
-the link brings up an activity that can display the page. That activity
-is defined by the browser application, but is launched as part of the e-mail
-task. If it's reparented to the browser task, it will be shown when the
-browser next comes to the front, and will be absent when the e-mail task
-again comes forward.
-
-
-
-The affinity of an activity is defined by the
-{@code taskAffinity} attribute. The affinity
-of a task is determined by reading the affinity of its root activity.
-Therefore, by definition, a root activity is always in a task with the
-same affinity. Since activities with "{@code singleTask}" or
-"{@code singleInstance}" launch modes can only be at the root of a task,
-re-parenting is limited to the "{@code standard}" and "{@code singleTop}"
-modes. (See also the {@code launchMode}
-attribute.)
-
-
-
{@code android:alwaysRetainTaskState}
-
Whether or not the state of the task that the activity is in will always
-be maintained by the system — "{@code true}" if it will be, and
-"{@code false}" if the system is allowed to reset the task to its initial
-state in certain situations. The default value is "{@code false}". This
-attribute is meaningful only for the root activity of a task; it's ignored
-for all other activities.
-
-
-Normally, the system clears a task (removes all activities from the stack
-above the root activity) in certain situations when the user re-selects that
-task from the home screen. Typically, this is done if the user hasn't visited
-the task for a certain amount of time, such as 30 minutes.
-
-
-
-However, when this attribute is "{@code true}", users will always return
-to the task in its last state, regardless of how they get there. This is
-useful, for example, in an application like the web browser where there is
-a lot of state (such as multiple open tabs) that users would not like to lose.
-
-
-
{@code android:clearTaskOnLaunch}
-
Whether or not all activities will be removed from the task, except for
-the root activity, whenever it is re-launched from the home screen —
-"{@code true}" if the task is always stripped down to its root activity, and
-"{@code false}" if not. The default value is "{@code false}". This attribute
-is meaningful only for activities that start a new task (the root activity);
-it's ignored for all other activities in the task.
-
-
-When the value is "{@code true}", every time users start the task again, they
-are brought to its root activity, regardless of what they were last doing in
-the task and regardless of whether they used BACK or HOME to last leave it.
-When the value is "{@code false}", the task may be cleared of activities in
-some situations (see the {@code alwaysRetainTaskState} attribute), but not always.
-
-
-
-Suppose, for example, that someone launches activity P from the home screen,
-and from there goes to activity Q. The user next presses HOME, and then returns
-to activity P. Normally, the user would see activity Q, since that is what they
-were last doing in P's task. However, if P set this flag to "{@code true}", all
-of the activities on top of it (Q in this case) were removed when the user pressed
-HOME and the task went to the background. So the user sees only P when returning
-to the task.
-
-
-
-If this attribute and {@code allowTaskReparenting} are both "{@code true}",
-any activities that can be re-parented are moved to the task they share an
-affinity with; the remaining activities are then dropped, as described above.
-
-
-
{@code android:configChanges}
-
Lists configuration changes that the activity will handle itself. When
-changes that are not listed occur, the activity is shut down and restarted.
-When a listed change occurs, the activity remains running and its {@link android.app.Activity#onConfigurationChanged onConfigurationChanged()}
-method is called.
-
-
-Any or all of the following strings can be used to set this attribute. Values are
-separated by '{@code |}' — for example, "{@code locale|navigation|orientation}".
-
-
-
-
-
Value
-
Description
-
-
"{@code mcc}"
-
The IMSI mobile country code (MCC) has changed —
- that is, a SIM has been detected and updated the MCC.
-
-
"{@code mnc}"
-
The IMSI mobile network code (MNC) has changed —
- that is, a SIM has been detected and updated the MNC.
-
-
"{@code locale}"
-
The locale has changed — for example, the user has selected a new
- language that text should be displayed in.
-
-
"{@code touchscreen}"
-
The touchscreen has changed. (This should never normally happen.)
-
-
"{@code keyboard}"
-
The keyboard type has changed — for example, the user has
- plugged in an external keyboard.
-
-
"{@code keyboardHidden}"
-
The keyboard accessibility has changed — for example, the
- user has slid the keyboard out to expose it.
-
-
"{@code navigation}"
-
The navigation type has changed. (This should never normally happen.)
-
-
"{@code orientation}"
-
The screen orientation has changed — that is, the user has rotated
- the device.
-
-
"{@code fontScale}"
-
The font scaling factor has changed — that is, the user has selected
- a new global font size.
-
-
-
-
-All of these configuration changes can impact the resource values seen by the
-application. Therefore, when {@link android.app.Activity#onConfigurationChanged
-onConfigurationChanged()} is called, it will generally be necessary to again
-retrieve all resources (including view layouts, drawables, and so on) to correctly
-handle the change.
-
-
-
{@code android:enabled}
-
Whether or not the activity can be instantiated by the system —
-"{@code true}" if it can be, and "{@code false}" if not. The default value
-is "{@code true}".
-
-
-The {@code <application>} element has its own
-{@code enabled} attribute that applies to all
-application components, including activities. The
-{@code <application>} and {@code <activity>}
-attributes must both be "{@code true}" (as they both are by default) for
-the system to be able to instantiate the activity. If either is
-"{@code false}", it cannot be instantiated.
-
-
-
{@code android:excludeFromRecents}
-
Whether or not the activity should be excluded from the list of recently
-launched activities that can be displayed to users — "{@code true}" if
-it should be excluded, and "{@code false}" if it should be included.
-The default value is "{@code false}".
-
-
-
{@code android:exported}
-
Whether or not the activity can be launched by components of other
-applications — "{@code true}" if it can be, and "{@code false}" if not.
-If "{@code false}", the activity can be launched only by components of the
-same application or applications with the same user ID.
-
-
-The default value depends on whether the activity contains intent filters. The
-absence of any filters means that the activity can be invoked only by specifying
-its exact class name. This implies that the activity is intended only for
-application-internal use (since others would not know the class name). So in
-this case, the default value is "{@code false}".
-On the other hand, the presence of at least one filter implies that the activity
-is intended for external use, so the default value is "{@code true}".
-
-
-
-This attribute is not the only way to limit an activity's exposure to other
-applications. You can also use a permission to limit the external entities that
-can invoke the activity (see the {@code permission}
-attribute).
-
-
-
{@code android:finishOnTaskLaunch}
-
Whether or not an existing instance of the activity should be shut down
-(finished) whenever the user again launches its task (chooses the task on the
-home screen) — "{@code true}" if it should be shut down, and "{@code false}"
-if not. The default value is "{@code false}".
-
-
-If this attribute and {@code allowTaskReparenting}
-are both "{@code true}", this attribute trumps the other. The affinity of the
-activity is ignored. The activity is not re-parented, but destroyed.
-
-
-
{@code android:icon}
-
An icon representing the activity. The icon is displayed to users when
-a representation of the activity is required on-screen. For example, icons
-for activities that initiate tasks are displayed in the launcher window.
-The icon is often accompanied by a label (see the {@code label} attribute).
-
-
-
-This attribute must be set as a reference to a drawable resource containing
-the image definition. If it is not set, the icon specified for the application
-as a whole is used instead (see the {@code <application>}
-element's {@code icon} attribute).
-
-
-
-The activity's icon — whether set here or by the
-{@code <application>} element — is also the
-default icon for all the activity's intent filters (see the
-{@code <intent-filter>} element's
-{@code icon} attribute).
-
-
-
{@code android:label}
-
A user-readable label for the activity. The label is displayed on-screen
-when the activity must be represented to the user. It's often displayed along
-with the activity icon.
-
-
-If this attribute is not set, the label set for the application as a whole is
-used instead (see the {@code <application>} element's
-{@code label} attribute).
-
-
-
-The activity's label — whether set here or by the
-{@code <application>} element — is also the
-default label for all the activity's intent filters (see the
-{@code <intent-filter>} element's
-{@code label} attribute).
-
-
-
-The label should be set as a reference to a string resource, so that
-it can be localized like other strings in the user interface.
-However, as a convenience while you're developing the application,
-it can also be set as a raw string.
-
-
-
{@code android:launchMode}
-
An instruction on how the activity should be launched. There are four modes
-that work in conjunction with activity flags ({@code FLAG_ACTIVITY_*} constants)
-in {@link android.content.Intent} objects to determine what should happen when
-the activity is called upon to handle an intent:
-
-
-The default mode is "{@code standard}".
-The modes differ from each other on three points:
-
-
-
-
-
Whether or not a new instance of the class will be launched. For
-the default "{@code standard}" mode, every time a new intent is received, a new
-instance of the class is created to handle that intent. For all the other modes,
-an existing instance is re-used if it resides at the top of the activity stack.
-As we'll see below, if there's an existing instance of a "{@code singleTask}" or
-"{@code singleInstance}" activity, it will always be (or come to be) at the top
-of the stack, so this condition will always be met for those two modes. However,
-an existing "{@code singleTop}" instance may or may not be at the top of the stack.
-If it is, it will be re-used. If not, a new instance is created.
-
-
-For example, suppose a task's activity stack consists of root activity A with
-activities B, C, and D on top in that order, so the stack is A-B-C-D. An intent
-arrives for an activity of type D. If D has the default "{@code standard}" launch
-mode, a new instance of the class is launched and the stack becomes A-B-C-D-D.
-However, if D's launch mode is "{@code singleTop}", the existing instance is
-expected to handle the new intent (since it's at the top of the stack) and the
-stack remains A-B-C-D.
-
-
-
-If, on the other hand, the arriving intent is for an activity of type B, a new
-instance of B would be launched no matter whether B's mode is "{@code standard}"
-or "{@code singleTop}" (since B is not at the top of the stack), so the resulting
-stack would be A-B-C-D-B.
-
-
-
-Now, suppose again that the stack is A-B-C-D and that the intent that arrives for
-B has the {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP} flag set. Since
-the intent is destined for an activity of type B and the stack already has an object
-of that type, the flag causes activities C and D to be shut down and removed from
-the stack. If B's launch mode is "{@code standard}", it too will be removed, and
-a new instance of B launched to handle the incoming intent. That's because a new
-instance is always created for a new intent when the launch mode is "{@code standard}".
-However, if B's launch mode is "{@code singleTop}", the current instance would remain
-in the stack and receive the intent.
-
-
-
-Whenever an existing "{@code singleTop}", "{@code singleTask}", or
-"{@code singleInstance}" object is expected to handle an incoming intent, its
-{@link android.app.Activity#onNewIntent onNewIntent()} method is called with the
-{@link android.content.Intent} object passed as an argument.
-
-
-
-
Which task will hold the activity that responds to the intent.
-For the "{@code standard}" and "{@code singleTop}" modes, it's the task that
-originated the intent (and called {@link android.content.Context#startActivity
-startActivity()}) — unless the Intent object contains the
-{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} flag. In that case,
-a different task is chosen as follows:
-
-
-
If there's an existing task with the same affinity as the target activity,
-that task will hold the instance that responds to the intent. (As noted above,
-it could be an existing instance for a "{@code singleTop}" activity, but will
-always be a new instance for a "{@code standard}" activity.)
-
-
Otherwise, the activity is launched as the root of a new task.
-
-
-
-In contrast, the "{@code singleTask}" and "{@code singleInstance}" modes mark
-activities that will always be at the root of a task; they can never be launched
-as part of another task. Moreover, once a "{@code singleTask}" or
-"{@code singleInstance}" activity has been launched, that instance is re-used
-to handle all new intents, so there is never more than one instance of the
-activity on the device.
-
-
-
-When a new intent arrives for an existing "{@code singleTask}" activity, all
-other activities are removed from its stack, so that only the root activity
-remains; it's as if the Intent object included the
-{@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP} flag. The activity
-is then at the top of its stack, and in a position to receive the new intent
-in an {@link android.app.Activity#onNewIntent onNewIntent()} call.
-
-
-
Whether the instance can have other activities in its task.
-A "{@code singleInstance}" activity stands alone as the only activity in its
-task. If it starts another activity, that activity will be launched in a
-different task regardless of its launch mode. In all other respects, the
-"{@code singleInstance}" mode is identical to "{@code singleTask}".
-
-
-All modes other than "{@code singleInstance}" permit multiple activities
-to belong to the task.
-
-
-
-
-
{@code android:multiprocess}
-
Whether an instance of the activity can be launched into the process of the component
-that started it — "{@code true}" if it can be, and "{@code false}" if not.
-The default value is "{@code false}".
-
-
-Normally, a new instance of an activity is launched into the process of the
-application that defined it, so all instances of the activity run in the same
-process. However, if this flag is set to "{@code true}", instances of the
-activity can run in multiple processes, allowing the system to create instances
-wherever they are used (provided permissions allow it), something that is almost
-never necessary or desirable.
-
-
-
{@code android:name}
-
The name of the class that implements the activity, a subclass of
-{@link android.app.Activity}. The attribute value should be a fully qualified
-class name (such as, "{@code com.example.project. ExtracurricularActivity}").
-However, as a shorthand, if the first character of the name is a period
-(for example, "{@code . ExtracurricularActivity}"), it is appended to the
-package name specified in the {@code <manifest>}
-element.
-
-
-There is no default. The name must be specified.
-
-
-
{@code android:permission}
-
The name of a permission that clients must have to launch the activity
-or otherwise get it to respond to an intent. If a caller of
-{@link android.content.Context#startActivity startActivity()} or
-{@link android.app.Activity#startActivityForResult startActivityForResult()}
-has not been granted the specified permission, its intent will not be
-delivered to the activity.
-
-
-If this attribute is not set, the permission set by the
-{@code <application>} element's
-{@code permission} attribute applies
-to the activity. If neither attribute is set, the activity is
-not protected by a permission.
-
-
-
-For more information on permissions, see the Permissions
-section earlier in this document and a separate document,
-Security and
-Permissions.
-
-
-
{@code android:process}
-
The name of the process in which the activity should run. Normally,
-all components of an application run in the default process created for the
-application. It has the same name as the application package. The {@code <application>} element's
-{@code process} attribute can set a different
-default for all components. But each component can override the default,
-allowing you to spread your application across multiple processes.
-
-
-If the name assigned to this attribute begins with a colon (':'), a new
-process, private to the application, is created when it's needed and
-the activity runs in that process.
-If the process name begins with a lowercase character, the activity will run
-in a global process of that name, provided that it has permission to do so.
-This allows components in different applications to share a process, reducing
-resource usage.
-
-
-
{@code android:screenOrientation}
-
The orientation of the activity's display on the device.
-The value can be any one of the following strings:
-
-
-
-
"{@code unspecified}"
-
The default value. The system chooses the orientation. The policy it
- uses, and therefore the choices made in specific contexts, may differ
- from device to device.
-
-
"{@code landscape}"
-
Landscape orientation (the display is wider than it is tall).
-
-
"{@code portrait}"
-
Portrait orientation (the display is taller than it is wide).
-
-
"{@code user}"
-
The user's current preferred orientation.
-
-
"{@code behind}"
-
The same orientation as the activity that's immediately beneath it in
- the activity stack.
-
-
"{@code sensor}"
-
The orientation determined by a physical orientation sensor. The
- orientation of the display depends on how the user is holding the device;
- it changes when the user rotates the device.
-
-
"{@code nosensor}"
-
An orientation determined without reference to a physical orientation sensor.
- The sensor is ignored, so the display will not rotate based on how the user
- moves the device. Except for this distinction, the system chooses the
- orientation using the same policy as for the "{@code unspecified}" setting.
-
-
-
-
{@code android:stateNotNeeded}
-
Whether or not the activity can be killed and successfully restarted
-without having saved its state — "{@code true}" if it can be restarted
-without reference to its previous state, and "{@code false}" if its previous
-state is required. The default value is "{@code false}".
-
-
-Normally, before an activity is temporarily shut down to save resources, its
-{@link android.app.Activity#onSaveInstanceState onSaveInstanceState()}
-method is called. This method stores the current state of the activity in a
-{@link android.os.Bundle} object, which is then passed to
-{@link android.app.Activity#onCreate onCreate()} when the activity
-is restarted. If this attribute is set to "{@code true}",
-{@code onSaveInstanceState()} may not be called and {@code onCreate()} will
-be passed {@code null} instead of the Bundle — just as it was when the
-activity started for the first time.
-
-
-
-A "{@code true}" setting ensures that the activity can be restarted in the
-absence of retained state. For example, the activity that displays the
-home screen uses this setting to make sure that it does not get removed if it
-crashes for some reason.
-
-
-
{@code android:taskAffinity}
-
The task that the activity has an affinity for. Activities with
-the same affinity conceptually belong to the same task (to the same
-"application" from the user's perspective). The affinity of a task
-is determined by the affinity of its root activity.
-
-
-The affinity determines two things — the task that the activity is re-parented
-to (see the {@code allowTaskReparenting}
-attribute) and the task that will house the activity when it is launched
-with the {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}
-flag.
-
-
-
-By default, all activities in an application have the same affinity. You
-can set this attribute to group them differently, and even place
-activities defined in different applications within the same task. To
-specify that the activity does not have an affinity for any task, set
-it to an empty string.
-
-
-If this attribute is not set, the activity inherits the affinity set
-for the application (see the {@code <application>}
-element's {@code taskAffinity} attribute).
-The name of the default affinity for an application is the package name set
-by the {@code <manifest>} element.
-
-
-
{@code android:theme}
-
A reference to a style resource defining an overall theme for the activity.
-This automatically sets the activity's context to use this theme (see
-{@link android.content.Context#setTheme setTheme()}, and may also
-cause "starting" animations prior to the activity being launched (to better
-match what the activity actually looks like).
-
-
-If this attribute is not set, the activity inherits the theme set for the
-application as a whole — see the {@code <application>}
-element's {@code theme} attribute. If that attribute is
-also not set, the default system theme is used.
-
An alias for an activity, named by the {@code targetActivity}
-attribute. The target must be in the same application as the
-alias and it must be declared before the alias in the manifest.
-
-
-The alias presents the target activity as a independent entity.
-It can have its own set of intent filters, and they, rather than the
-intent filters on the target activity itself, determine which intents
-can activate the target through the alias and how the system
-treats the alias. For example, the intent filters on the alias may
-specify the "{@link android.content.Intent#ACTION_MAIN
-android.intent.action.MAIN}"
-and "{@link android.content.Intent#CATEGORY_LAUNCHER
-android.intent.category.LAUNCHER}" flags, causing it to be
-represented in the application launcher, even though none of the
-filters on the target activity itself set these flags.
-
-
-
-With the exception of {@code targetActivity}, {@code <activity-alias>}
-attributes are a subset of {@code <activity>} attributes.
-For attributes in the subset, none of the values set for the target carry over
-to the alias. However, for attributes not in the subset, the values set for
-the target activity also apply to the alias.
-
-
-
attributes:
-
-
{@code android:enabled}
-
Whether or not the target activity can be instantiated by the system through
-this alias — "{@code true}" if it can be, and "{@code false}" if not.
-The default value is "{@code true}".
-
-
-The {@code <application>} element has its own
-{@code enabled} attribute that applies to all
-application components, including activity aliases. The
-{@code <application>} and {@code <activity-alias>}
-attributes must both be "{@code true}" for the system to be able to instantiate
-the target activity through the alias. If either is "{@code false}", the alias
-does not work.
-
-
-
{@code android:exported}
-
Whether or not components of other applications can launch the target activity
-through this alias — "{@code true}" if they can, and "{@code false}" if not.
-If "{@code false}", the target activity can be launched through the alias only by
-components of the same application as the alias or applications with the same user ID.
-
-
-The default value depends on whether the alias contains intent filters. The
-absence of any filters means that the activity can be invoked through the alias
-only by specifying the exact name of the alias. This implies that the alias
-is intended only for application-internal use (since others would not know its name)
-— so the default value is "{@code false}".
-On the other hand, the presence of at least one filter implies that the alias
-is intended for external use — so the default value is "{@code true}".
-
-
-
{@code android:icon}
-
An icon for the target activity when presented to users through the alias.
-See the {@code <activity>} element's
-{@code icon} attribute for more information.
-
-
{@code android:label}
-
A user-readable label for the alias when presented to users through the alias.
-See the the {@code <activity>} element's
-{@code label} attribute for more information.
-
-
-
{@code android:name}
-
A unique name for the alias. The name should resemble a fully
-qualified class name. But, unlike the name of the target activity,
-the alias name is arbitrary; it does not refer to an actual class.
-
-
-
{@code android:permission}
-
The name of a permission that clients must have to launch the target activity
-or get it to do something via the alias. If a caller of
-{@link android.content.Context#startActivity startActivity()} or
-{@link android.app.Activity#startActivityForResult startActivityForResult()}
-has not been granted the specified permission, the target activity will not be
-activated.
-
-
This attribute supplants any permission set for the target activity itself. If
-it is not set, a permission is not needed to activate the target through the alias.
-
-
-
-For more information on permissions, see the {@code Permissions
-section earlier in this document.
-
-
-
{@code android:targetActivity}
-
The name of the activity that can be activated through the alias.
-This name must match the {@code name} attribute of an
-{@code <activity>} element that precedes
-the alias in the manifest.
-
The declaration of the application. This element contains subelements
-that declare each of the application's components and has attributes
-that can affect all the components. Many of these attributes (such as
-{@code icon}, {@code label}, {@code permission}, {@code process},
-{@code taskAffinity}, and {@code allowTaskReparenting}) set default values
-for corresponding attributes of the component elements. Others (such as
-{@code debuggable}, {@code enabled}, {@code description}, and
-{@code allowClearUserData}) set values for the application as a whole and
-cannot be overridden by the components.
-
-
attributes
-
-
{@code android:allowClearUserData}
-
Whether or not users are given the option to remove user data —
-"{@code true}" if they are, and "{@code false}" if not. If the value is
-"{@code true}", as it is by default, the application manager includes an
-option that allows users to clear the data.
-
-
{@code android:allowTaskReparenting}
-
Whether or not activities that the application defines can move from
-the task that started them to the task they have an affinity for when that task
-is next brought to the front — "{@code true}" if they can move, and
-"{@code false}" if they must remain with the task where they started.
-The default value is "{@code false}".
-
-
-The {@code <activity>} element has its own
-{@code allowTaskReparenting} attribute
-that can override the value set here. See that attribute for more
-information.
-
-
-
{@code android:debuggable}
-
Whether or not the application can be debugged, even when running
-on a device in user mode — "{@code true}" if it can be, and "{@code false}"
-if not. The default value is "{@code false}".
-
-
{@code android:description}
-
User-readable text about the application, longer and more descriptive than the application label. The value must be set as a reference to a string resource. Unlike the label, it cannot be a raw string. There is no default value.
-
-
{@code android:enabled}
-
Whether or not the Android system can instantiate components of
-the application — "{@code true}" if it can, and "{@code false}"
-if not. If the value is "{@code true}", each component's
-{@code enabled} attribute determines whether that component is enabled
-or not. If the value is "{@code false}", it overrides the
-component-specific values; all components are disabled.
-
-
-The default value is "{@code true}".
-
-
-
{@code android:hasCode}
-
Whether or not the application contains any code — "{@code true}"
-if it does, and "{@code false}" if not. When the value is "{@code false}",
-the system does not try to load any application code when launching components.
-The default value is "{@code true}".
-
-
-An application would not have any code of its own only if it's using nothing
-but built-in component classes, such as an activity that uses the {@link
-android.app.AliasActivity} class, a rare occurrence.
-
-
{@code android:icon}
-
An icon for the application as whole, and the default icon for
-each of the application's components. See the individual
-{@code icon} attributes for
-{@code <activity>},
-{@code <activity-alias>},
-{@code <service>},
-{@code <receiver>}, and
-{@code <provider>} elements.
-
-
-This attribute must be set as a reference to a drawable resource containing
-the image definition. There is no default icon.
-
-
-
{@code android:label}
-
A user-readable label for the application as a whole, and a default
-label for each of the application's components. See the individual
-{@code label} attributes for
-{@code <activity>},
-{@code <activity-alias>},
-{@code <service>},
-{@code <receiver>}, and
-{@code <provider>} elements.
-
-
-The label should be set as a reference to a string resource, so that
-it can be localized like other strings in the user interface.
-However, as a convenience while you're developing the application,
-it can also be set as a raw string.
-
-
-
{@code android:manageSpaceActivity}
-
The fully qualified name of an Activity subclass that the system
-can launch to let users manage the memory occupied by the application
-on the device. The activity should also be declared with an
-{@code <activity>} element.
-
-
-
{@code android:name}
-
The fully qualified name of an {@link android.app.Application}
-subclass implemented for the application. When the application process
-is started, this class is instantiated before any of the application's
-components.
-
-
-The subclass is optional; most applications won't need one.
-In the absence of a subclass, Android uses an instance of the base
-Application class.
-
-
-
{@code android:permission}
-
The name of a permission that clients must have in order to interact
-with the application. This attribute is a convenient way to set a
-permission that applies to all of the application's components. It can
-be overwritten by setting the {@code permission} attributes of individual
-components.
-
-
-For more information on permissions, see the Permissions
-section earlier in this document and a separate document,
-Security and
-Permissions.
-
-
-
{@code android:persistent}
-
Whether or not the application should remain running at all times —
-"{@code true}" if it should, and "{@code false}" if not. The default value
-is "{@code false}". Applications should not normally set this flag;
-persistence mode is intended only for certain system applications.
-
-
{@code android:process}
-
The name of a process where all components of the application should run.
-Each component can override this default by setting its own {@code process}
-attribute.
-
-
-By default, Android creates a process for an application when the first
-of its components needs to run. All components then run in that process.
-The name of the default process matches the package name set by the
-{@code <manifest>} element.
-
-
-
By setting this attribute to a process name that's shared with another
-application, you can arrange for components of both applications to run in
-the same process — but only if the two applications also share a
-user ID and be signed with the same certificate.
-
-
-
-If the name assigned to this attribute begins with a colon (':'), a new
-process, private to the application, is created when it's needed.
-If the process name begins with a lowercase character, a global process
-of that name is created. A global process can be shared with other
-applications, reducing resource usage.
-
-
-
{@code android:taskAffinity}
-
An affinity name that applies to all activities within the application,
-except for those that set a different affinity with their own {@code
-taskAffinity} attributes. See that attribute
-for more information.
-
-
-By default, all activities within an application share the same
-affinity. The name of that affinity is the same as the package name
-set by the {@code <manifest>} element.
-
-
-
{@code android:theme}
-
A reference to a style resource defining a default theme for all
-activities in the application. Individual activities can override
-the default by setting their own {@code theme}
-attributes; see that attribute for more information.
Adds a category name to an intent filter. See
-Intents and
-Intent Filters for details on intent filters and the role of category
-specifications within a filter.
-
-
attributes:
-
-
{@code android:name}
-
The name of the category. Standard categories are defined in the
-{@link android.content.Intent} class as {@code CATEGORY_name}
-constants. The name assigned here can be derived from those constants
-by prefixing "{@code android.intent.category.}" to the
-{@code name} that follows {@code CATEGORY_}. For example,
-the string value for {@code CATEGORY_LAUNCHER} is
-"{@code android.intent.category.LAUNCHER}".
-
-
-Custom categories should use the package name as a prefix, to ensure
-that they are unique.
-
Adds a data specification to an intent filter. The specification can
-be just a data type (the {@code mimeType} attribute),
-just a URI, or both a data type and a URI. A URI is specified by separate
-attributes for each of its parts:
-
-
{@code scheme://host:port/path} or
-{@code pathPrefix} or {@code pathPattern}
-
-
-These attributes are optional, but also mutually dependent:
-If a {@code scheme} is not specified for the
-intent filter, all the other URI attributes are ignored. If a
-{@code host} is not specified for the filer,
-the {@code port} attribute and all the path attributes are ignored.
-
-
-
-All the {@code <data>} elements contained within the same
-{@code <intent-filter>} element contribute to
-the same filter. So, for example, the following filter specification,
-
-You can place any number of <data> elements inside an
-{@code <intent-filter>} to give it multiple data
-options. None of its attributes have default values.
-
-
-
-Information on how intent filters work, including the rules for how Intent objects
-are matched against filters, can be found in another document,
-Intents and
-Intent Filters. See also the Intent Filters section
-earlier in this document.
-
-
-
attributes:
-
-
{@code android:host}
-
The host part of a URI authority. This attribute is meaningless
-unless a {@code scheme} attribute is also
-specified for the filter.
-
-
-
{@code android:mimeType}
-
A MIME media type, such as {@code image/jpeg} or {@code audio/mpeg4-generic}.
-The subtype can be the asterisk wildcard ({@code *}) to indicate that any
-subtype matches.
The path part of a URI. The {@code path} attribute specifies a complete
-path that is matched against the complete path in an Intent object. The
-{@code pathPrefix} attribute specifies a partial path that is matched against
-only the initial part of the path in the Intent object. The {@code pathPattern}
-attribute specifies a complete path that is matched against the complete path
-in the Intent object, but it can contain the following wildcards:
-
-
-
An asterisk ('{@code *}') matches a sequence of 0 to many occurrences of
-the immediately preceding character.
-
-
A period followed by an asterisk ("{@code .*}") matches any sequence of
-0 to many characters.
-
-
-
-Because '{@code \}' is used as an escape character when the string is read
-from XML (before it is parsed as a pattern), you will need to double-escape:
-For example, a literal '{@code *}' would be written as "{@code \\*}" and a
-literal '{@code \}' would be written as "{@code \\\\}". This is basically
-the same as what you would need to write if constructing the string in Java code.
-
-
-
-For more information on these three types of patterns, see the descriptions of
-{@link android.os.PatternMatcher#PATTERN_LITERAL},
-{@link android.os.PatternMatcher#PATTERN_PREFIX}, and
-{@link android.os.PatternMatcher#PATTERN_SIMPLE_GLOB} in the
-{@link android.os.PatternMatcher} class.
-
-
-
These attributes are meaningful only if the
-{@code scheme} and
-{@code host}
-attributes are also specified for the filter.
-
-
-
{@code android:port}
-
The port part of a URI authority. This attribute is meaningful only
-if the {@code scheme} and
-{@code host} attributes are also specified for
-the filter.
-
-
{@code android:scheme}
-
The scheme part of a URI. This is the minimal essential attribute for
-specifying a URI; at least one {@code scheme} attribute must be set
-for the filter, or none of the other URI attributes are meaningful.
-
-
-A scheme is specified without the trailing colon (for example,
-{@code http}, rather than {@code http:}).
-
-
-
-If the filter has a data type set (the {@code mimeType}
-attribute) but no scheme, the {@code content:} and {@code file:} schemes are
-assumed.
-
Specifies which data subsets of the parent content provider permission
-can be granted for. Data subsets are indicated by the path part of a
-{@code content:} URI. (The authority part of the URI identifies the
-content provider.)
-Granting permission is a way of enabling clients of the provider that don't
-normally have permission to access its data to overcome that restriction on
-a one-time basis.
-
-
-If a content provider's {@code grantUriPermissions}
-attribute is "{@code true}", permission can be granted for any the data under
-the provider's purview. However, if that attribute is "{@code false}", permission
-can be granted only to data subsets that are specified by this element.
-A provider can contain any number of {@code <grant-uri-permission>} elements.
-Each one can specify only one path (only one of the three possible attributes).
-
A path identifying the data subset or subsets that permission can be
-granted for. The {@code path} attribute specifies a complete path;
-permission can be granted only to the particular data subset identified
-by that path.
-The {@code pathPrefix} attribute specifies the initial part of a path;
-permission can be granted to all data subsets with paths that share that
-initial part.
-The {@code pathPattern} attribute specifies a complete path, but one
-that can contain the following wildcards:
-
-
-
An asterisk ('{@code *}') matches a sequence of 0 to many occurrences of
-the immediately preceding character.
-
-
A period followed by an asterisk ("{@code .*}") matches any sequence of
-0 to many characters.
-
-
-
-Because '{@code \}' is used as an escape character when the string is read
-from XML (before it is parsed as a pattern), you will need to double-escape:
-For example, a literal '{@code *}' would be written as "{@code \\*}" and a
-literal '{@code \}' would be written as "{@code \\\\}". This is basically
-the same as what you would need to write if constructing the string in Java code.
-
-
-
-For more information on these types of patterns, see the descriptions of
-{@link android.os.PatternMatcher#PATTERN_LITERAL},
-{@link android.os.PatternMatcher#PATTERN_PREFIX}, and
-{@link android.os.PatternMatcher#PATTERN_SIMPLE_GLOB} in the
-{@link android.os.PatternMatcher} class.
-
Declares an {@link android.app.Instrumentation} class that enables you
-to monitor an application's interaction with the system. The Instrumentation
-object is instantiated before any of the application's components.
-
-
attributes:
-
-
{@code android:functionalTest}
-
Whether or not the Instrumentation class should run as a functional test
-— "{@code true}" if it should, and "{@code false}" if not. The
-default value is "{@code false}".
-
-
{@code android:handleProfiling}
-
Whether or not the Instrumentation object will turn profiling on and
-off — "{@code true}" if it determines when profiling starts and
-stops, and "{@code false}" if profiling continues the entire time it is
-running. A value of "{@code true}" enables the object to target profiling
-at a specific set of operations. The default value is "{@code false}".
-
-
{@code android:icon}
-
An icon that represents the Instrumentation class. This attribute must
-be set as a reference to a drawable resource.
-
-
{@code android:label}
-
A user-readable label for the Instrumentation class. The label can
-be set as a raw string or a reference to a string resource.
-
-
{@code android:name}
-
The name of the {@link android.app.Instrumentation} subclass.
-This should be a fully qualified class name (such as,
-"{@code com.example.project.StringInstrumentation}"). However, as a shorthand,
-if the first character of the name is a period, it is appended to the package
-name specified in the {@code <manifest>} element.
-
-
-There is no default. The name must be specified.
-
-
-
{@code android:targetPackage}
-
The application that the Instrumentation object will run against.
-An application is identified by the package name assigned in its manifest
-file by the {@code <manifest>} element.
Specifies the types of intents that an activity, service, or broadcast
-receiver can respond to. An intent filter declares the capabilities of its
-parent component — what an activity or service can do and what types
-of broadcasts a receiver can handle. It opens the component to receiving
-intents of the advertised type, while filtering out those that are not
-meaningful for the component.
-
-
-Most of the contents of the filter are described by its
-{@code <action>},
-{@code <category>}, and
-{@code <data>} subelements.
-
An icon that represents the parent activity, service, or broadcast
-receiver when that component is presented to the user as having the
-capability described by the filter.
-
-
-This attribute must be set as a reference to a drawable resource
-containing the image definition. The default value is the icon set
-by the parent component's {@code icon} attribute. If the parent
-does not specify an icon, the default is the icon set by the
-{@code <application>} element.
-
-
-
-For more on intent filter icons, see Icons and Labels,
-earlier.
-
-
-
{@code android:label}
-
A user-readable label for the parent component. This label, rather than
-the one set by the parent component, is used when the component is presented
-to the user as having the capability described by the filter.
-
-
-The label should be set as a reference to a string resource, so that
-it can be localized like other strings in the user interface.
-However, as a convenience while you're developing the application,
-it can also be set as a raw string.
-
-
-
-The default value is the label set by the parent component. If the
-parent does not specify a label, the default is the label set by the
-{@code <application>} element's
-{@code label} attribute.
-
-
-
-For more on intent filter labels, see Icons and Labels,
-earlier.
-
-
-
{@code android:priority}
-
The priority that should be given to the parent component with regard
-to handling intents of the type described by the filter. This attribute has
-meaning for both activities and broadcast receivers:
-
-
-
It provides information about how able an activity is to respond to
-an intent that matches the filter, relative to other activities that could
-also respond to the intent. When an intent could be handled by multiple
-activities with different priorities, Android will consider only those with
-higher priority values as potential targets for the intent.
-
-
It controls the order in which broadcast receivers are executed to
-receive broadcast messages. Those with higher priority
-values are called before those with lower values. (The order applies only
-to synchronous messages; it's ignored for asynchronous messages.)
-
-
-
-Use this attribute only if you really need to impose a specific order in
-which the broadcasts are received, or want to force Android to prefer
-one activity over others.
-
-
-
-The value must be an integer, such as "{@code 100}". Higher numbers have a
-higher priority.
-
The root element of the AndroidManifest.xml file. It must
-contain an {@code <application>} element
-and specify {@code xlmns:android} and {@code package} attributes.
-
-
attributes:
-
-
{@code xmlns:android}
-
Defines the Android namespace. This attribute should always be set
-to "{@code http://schemas.android.com/apk/res/android}".
-
-
{@code package}
-
A full Java package name for the application. The name should
-be unique. For example, applications published by Google could have
-names in the form com.google.app.application_name.
-
-
-The package name serves as a unique identifier for the application.
-It's also the default name for the task affinity of components
-(see the {@code taskAffinity} attribute).
-
-
-
{@code android:sharedUserId}
-
The name of a Linux user ID that will be shared with other applications.
-By default, Android assigns each application its own unique user ID.
-However, if this attribute is set to the same value for two or more applications,
-they will all share the same ID — provided that they are also signed
-by the same certificate. Application with the same user ID can access each
-other's data and, if desired, run in the same process.
-
-
{@code android:versionCode}
-
An internal version number. This number is used only to determine whether
-one version is more recent than another, with higher numbers indicating more
-recent versions. This is not the version number shown to users; that number
-is set by the {@code versionName} attribute.
-
-
-The value must be set as an integer, such as "100". You can define it however
-you want, as long as each successive version has a higher number. For example,
-it could be a build number. Or you could translate a version number in "x.y"
-format to an integer by encoding the "x" and "y" separately in the lower and
-upper 16 bits. Or you could simply increase the number by one each time a new
-version is released.
-
-
-
{@code android:versionName}
-
The version number shown to users. This attribute can be set as a raw
-string or as a reference to a string resource. The string has no other purpose
-than to be displayed to users. The {@code versionCode} attribute holds
-the significant version number used internally.
-
A name-value pair for an item of additional, arbitrary data that can
-be supplied to the parent component. A component element can contain any
-number of {@code <meta-data>} subelements. The values from all of
-them are collected in a single {@link android.os.Bundle} object and made
-available to the component as the
-{@link android.content.pm.PackageItemInfo#metaData
-PackageItemInfo.metaData} field.
-
-
-Ordinary values are specified through the {@code value}
-attribute. However, to assign a resource ID as the value, use the
-{@code resource} attribute instead. For example,
-the following code assigns whatever value is stored in the {@code @string/kangaroo}
-resource to the "{@code zoo}" name:
-
-On the other hand, using the {@code resource} attribute would assign "{@code zoo}"
-the numeric ID of the resource, not the value stored in the resource:
-
-It is highly recommended that you avoid supplying related data as
-multiple separate {@code <meta-data>} entries. Instead, if you
-have complex data to associate with a component, store it as a resource and
-use the {@code resource} attribute to inform the component of its ID.
-
-
-
attributes:
-
-
{@code android:name}
-
A unique name for the item. To ensure that the name is unique, use a
-Java-style naming convention — for example,
-"{@code com.example.project.activity.fred}".
-
-
{@code android:resource}
-
A reference to a resource. The ID of the resource is the value assigned
-to the item. The ID can be retrieved from the meta-data Bundle by the
-{@link android.os.Bundle#getInt Bundle.getInt()} method.
-
-
{@code android:value}
-
The value assigned to the item. The data types that can be assigned as values and the Bundle methods that components use to retrieve those values are listed in the following table:
-
-
-
-
Type
-
Bundle method
-
-
String value, using double backslashes ({@code \\}) to escape characters
- — such as "{@code \\n}" and "{@code \\uxxxxx}" for a Unicode character.
Declares a security permission that can be used to limit access
-to specific components or features of this or other applications.
-See the Permissions, earlier in this document,
-and the Security Model
-document for more information on how permissions work.
-
-
attributes:
-
-
{@code android:description}
-
A user-readable description of the permission, longer and more
-informative than the label. It may be displayed to explain the
-permission to the user — for example, when the user is asked
-whether to grant the permission to another application.
-
-
-This attribute must be set as a reference to a string resource;
-unlike the {@code label} attribute, it cannot be a raw string.
-
-
-
{@code android:icon}
-
A reference to a drawable resource for an icon that represents the
-permission.
-
-
{@code android:label}
-
A name for the permission, one that can be displayed to users.
-
-
-As a convenience, the label can be directly set
-as a raw string while you're developing the application. However,
-when the application is ready to be published, it should be set as a
-reference to a string resource, so that it can be localized like other
-strings in the user interface.
-
-
-
{@code android:name}
-
The name of the permission. This is the name that will be used in
-code to refer to the permission — for example, in a
-{@code <uses-permission>} element and the
-{@code permission} attributes of application components.
-
-
-The name must be unique, so it should use Java-style scoping —
-for example, "{@code com.example.project.PERMITTED_ACTION}".
-
-
-
{@code android:permissionGroup}
-
Assigns this permission to a group. The value of this attribute is
-the name of the group, which must be declared with the
-{@code <permission-group>} element in this
-or another application. If this attribute is not set, the permission
-does not belong to a group.
-
-
{@code android:protectionLevel}
-
Characterizes the potential risk implied in the permission and
-indicates the procedure the system should follow when determining
-whether or not to grant the permission to an application requesting it.
-The value can be set to one of the following strings:
-
-
-
-
Value
-
Meaning
-
-
"{@code normal}"
-
The default value. A lower-risk permission that gives requesting
- applications access to isolated application-level features, with
- minimal risk to other applications, the system, or the user.
- The system automatically grants this type
- of permission to a requesting application at installation, without
- asking for the user's explicit approval (though the user always
- has the option to review these permissions before installing).
-
-
"{@code dangerous}"
-
A higher-risk permission that would give a requesting application
- access to private user data or control over the device that can
- negatively impact the user. Because this type of permission
- introduces potential risk, the system may not automatically
- grant it to the requesting application. For example, any dangerous
- permissions requested by an application may be displayed to the
- user and require confirmation before proceeding, or some other
- approach may be taken to avoid the user automatically allowing
- the use of such facilities.
-
-
"{@code signature}"
-
A permission that the system grants only if the requesting
- application is signed with the same certificate as the application
- that declared the permission. If the certificates match, the system
- automatically grants the permission without notifying the user or
- asking for the user's explicit approval.
-
-
"{@code signatureOrSystem}"
-
A permission that the system grants only to applications that are
- in the Android system image or that are signed with the same
- certificates as those in the system image. Please avoid using this
- option, as the {@code signature} protection level should be sufficient
- for most needs and works regardless of exactly where applications are
- installed. The "{@code signatureOrSystem}"
- permission is used for certain special situations where multiple
- vendors have applications built into a system image and need
- to share specific features explicitly because they are being built
- together.
-
Declares a name for a logical grouping of related permissions. Individual
-permission join the group through the {@code permissionGroup} attribute of the
-{@code <permission>} element. Members of a group are
-presented together in the user interface.
-
-
-Note that this element does not declare a permission itself, only a category in
-which permissions can be placed. See the
-{@code <permission>} element for element for information
-on declaring permissions and assigning them to groups.
-
-
-
attributes:
-
-
{@code android:description}
-
User-readable text that describes the group. The text should be
-longer and more explanatory than the label. This attribute must be
-set as a reference to a string resource. Unlike the {@code label}
-attribute, it cannot be a raw string.
-
-
{@code android:icon}
-
An icon representing the permission. This attribute must be set
-as a reference to a drawable resource containing the image definition.
-
-
{@code android:label}
-
A user-readable name for the group. As a convenience, the label can
-be directly set as a raw string while you're developing the application.
-However, when the application is ready to be published, it should be set
-as a reference to a string resource, so that it can be localized like other
-strings in the user interface.
-
-
{@code android:name}
-
The name of the group. This is the name that can be assigned to a
-{@code <permission>} element's
-{@code permissionGroup} attribute.
Declares the base name for a tree of permissions. The application takes
-ownership of all names within the tree. It can dynamically add new permissions
-to the tree by calling {@link android.content.pm.PackageManager#addPermission PackageManager.addPermission()}. Names within the tree are separated by
-periods ('{@code .}'). For example, if the base name is
-{@code com.example.project.taxes}, permissions like the following might be
-added:
-
-
-Note that this element does not declare a permission itself, only a
-namespace in which further permissions can be placed.
-See the {@code <permission>} element for
-information on declaring permissions.
-
-
attributes:
-
-
{@code android:icon}
-
An icon representing all the permissions in the tree. This attribute
-must be set as a reference to a drawable resource containing the image
-definition.
-
-
{@code android:label}
-
A user-readable name for the group. As a convenience, the label can
-be directly set as a raw string for quick and dirty programming. However,
-when the application is ready to be published, it should be set as a
-reference to a string resource, so that it can be localized like other
-strings in the user interface.
-
-
{@code android:name}
-
The name that's at the base of the permission tree. It serves as
-a prefix to all permission names in the tree. Java-style scoping should
-be used to ensure that the name is unique. The name must have more than
-two period-separated seqments in its path — for example,
-{@code com.example.base} is OK, but {@code com.example} is not.
Declares a content provider — a subclass of
-{@link android.content.ContentProvider} — that supplies structured
-access to data managed by the application. All content providers that
-are part of the application must be represented by {@code <provider>}
-elements in the manifest file. The system cannot see, and therefore will
-not run, any that are not declared. (You need to declare only
-those content providers that you develop as part of your application,
-not those developed by others that your application uses.)
-
-
-The Android system identifies content providers by the authority part
- of a {@code content:} URI. For example, suppose that the following URI
-is passed to {@link android.content.ContentResolver#query
-ContentResolver.query()}:
-
-
-The {@code content:} scheme identifies the data as belonging to a content
-provider and the authority ({@code com.example.project.healthcareprovider})
-identifies the particular provider. The authority therefore must be unique.
-Typically, as in this example, it's the fully qualified name of a
-ContentProvider subclass. The path part of a URI may be used by a content
-provider to identify particular data subsets, but those paths are not
-declared in the manifest.
-
-
-
-For information on using and developing content providers, see a separate document,
-Content Providers.
-
-
-
attributes:
-
-
{@code android:authorities}
-
A list of one or more URI authorities that identify data under the purview
-of the content provider.
-Multiple authorities are listed by separating their names with a semicolon.
-To avoid conflicts, authority names should use a Java-style naming convention
-(such as {@code com.example.provider.cartoonprovider}). Typically, it's the name
-of the ContentProvider subclass.
-
-
-There is no default. At least one authority must be specified.
-
-
-
{@code android:enabled}
-
Whether or not the content provider can be instantiated by the system —
-"{@code true}" if it can be, and "{@code false}" if not. The default value
-is "{@code true}".
-
-
-The {@code <application>} element has its own
-{@code enabled} attribute that applies to all
-application components, including content providers. The
-{@code <application>} and {@code <provider>}
-attributes must both be "{@code true}" (as they both
-are by default) for the content provider to be enabled. If either is
-"{@code false}", the provider is disabled; it cannot be instantiated.
-
-
-
{@code android:exported}
-
Whether or not the content provider can be used by components of other
-applications — "{@code true}" if it can be, and "{@code false}" if not.
-If "{@code false}", the provider is available only to components of the
-same application or applications with the same user ID. The default value
-is "{@code true}".
-
-
-You can export a content provider but still limit access to it with the
-{@code permission} attribute.
-
-
-
{@code android:grantUriPermissions}
-
Whether or not those who ordinarily would not have permission to
-access the content provider's data can be granted permission to do so,
-temporarily overcoming the restriction imposed by the
-{@code readPermission},
-{@code writePermission}, and
-{@code permission} attributes
-—
-"{@code true}" if permission can be granted, and "{@ code false}" if not.
-If "{@code true}", permission can be granted to any of the content
-provider's data. If "{@code false}", permission can be granted only
-to the data subsets listed in
-{@code <grant-uri-permission>} subelements,
-if any. The default value is "{@code false}".
-
-
-Granting permission is a way of giving an application component one-time
-access to data protected by a permission. For example, when an e-mail
-message contains an attachment, the mail application may call upon the
-appropriate viewer to open it, even though the viewer doesn't have general
-permission to look at all the content provider's data.
-
-
-
-In such cases, permission is granted by
-{@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION}
-and {@link android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION}
-flags in the Intent object that activates the component. For example, the
-mail application might put {@code FLAG_GRANT_READ_URI_PERMISSION} in the
-Intent passed to {@code Context.startActivity()}. The permission is specific
-to the URI in the Intent.
-
-
-
-If you enable this feature, either by setting this attribute to "{@code true}"
-or by defining {@code <grant-uri-permission>}
-subelements, you must call
-{@link android.content.Context#revokeUriPermission
-Context.revokeUriPermission()} when a covered URI is deleted from
-the provider.
-
An icon representing the content provider.
-This attribute must be set as a reference to a drawable resource containing
-the image definition. If it is not set, the icon specified for the application
-as a whole is used instead (see the {@code <application>}
-element's {@code icon} attribute).
-
-
{@code android:initOrder}
-
The order in which the content provider should be instantiated,
-relative to other content providers hosted by the same process.
-When there are dependencies among content providers, setting this
-attribute for each of them ensures that they are created in the order
-required by those dependencies. The value is a simple integer,
-with higher numbers being initialized first.
-
-
{@code android:label}
-
A user-readable label for the content provided.
-If this attribute is not set, the label set for the application as a whole is
-used instead (see the {@code <application>} element's
-{@code label} attribute).
-
-
-The label should be set as a reference to a string resource, so that
-it can be localized like other strings in the user interface.
-However, as a convenience while you're developing the application,
-it can also be set as a raw string.
-
-
-
{@code android:multiprocess}
-
Whether or not an instance of the content provider can be created in
-every client process — "{@code true}" if instances can run in multiple
-processes, and "{@code false}" if not. The default value is "{@code false}".
-
-
-Normally, a content provider is instantiated in the process of the
-application that defined it. However, if this flag is set to "{@code true}",
-the system can create an instance in every process where there's a client
-that wants to interact withit, thus avoiding the overhead of interprocess
-communication.
-
-
-
{@code android:name}
-
The name of the class that implements the content provider, a subclass of
-{@link android.content.ContentProvider}. This should be a fully qualified
-class name (such as, "{@code com.example.project.TransportationProvider}").
-However, as a shorthand, if the first character of the name is a period,
-it is appended to the package name specified in the
-{@code <manifest>} element.
-
-
-There is no default. The name must be specified.
-
-
-
-
{@code android:permission}
-
The name of a permission that clients must have to read or write the
-content provider's data. This attribute is a convenient way of setting a
-single permission for both reading and writing. However, the
-{@code readPermission} and
-{@code writePermission} attributes take precedence
-over this one. If the {@code readPermission}
-attribute is also set, it controls access for querying the content provider.
-And if the {@code writePermission} attribute is set,
-it controls access for modifying the provider's data.
-
-
-For more information on permissions, see the Permissions
-section earlier in this document and a separate document,
-Security and
-Permissions.
-
-
-
{@code android:process}
-
The name of the process in which the content provider should run. Normally,
-all components of an application run in the default process created for the
-application. It has the same name as the application package. The {@code <application>} element's
-{@code process} attribute can set a different
-default for all components. But each component can override the default
-with its own {@code process} attribute, allowing you to spread your
-application across multiple processes.
-
-
-If the name assigned to this attribute begins with a colon (':'), a new
-process, private to the application, is created when it's needed and
-the activity runs in that process.
-If the process name begins with a lowercase character, the activity will run
-in a global process of that name, provided that it has permission to do so.
-This allows components in different applications to share a process, reducing
-resource usage.
-
-
-
{@code android:readPermission}
-
A permission that clients must have to query the content provider.
-See also the {@code permission} and
-{@code writePermission} attributes.
-
-
{@code android:syncable}
-
Whether or not the data under the content provider's control
-is to be synchronized with data on a server — "{@code true}"
-if it is to be synchronized, and "{@ code false}" if not.
-
-
{@code android:writePermission}
-
A permission that clients must have to make changes to the data
-controlled by the content provider.
-See also the {@code permission} and
-{@code readPermission} attributes.
Declares a broadcast receiver (a {@link android.content.BroadcastReceiver}
-subclass) as one of the application's components. Broadcast receivers enable
-applications to receive intents that are broadcast by the system or by other
-applications, even when other components of the application are not running.
-
-
-There are two ways to make a broadcast receiver known to the system: One is
-declare it in the manifest file with this element. The other is to create
-the receiver dynamically in code and register it with the {@link
-android.content.Context#registerReceiver Context.registerReceiver()}
-method. See the {@link android.content.BroadcastReceiver} class description
-for more on dynamically created receivers.
-
-
-
attributes:
-
-
{@code android:enabled}
-
Whether or not the broadcast receiver can be instantiated by the system —
-"{@code true}" if it can be, and "{@code false}" if not. The default value
-is "{@code true}".
-
-
-The {@code <application>} element has its own
-{@code enabled} attribute that applies to all
-application components, including broadcast receivers. The
-{@code <application>} and
-{@code <receiver>} attributes must both be "{@code true}" for
-the broadcast receiver to be enabled. If either is "{@code false}", it is
-disabled; it cannot be instantiated.
-
-
-
{@code android:exported}
-
Whether or not the broadcast receiver can receive messages from sources
-outside its application — "{@code true}" if it can, and "{@code false}"
-if not. If "{@code false}", the only messages the broadcast receiver can
-receive are those sent by components of the same application or applications
-with the same user ID.
-
-
-The default value depends on whether the broadcast receiver contains intent filters.
-The absence of any filters means that it can be invoked only by Intent objects that
-specify its exact class name. This implies that the receiver is intended only for
-application-internal use (since others would not normally know the class name).
-So in this case, the default value is "{@code false}".
-On the other hand, the presence of at least one filter implies that the broadcast
-receiver is intended to receive intents broadcast by the system or other applications,
-so the default value is "{@code true}".
-
-
-
-This attribute is not the only way to limit a broadcast receiver's external exposure.
-You can also use a permission to limit the external entities that can send it messages
-(see the {@code permission} attribute).
-
-
-
{@code android:icon}
-
An icon representing the broadcast receiver. This attribute must be set
-as a reference to a drawable resource containing the image definition.
-If it is not set, the icon specified for the application as a whole is used
-instead (see the {@code <application>}
-element's {@code icon} attribute).
-
-
-The broadcast receiver's icon — whether set here or by the
-{@code <application>} element — is also the
-default icon for all the receiver's intent filters (see the
-{@code <intent-filter>} element's
-{@code icon} attribute).
-
-
-
{@code android:label}
-
A user-readable label for the broadcast receiver. If this attribute is not
-set, the label set for the application as a whole is
-used instead (see the {@code <application>} element's
-{@code label} attribute).
-
-
-The broadcast receiver's label — whether set here or by the
-{@code <application>} element — is also the
-default label for all the receiver's intent filters (see the
-{@code <intent-filter>} element's
-{@code label} attribute).
-
-
-
-The label should be set as a reference to a string resource, so that
-it can be localized like other strings in the user interface.
-However, as a convenience while you're developing the application,
-it can also be set as a raw string.
-
-
-
{@code android:name}
-
The name of the class that implements the broadcast receiver, a subclass of
-{@link android.content.BroadcastReceiver}. This should be a fully qualified
-class name (such as, "{@code com.example.project.ReportReceiver}"). However,
-as a shorthand, if the first character of the name is a period (for example,
-"{@code . ReportReceiver}"), it is appended to the package name specified in
-the {@code <manifest>} element.
-
-
-There is no default. The name must be specified.
-
-
-
{@code android:permission}
-
The name of a permission that broadcasters must have to send a
-message to the broadcast receiver.
-If this attribute is not set, the permission set by the
-{@code <application>} element's
-{@code permission} attribute applies
-to the broadcast receiver. If neither attribute is set, the receiver
-is not protected by a permission.
-
-
-For more information on permissions, see the Permissions
-section earlier in this document and a separate document,
-Security and
-Permissions.
-
-
-
{@code android:process}
-
The name of the process in which the broadcast receiver should run.
-Normally, all components of an application run in the default process created
-for the application. It has the same name as the application package. The
-{@code <application>} element's
-{@code process} attribute can set a different
-default for all components. But each component can override the default
-with its own {@code process} attribute, allowing you to spread your
-application across multiple processes.
-
-
-If the name assigned to this attribute begins with a colon (':'), a new
-process, private to the application, is created when it's needed and
-the broadcast receiver runs in that process.
-If the process name begins with a lowercase character, the receiver will run
-in a global process of that name, provided that it has permission to do so.
-This allows components in different applications to share a process, reducing
-resource usage.
-
Declares a service (a {@link android.app.Service} subclass) as one
-of the application's components. Unlike activities, services lack a
-visual user interface. They're used to implement long-running background
-operations or a rich communications API that can be called by other
-applications.
-
-
-All services must be represented by {@code <service>} elements in
-the manifest file. Any that are not declared there will not be seen
-by the system and will never be run.
-
-
-
attributes:
-
-
{@code android:enabled}
-
Whether or not the service can be instantiated by the system —
-"{@code true}" if it can be, and "{@code false}" if not. The default value
-is "{@code true}".
-
-
-The {@code <application>} element has its own
-{@code enabled} attribute that applies to all
-application components, including services. The
-{@code <application>} and {@code <service>}
-attributes must both be "{@code true}" (as they both
-are by default) for the service to be enabled. If either is
-"{@code false}", the service is disabled; it cannot be instantiated.
-
-
-
{@code android:exported}
-
Whether or not components of other applications can invoke
-the service or interact with it — "{@code true}" if they can, and
-"{@code false}" if not. When the value is "{@code false}", only
-components of the same application or applications
-with the same user ID can start the service or bind to it.
-
-
-The default value depends on whether the service contains intent filters. The
-absence of any filters means that it can be invoked only by specifying
-its exact class name. This implies that the service is intended only for
-application-internal use (since others would not know the class name). So in
-this case, the default value is "{@code false}".
-On the other hand, the presence of at least one filter implies that the service
-is intended for external use, so the default value is "{@code true}".
-
-
-
-This attribute is not the only way to limit the exposure of a service to other
-applications. You can also use a permission to limit the external entities that
-can interact with the service (see the {@code permission}
-attribute).
-
-
-
{@code android:icon}
-
An icon representing the service. This attribute must be set as a
-reference to a drawable resource containing the image definition.
-If it is not set, the icon specified for the application
-as a whole is used instead (see the {@code <application>}
-element's {@code icon} attribute).
-
-
-
-The service's icon — whether set here or by the
-{@code <application>} element — is also the
-default icon for all the service's intent filters (see the
-{@code <intent-filter>} element's
-{@code icon} attribute).
-
-
-
{@code android:label}
-
A name for the service that can be displayed to users.
-If this attribute is not set, the label set for the application as a whole is
-used instead (see the {@code <application>} element's
-{@code label} attribute).
-
-
-The service's label — whether set here or by the
-{@code <application>} element — is also the
-default label for all the service's intent filters (see the
-{@code <intent-filter>} element's
-{@code label} attribute).
-
-
-
-The label should be set as a reference to a string resource, so that
-it can be localized like other strings in the user interface.
-However, as a convenience while you're developing the application,
-it can also be set as a raw string.
-
-
-
{@code android:name}
-
The name of the {@link android.app.Service} subclass that implements
-the service. This should be a fully qualified class name (such as,
-"{@code com.example.project.RoomService}"). However, as a shorthand, if
-the first character of the name is a period (for example, "{@code .RoomService}"),
-it is appended to the package name specified in the
-{@code <manifest>} element.
-
-
-There is no default. The name must be specified.
-
-
-
{@code android:permission}
-
The name of a permission that that an entity must have in order to
-launch the service or bind to it. If a caller of
-{@link android.content.Context#startService startService()},
-{@link android.content.Context#bindService bindService()}, or
-{@link android.content.Context#stopService stopService()},
-has not been granted this permission, the method will not work and the
-Intent object will not be delivered to the service.
-
-
-If this attribute is not set, the permission set by the
-{@code <application>} element's
-{@code permission} attribute applies
-to the service. If neither attribute is set, the service is
-not protected by a permission.
-
-
-
-For more information on permissions, see the Permissions
-section earlier in this document and a separate document,
-Security and
-Permissions.
-
-
-
{@code android:process}
-
The name of the process where the service is to run. Normally,
-all components of an application run in the default process created for the
-application. It has the same name as the application package. The
-{@code <application>} element's
-{@code process} attribute can set a different
-default for all components. But component can override the default
-with its own {@code process} attribute, allowing you to spread your
-application across multiple processes.
-
-
-If the name assigned to this attribute begins with a colon (':'), a new
-process, private to the application, is created when it's needed and
-the service runs in that process.
-If the process name begins with a lowercase character, the service will run
-in a global process of that name, provided that it has permission to do so.
-This allows components in different applications to share a process, reducing
-resource usage.
-
Specifies a shared library that the application must be linked against.
-This element tells the system to include the library's code in the class
-loader for the package.
-
-
-All of the {@code android} packages (such as {@link android.app},
-{@link android.content}, {@link android.view}, and {@link android.widget})
-are in the default library that all applications are automatically linked
-against. However, some packages (such as {@code maps} and {@code awt} are
-in separate libraries that are not automatically linked. Consult the
-documentation for the packages you're using to determine which library
-contains the package code.
-
Requests a permission that the application must be granted in
-order for it to operate correctly. Permissions are granted when the
-application is installed, not while it's running.
-
-
-For more information on permissions, see the
-{@code Permissions} section earlier in this document
-and the separate Security Model
-document.
-A list of permissions defined by the base platform can be found at
-{@link android.Manifest.permission android.Manifest.permission}.
-
-
attributes:
-
-
{@code android:name}
-
The name of the permission. It can be a permission defined by the
-application with the {@code <permission>}
-element, a permission defined by another application, or one of the
-standard system permissions, such as "{@code android.permission.CAMERA}"
-or "{@code android.permission.READ_CONTACTS}". As these examples show,
-a permission name typically includes the package name as a prefix.
Declares which versions of the Android SDK (software development kit)
-the application can run against. The version number is incremented when
-there are additions to the API and resource tree, so an application developed
-using version 3 of the SDK may not run against versions 1 or 2, but should
-run against version 3, 4, 5, and above.
-
-
-The default is version 1. The current version is also 1.
-
-
-
attributes:
-
-
{@code android:minSdkVersion}
-
An integer designating the minimum version of the SDK that's required
-for the application to run.
A name-value pair for an item of additional, arbitrary data that can
+be supplied to the parent component. A component element can contain any
+number of {@code <meta-data>} subelements. The values from all of
+them are collected in a single {@link android.os.Bundle} object and made
+available to the component as the
+{@link android.content.pm.PackageItemInfo#metaData
+PackageItemInfo.metaData} field.
+
+
+Ordinary values are specified through the value
+attribute. However, to assign a resource ID as the value, use the
+resource attribute instead. For example,
+the following code assigns whatever value is stored in the {@code @string/kangaroo}
+resource to the "{@code zoo}" name:
+
+On the other hand, using the {@code resource} attribute would assign "{@code zoo}"
+the numeric ID of the resource, not the value stored in the resource:
+
+It is highly recommended that you avoid supplying related data as
+multiple separate {@code <meta-data>} entries. Instead, if you
+have complex data to associate with a component, store it as a resource and
+use the {@code resource} attribute to inform the component of its ID.
+
+
+
attributes:
+
+
{@code android:name}
+
A unique name for the item. To ensure that the name is unique, use a
+Java-style naming convention — for example,
+"{@code com.example.project.activity.fred}".
+
+
{@code android:resource}
+
A reference to a resource. The ID of the resource is the value assigned
+to the item. The ID can be retrieved from the meta-data Bundle by the
+{@link android.os.Bundle#getInt Bundle.getInt()} method.
+
+
{@code android:value}
+
The value assigned to the item. The data types that can be assigned as values and the Bundle methods that components use to retrieve those values are listed in the following table:
+
+
+
+
Type
+
Bundle method
+
+
String value, using double backslashes ({@code \\}) to escape characters
+ — such as "{@code \\n}" and "{@code \\uxxxxx}" for a Unicode character.
Declares a security permission that can be used to limit access
+to specific components or features of this or other applications.
+See the Permissions
+section in the introduction,
+and the Security and Permissions
+document for more information on how permissions work.
+
+
attributes:
+
+
{@code android:description}
+
A user-readable description of the permission, longer and more
+informative than the label. It may be displayed to explain the
+permission to the user — for example, when the user is asked
+whether to grant the permission to another application.
+
+
+This attribute must be set as a reference to a string resource;
+unlike the {@code label} attribute, it cannot be a raw string.
+
+
+
{@code android:icon}
+
A reference to a drawable resource for an icon that represents the
+permission.
+
+
{@code android:label}
+
A name for the permission, one that can be displayed to users.
+
+
+As a convenience, the label can be directly set
+as a raw string while you're developing the application. However,
+when the application is ready to be published, it should be set as a
+reference to a string resource, so that it can be localized like other
+strings in the user interface.
+
+
+
{@code android:name}
+
The name of the permission. This is the name that will be used in
+code to refer to the permission — for example, in a
+<uses-permission> element and the
+{@code permission} attributes of application components.
+
+
+The name must be unique, so it should use Java-style scoping —
+for example, "{@code com.example.project.PERMITTED_ACTION}".
+
+
+
{@code android:permissionGroup}
+
Assigns this permission to a group. The value of this attribute is
+the name of the group, which must be declared with the
+<permission-group> element in this
+or another application. If this attribute is not set, the permission
+does not belong to a group.
+
+
{@code android:protectionLevel}
+
Characterizes the potential risk implied in the permission and
+indicates the procedure the system should follow when determining
+whether or not to grant the permission to an application requesting it.
+The value can be set to one of the following strings:
+
+
+
+
Value
+
Meaning
+
+
"{@code normal}"
+
The default value. A lower-risk permission that gives requesting
+ applications access to isolated application-level features, with
+ minimal risk to other applications, the system, or the user.
+ The system automatically grants this type
+ of permission to a requesting application at installation, without
+ asking for the user's explicit approval (though the user always
+ has the option to review these permissions before installing).
+
+
"{@code dangerous}"
+
A higher-risk permission that would give a requesting application
+ access to private user data or control over the device that can
+ negatively impact the user. Because this type of permission
+ introduces potential risk, the system may not automatically
+ grant it to the requesting application. For example, any dangerous
+ permissions requested by an application may be displayed to the
+ user and require confirmation before proceeding, or some other
+ approach may be taken to avoid the user automatically allowing
+ the use of such facilities.
+
+
"{@code signature}"
+
A permission that the system grants only if the requesting
+ application is signed with the same certificate as the application
+ that declared the permission. If the certificates match, the system
+ automatically grants the permission without notifying the user or
+ asking for the user's explicit approval.
+
+
"{@code signatureOrSystem}"
+
A permission that the system grants only to applications that are
+ in the Android system image or that are signed with the same
+ certificates as those in the system image. Please avoid using this
+ option, as the {@code signature} protection level should be sufficient
+ for most needs and works regardless of exactly where applications are
+ installed. The "{@code signatureOrSystem}"
+ permission is used for certain special situations where multiple
+ vendors have applications built into a system image and need
+ to share specific features explicitly because they are being built
+ together.
+
Declares a name for a logical grouping of related permissions. Individual
+permission join the group through the {@code permissionGroup} attribute of the
+<permission> element. Members of a group are
+presented together in the user interface.
+
+
+Note that this element does not declare a permission itself, only a category in
+which permissions can be placed. See the
+<permission> element for element for information
+on declaring permissions and assigning them to groups.
+
+
+
attributes:
+
+
{@code android:description}
+
User-readable text that describes the group. The text should be
+longer and more explanatory than the label. This attribute must be
+set as a reference to a string resource. Unlike the {@code label}
+attribute, it cannot be a raw string.
+
+
{@code android:icon}
+
An icon representing the permission. This attribute must be set
+as a reference to a drawable resource containing the image definition.
+
+
{@code android:label}
+
A user-readable name for the group. As a convenience, the label can
+be directly set as a raw string while you're developing the application.
+However, when the application is ready to be published, it should be set
+as a reference to a string resource, so that it can be localized like other
+strings in the user interface.
+
+
{@code android:name}
+
The name of the group. This is the name that can be assigned to a
+<permission>
+element's
+<permissionGroup>
+attribute.
Declares the base name for a tree of permissions. The application takes
+ownership of all names within the tree. It can dynamically add new permissions
+to the tree by calling {@link android.content.pm.PackageManager#addPermission PackageManager.addPermission()}. Names within the tree are separated by
+periods ('{@code .}'). For example, if the base name is
+{@code com.example.project.taxes}, permissions like the following might be
+added:
+
+
+Note that this element does not declare a permission itself, only a
+namespace in which further permissions can be placed. See the
+<permission>
+element for information on declaring permissions.
+
+
attributes:
+
+
{@code android:icon}
+
An icon representing all the permissions in the tree. This attribute
+must be set as a reference to a drawable resource containing the image
+definition.
+
+
{@code android:label}
+
A user-readable name for the group. As a convenience, the label can
+be directly set as a raw string for quick and dirty programming. However,
+when the application is ready to be published, it should be set as a
+reference to a string resource, so that it can be localized like other
+strings in the user interface.
The name that's at the base of the permission tree. It serves as
+a prefix to all permission names in the tree. Java-style scoping should
+be used to ensure that the name is unique. The name must have more than
+two period-separated seqments in its path — for example,
+{@code com.example.base} is OK, but {@code com.example} is not.
Declares a content provider — a subclass of
+{@link android.content.ContentProvider} — that supplies structured
+access to data managed by the application. All content providers that
+are part of the application must be represented by {@code <provider>}
+elements in the manifest file. The system cannot see, and therefore will
+not run, any that are not declared. (You need to declare only
+those content providers that you develop as part of your application,
+not those developed by others that your application uses.)
+
+
+The Android system identifies content providers by the authority part
+ of a {@code content:} URI. For example, suppose that the following URI
+is passed to {@link android.content.ContentResolver#query
+ContentResolver.query()}:
+
+
+The {@code content:} scheme identifies the data as belonging to a content
+provider and the authority ({@code com.example.project.healthcareprovider})
+identifies the particular provider. The authority therefore must be unique.
+Typically, as in this example, it's the fully qualified name of a
+ContentProvider subclass. The path part of a URI may be used by a content
+provider to identify particular data subsets, but those paths are not
+declared in the manifest.
+
+
+
+For information on using and developing content providers, see a separate document,
+Content Providers.
+
+
+
attributes:
+
+
{@code android:authorities}
+
A list of one or more URI authorities that identify data under the purview
+of the content provider.
+Multiple authorities are listed by separating their names with a semicolon.
+To avoid conflicts, authority names should use a Java-style naming convention
+(such as {@code com.example.provider.cartoonprovider}). Typically, it's the name
+of the ContentProvider subclass.
+
+
+There is no default. At least one authority must be specified.
+
+
+
{@code android:enabled}
+
Whether or not the content provider can be instantiated by the system —
+"{@code true}" if it can be, and "{@code false}" if not. The default value
+is "{@code true}".
+
+
+The <application> element has its own
+enabled attribute that applies to all
+application components, including content providers. The
+<application> and {@code <provider>}
+attributes must both be "{@code true}" (as they both
+are by default) for the content provider to be enabled. If either is
+"{@code false}", the provider is disabled; it cannot be instantiated.
+
+
+
{@code android:exported}
+
Whether or not the content provider can be used by components of other
+applications — "{@code true}" if it can be, and "{@code false}" if not.
+If "{@code false}", the provider is available only to components of the
+same application or applications with the same user ID. The default value
+is "{@code true}".
+
+
+You can export a content provider but still limit access to it with the
+permission attribute.
+
+
+
{@code android:grantUriPermissions}
+
Whether or not those who ordinarily would not have permission to
+access the content provider's data can be granted permission to do so,
+temporarily overcoming the restriction imposed by the
+readPermission,
+writePermission, and
+permission attributes
+—
+"{@code true}" if permission can be granted, and "{@ code false}" if not.
+If "{@code true}", permission can be granted to any of the content
+provider's data. If "{@code false}", permission can be granted only
+to the data subsets listed in
+<grant-uri-permission> subelements,
+if any. The default value is "{@code false}".
+
+
+Granting permission is a way of giving an application component one-time
+access to data protected by a permission. For example, when an e-mail
+message contains an attachment, the mail application may call upon the
+appropriate viewer to open it, even though the viewer doesn't have general
+permission to look at all the content provider's data.
+
+
+
+In such cases, permission is granted by
+{@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION}
+and {@link android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION}
+flags in the Intent object that activates the component. For example, the
+mail application might put {@code FLAG_GRANT_READ_URI_PERMISSION} in the
+Intent passed to {@code Context.startActivity()}. The permission is specific
+to the URI in the Intent.
+
+
+
+If you enable this feature, either by setting this attribute to "{@code true}"
+or by defining <grant-uri-permission>
+subelements, you must call
+{@link android.content.Context#revokeUriPermission
+Context.revokeUriPermission()} when a covered URI is deleted from
+the provider.
+
An icon representing the content provider.
+This attribute must be set as a reference to a drawable resource containing
+the image definition. If it is not set, the icon specified for the application
+as a whole is used instead (see the <application>
+element's icon attribute).
+
+
{@code android:initOrder}
+
The order in which the content provider should be instantiated,
+relative to other content providers hosted by the same process.
+When there are dependencies among content providers, setting this
+attribute for each of them ensures that they are created in the order
+required by those dependencies. The value is a simple integer,
+with higher numbers being initialized first.
+
+
{@code android:label}
+
A user-readable label for the content provided.
+If this attribute is not set, the label set for the application as a whole is
+used instead (see the <application> element's
+label attribute).
+
+
+The label should be set as a reference to a string resource, so that
+it can be localized like other strings in the user interface.
+However, as a convenience while you're developing the application,
+it can also be set as a raw string.
+
+
+
{@code android:multiprocess}
+
Whether or not an instance of the content provider can be created in
+every client process — "{@code true}" if instances can run in multiple
+processes, and "{@code false}" if not. The default value is "{@code false}".
+
+
+Normally, a content provider is instantiated in the process of the
+application that defined it. However, if this flag is set to "{@code true}",
+the system can create an instance in every process where there's a client
+that wants to interact withit, thus avoiding the overhead of interprocess
+communication.
+
+
+
{@code android:name}
+
The name of the class that implements the content provider, a subclass of
+{@link android.content.ContentProvider}. This should be a fully qualified
+class name (such as, "{@code com.example.project.TransportationProvider}").
+However, as a shorthand, if the first character of the name is a period,
+it is appended to the package name specified in the
+<manifest> element.
+
+
+There is no default. The name must be specified.
+
+
+
+
{@code android:permission}
+
The name of a permission that clients must have to read or write the
+content provider's data. This attribute is a convenient way of setting a
+single permission for both reading and writing. However, the
+readPermission and
+writePermission attributes take precedence
+over this one. If the readPermission
+attribute is also set, it controls access for querying the content provider.
+And if the writePermission attribute is set,
+it controls access for modifying the provider's data.
+
+
The name of the process in which the content provider should run. Normally,
+all components of an application run in the default process created for the
+application. It has the same name as the application package. The
+<application> element's
+process
+attribute can set a different
+default for all components. But each component can override the default
+with its own {@code process} attribute, allowing you to spread your
+application across multiple processes.
+
+
+If the name assigned to this attribute begins with a colon (':'), a new
+process, private to the application, is created when it's needed and
+the activity runs in that process.
+If the process name begins with a lowercase character, the activity will run
+in a global process of that name, provided that it has permission to do so.
+This allows components in different applications to share a process, reducing
+resource usage.
+
+
+
{@code android:readPermission}
+
A permission that clients must have to query the content provider.
+See also the permission and
+writePermission attributes.
+
+
{@code android:syncable}
+
Whether or not the data under the content provider's control
+is to be synchronized with data on a server — "{@code true}"
+if it is to be synchronized, and "{@ code false}" if not.
+
+
{@code android:writePermission}
+
A permission that clients must have to make changes to the data
+controlled by the content provider.
+See also the permission and
+readPermission attributes.
Declares a broadcast receiver (a {@link android.content.BroadcastReceiver}
+subclass) as one of the application's components. Broadcast receivers enable
+applications to receive intents that are broadcast by the system or by other
+applications, even when other components of the application are not running.
+
+
+There are two ways to make a broadcast receiver known to the system: One is
+declare it in the manifest file with this element. The other is to create
+the receiver dynamically in code and register it with the {@link
+android.content.Context#registerReceiver Context.registerReceiver()}
+method. See the {@link android.content.BroadcastReceiver} class description
+for more on dynamically created receivers.
+
+
+
attributes:
+
+
{@code android:enabled}
+
Whether or not the broadcast receiver can be instantiated by the system —
+"{@code true}" if it can be, and "{@code false}" if not. The default value
+is "{@code true}".
+
+
+The <application> element has its own
+enabled attribute that applies to all
+application components, including broadcast receivers. The
+<application> and
+{@code <receiver>} attributes must both be "{@code true}" for
+the broadcast receiver to be enabled. If either is "{@code false}", it is
+disabled; it cannot be instantiated.
+
+
+
{@code android:exported}
+
Whether or not the broadcast receiver can receive messages from sources
+outside its application — "{@code true}" if it can, and "{@code false}"
+if not. If "{@code false}", the only messages the broadcast receiver can
+receive are those sent by components of the same application or applications
+with the same user ID.
+
+
+The default value depends on whether the broadcast receiver contains intent filters.
+The absence of any filters means that it can be invoked only by Intent objects that
+specify its exact class name. This implies that the receiver is intended only for
+application-internal use (since others would not normally know the class name).
+So in this case, the default value is "{@code false}".
+On the other hand, the presence of at least one filter implies that the broadcast
+receiver is intended to receive intents broadcast by the system or other applications,
+so the default value is "{@code true}".
+
+
+
+This attribute is not the only way to limit a broadcast receiver's external exposure.
+You can also use a permission to limit the external entities that can send it messages
+(see the permission attribute).
+
+
+
{@code android:icon}
+
An icon representing the broadcast receiver. This attribute must be set
+as a reference to a drawable resource containing the image definition.
+If it is not set, the icon specified for the application as a whole is used
+instead (see the <application>
+element's icon attribute).
+
+
+The broadcast receiver's icon — whether set here or by the
+<application> element — is also the
+default icon for all the receiver's intent filters (see the
+<intent-filter> element's
+icon attribute).
+
+
+
{@code android:label}
+
A user-readable label for the broadcast receiver. If this attribute is not
+set, the label set for the application as a whole is
+used instead (see the <application> element's
+label attribute).
+
+
+The broadcast receiver's label — whether set here or by the
+<application> element — is also the
+default label for all the receiver's intent filters (see the
+<intent-filter> element's
+label attribute).
+
+
+
+The label should be set as a reference to a string resource, so that
+it can be localized like other strings in the user interface.
+However, as a convenience while you're developing the application,
+it can also be set as a raw string.
+
+
+
{@code android:name}
+
The name of the class that implements the broadcast receiver, a subclass of
+{@link android.content.BroadcastReceiver}. This should be a fully qualified
+class name (such as, "{@code com.example.project.ReportReceiver}"). However,
+as a shorthand, if the first character of the name is a period (for example,
+"{@code . ReportReceiver}"), it is appended to the package name specified in
+the <manifest> element.
+
+
+There is no default. The name must be specified.
+
+
+
{@code android:permission}
+
The name of a permission that broadcasters must have to send a
+message to the broadcast receiver.
+If this attribute is not set, the permission set by the
+<application> element's
+permission attribute applies
+to the broadcast receiver. If neither attribute is set, the receiver
+is not protected by a permission.
+
+
+For more information on permissions, see the
+Permissions
+section in the introduction and a separate document,
+Security and Permissions.
+
+
+
{@code android:process}
+
The name of the process in which the broadcast receiver should run.
+Normally, all components of an application run in the default process created
+for the application. It has the same name as the application package. The
+<application> element's
+process attribute can set a different
+default for all components. But each component can override the default
+with its own {@code process} attribute, allowing you to spread your
+application across multiple processes.
+
+
+If the name assigned to this attribute begins with a colon (':'), a new
+process, private to the application, is created when it's needed and
+the broadcast receiver runs in that process.
+If the process name begins with a lowercase character, the receiver will run
+in a global process of that name, provided that it has permission to do so.
+This allows components in different applications to share a process, reducing
+resource usage.
+
Declares a service (a {@link android.app.Service} subclass) as one
+of the application's components. Unlike activities, services lack a
+visual user interface. They're used to implement long-running background
+operations or a rich communications API that can be called by other
+applications.
+
+
+All services must be represented by {@code <service>} elements in
+the manifest file. Any that are not declared there will not be seen
+by the system and will never be run.
+
+
+
attributes:
+
+
{@code android:enabled}
+
Whether or not the service can be instantiated by the system —
+"{@code true}" if it can be, and "{@code false}" if not. The default value
+is "{@code true}".
+
+
+The <application> element has its own
+enabled attribute that applies to all
+application components, including services. The
+<application> and {@code <service>}
+attributes must both be "{@code true}" (as they both
+are by default) for the service to be enabled. If either is
+"{@code false}", the service is disabled; it cannot be instantiated.
+
+
+
{@code android:exported}
+
Whether or not components of other applications can invoke
+the service or interact with it — "{@code true}" if they can, and
+"{@code false}" if not. When the value is "{@code false}", only
+components of the same application or applications
+with the same user ID can start the service or bind to it.
+
+
+The default value depends on whether the service contains intent filters. The
+absence of any filters means that it can be invoked only by specifying
+its exact class name. This implies that the service is intended only for
+application-internal use (since others would not know the class name). So in
+this case, the default value is "{@code false}".
+On the other hand, the presence of at least one filter implies that the service
+is intended for external use, so the default value is "{@code true}".
+
+
+
+This attribute is not the only way to limit the exposure of a service to other
+applications. You can also use a permission to limit the external entities that
+can interact with the service (see the permission
+attribute).
+
+
+
{@code android:icon}
+
An icon representing the service. This attribute must be set as a
+reference to a drawable resource containing the image definition.
+If it is not set, the icon specified for the application
+as a whole is used instead (see the <application>
+element's icon attribute).
+
+
+
+The service's icon — whether set here or by the
+<application> element — is also the
+default icon for all the service's intent filters (see the
+<intent-filter> element's
+icon attribute).
+
+
+
{@code android:label}
+
A name for the service that can be displayed to users.
+If this attribute is not set, the label set for the application as a whole is
+used instead (see the <application> element's
+label attribute).
+
+
+The service's label — whether set here or by the
+<application> element — is also the
+default label for all the service's intent filters (see the
+<intent-filter> element's
+label attribute).
+
+
+
+The label should be set as a reference to a string resource, so that
+it can be localized like other strings in the user interface.
+However, as a convenience while you're developing the application,
+it can also be set as a raw string.
+
+
+
{@code android:name}
+
The name of the {@link android.app.Service} subclass that implements
+the service. This should be a fully qualified class name (such as,
+"{@code com.example.project.RoomService}"). However, as a shorthand, if
+the first character of the name is a period (for example, "{@code .RoomService}"),
+it is appended to the package name specified in the
+<manifest> element.
+
+
+There is no default. The name must be specified.
+
+
+
{@code android:permission}
+
The name of a permission that that an entity must have in order to
+launch the service or bind to it. If a caller of
+{@link android.content.Context#startService startService()},
+{@link android.content.Context#bindService bindService()}, or
+{@link android.content.Context#stopService stopService()},
+has not been granted this permission, the method will not work and the
+Intent object will not be delivered to the service.
+
+
+If this attribute is not set, the permission set by the
+<application> element's
+permission
+attribute applies to the service. If neither attribute is set, the service is
+not protected by a permission.
+
+
+
+For more information on permissions, see the
+Permissions
+section in the introduction and a separate document,
+Security and Permissions.
+
+
+
{@code android:process}
+
The name of the process where the service is to run. Normally,
+all components of an application run in the default process created for the
+application. It has the same name as the application package. The
+<application> element's
+process
+attribute can set a different
+default for all components. But component can override the default
+with its own {@code process} attribute, allowing you to spread your
+application across multiple processes.
+
+
+If the name assigned to this attribute begins with a colon (':'), a new
+process, private to the application, is created when it's needed and
+the service runs in that process.
+If the process name begins with a lowercase character, the service will run
+in a global process of that name, provided that it has permission to do so.
+This allows components in different applications to share a process, reducing
+resource usage.
+
Specifies a shared library that the application must be linked against.
+This element tells the system to include the library's code in the class
+loader for the package.
+
+
+All of the {@code android} packages (such as {@link android.app},
+{@link android.content}, {@link android.view}, and {@link android.widget})
+are in the default library that all applications are automatically linked
+against. However, some packages (such as {@code maps} and {@code awt} are
+in separate libraries that are not automatically linked. Consult the
+documentation for the packages you're using to determine which library
+contains the package code.
+
Requests a permission that the application must be granted in
+order for it to operate correctly. Permissions are granted when the
+application is installed, not while it's running.
+
+
+For more information on permissions, see the
+Permissions
+section in the introduction and the separate
+Security and Permissions document.
+A list of permissions defined by the base platform can be found at
+{@link android.Manifest.permission android.Manifest.permission}.
+
+
attributes:
+
+
{@code android:name}
+
The name of the permission. It can be a permission defined by the
+application with the <permission>
+element, a permission defined by another application, or one of the
+standard system permissions, such as "{@code android.permission.CAMERA}"
+or "{@code android.permission.READ_CONTACTS}". As these examples show,
+a permission name typically includes the package name as a prefix.
Declares which levels of the Android API the application can run against.
+The level is incremented when there are additions to the API and resource tree,
+so an application developed using level 3 of the API may not run against level
+1 or 2, but should run against level 3, 4, 5, and above.
+
+
+
An integer designating the minimum level of the Android API that's required
+for the application to run.
+
+
+Despite its name, this attribute is set to the API level, not to the
+version number of the SDK (software development kit). The API level is always
+a single integer; the SDK version may be split into major and minor components
+(such as 1.2). You cannot derive the API level from the SDK version number
+(for example, it is not the same as the major version or the sum of the major
+and minor versions). To learn what the API level is, check the notes that
+came with the SDK you're using.
+
Note that it is necessary to have the People._ID column in projection used with CursorAdapter
or else you will get an exception.
+
If, during the course of your application's life, you change the underlying data that is read by your Adapter,
+you should call {@link android.widget.ArrayAdapter#notifyDataSetChanged()}. This will notify the attached View
+that the data has been changed and it should refresh itself.
Handling User Selections
You handle the user's selecction by setting the class's {@link
diff --git a/docs/html/guide/topics/ui/declaring-layout.jd b/docs/html/guide/topics/ui/declaring-layout.jd
index dd0b7deb5c06e..7ef22a6be2419 100644
--- a/docs/html/guide/topics/ui/declaring-layout.jd
+++ b/docs/html/guide/topics/ui/declaring-layout.jd
@@ -5,6 +5,12 @@ parent.link=index.html
Tip: You can also draw View and ViewGroups objects in Java code,
using the {@link android.view.ViewGroup#addView(View)} methods
to dynamically insert new View and ViewGroup objects.
@@ -66,7 +75,7 @@ or a reference to any other resource type.
Now this EditText widget will be styled as defined by the style example above.
-
Themes
+
Themes
Just like styles, themes are also declared in XML <style> elements, and are referenced in the same manner.
The difference is that you can add a theme style only to <application> and <activity> elements —
@@ -100,8 +109,8 @@ is done by referring to a specific <item> by its name
-
Set the theme in the Manifest
-
To set this theme for all the activites of your application, open the Manifest file and
+
Set the theme in the manifest
+
To set this theme for all the activites of your application, open the AndroidManifest.xml file and
edit the <application> tag to include the android:theme attribute with the
theme name:
@@ -136,7 +145,7 @@ For example, we'll modify the Theme.Dialog theme. First, we need to
So, for each item in the Dialog theme that we want to override, we re-define the value under this style and
then use CustomDialogTheme instead of the Theme.Dialog.
-
Set the theme from the application
+
Set the theme from the application
You can also load a theme for an Activity programmatically, if needed.
To do so, use the {@link android.app.Activity#setTheme(int) setTheme()}
method. Note that, when doing so, you must be sure to set the theme before
diff --git a/docs/html/guide/tutorials/hello-world.jd b/docs/html/guide/tutorials/hello-world.jd
index bbc4f77987305..7b9287fabfe85 100644
--- a/docs/html/guide/tutorials/hello-world.jd
+++ b/docs/html/guide/tutorials/hello-world.jd
@@ -2,37 +2,40 @@ page.title=Hello, World
@jd:body
As a developer, you know that the first impression
-you get of a development framework is how easy it is to write "Hello,
-World." Well, on Android, it's pretty easy.
-
-
It's particularly easy if you're using Eclipse as your IDE, because we've provided a
+of a development framework is how easy it is to write "Hello,
+World." Well, on Android, it's pretty easy.
+It's particularly easy if you're using Eclipse as your IDE, because we've provided a
great plugin that handles your project creation and management to greatly speed up your
-development cycles. Get Eclipse and visit the
-ADT Plugin page to install it.
+development cycles.
If you're not using Eclipse, that's okay. Familiarize yourself with
Developing in Other IDEs.
You can then come back here and ignore anything about Eclipse.
+
Before you start, you should already have the latest SDK installed, and if you're using
+Eclipse, you should have installed the ADT plugin as well. See
+Installing the Android SDK to get these
+installed.
+
Note:
In some cases, you might want to click the screenshots below to get a bigger view.
Create the Project
-
-
Create a new Android Project.
+
+
Open a new Android Project.
From Eclipse, select the File > New > Project menu item. If the Android
Plugin for Eclipse has been successfully installed, the resulting dialog
should have a folder labeled "Android" which should contain a single entry:
"Android Project".
+
Selected "Android Project" and click Next.
-
Once you've selected "Android Project", click Next.
-
Fill out the project details.
+
Fill out the project details.
The next screen allows you to enter the relevant details for your project:
Project name: HelloAndroid
@@ -40,7 +43,7 @@ In some cases, you might want to click the screenshots below to get a bigger vie
Activity name: HelloAndroid
Application name: Hello, Android
-
+
Click Finish.
Here's what each field on this screen means:
@@ -74,12 +77,18 @@ In some cases, you might want to click the screenshots below to get a bigger vie
-
Edit the auto-generated source code.
-
After the plugin runs, you'll have a class named HelloAndroid
-(found in your package, HelloAndroid > src > com.android.hello). It should look like
+
View the auto-generated source code.
+
After the plugin completes your project creations, you'll have a class named HelloAndroid
+(found in your project package, HelloAndroid > src > com.android.hello). It should look like
this:
-
public class HelloAndroid extends Activity {
+
+package com.example.hello;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class HelloAndroid extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -88,9 +97,7 @@ this:
}
}
-
Now, you could run this right away, but let's go a little further,
-so we understand more about what's happening.
-So, the next step is to modify some code!
+
Now let's modify some code!
@@ -105,16 +112,16 @@ package com.android.hello;
import android.app.Activity;
import android.os.Bundle;
-import android.widget.TextView;
+import android.widget.TextView;
public class HelloAndroid extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- TextView tv = new TextView(this);
+ TextView tv = new TextView(this);
tv.setText("Hello, Android");
- setContentView(tv);
+ setContentView(tv);
}
}
@@ -122,16 +129,21 @@ public class HelloAndroid extends Activity {
press Ctrl-Shift-O (Cmd-Shift-O, on Mac). This is an Eclipse
shortcut to organize imports—it identifies missing packages and adds them for you.
-
In Android, user interfaces are composed of hierarchies of classes called
-Views. A View is simply a drawable object, such as a radio button, an
+
Notice that our class is based on the {@link android.app.Activity} class. An Activity is a
+single application entity that is used to perform actions. An application may have many, but the user
+interacts with them only one at a time. An Activity is not required to actually have a user interface,
+but usually will.
+
+
An Android user interface is composed of hierarchies of objects called
+Views. A {@link android.view.View} is simply a drawable object, such as a radio button, an
animation, or (in our case) a text label. The specific name for the View
-subclass that handles text is simply TextView.
+subclass that handles text, which we use here, is {@link android.widget.TextView}.
Here's how you construct a TextView:
TextView tv = new TextView(this);
-
The argument to TextView's constructor is an Android Context instance. The
+
The argument to TextView's constructor is an Android {@link android.content.Context} instance. The
Context is simply a handle to the system; it provides services like
resolving resources, obtaining access to databases and preferences, and so
on. The Activity class inherits from Context. Since our
@@ -189,18 +201,21 @@ simply continue.
-
That's it — you're done! Click the Run button, and the Android Emulator
-should start. Once it's booted up your application will appear. When all is said and done, you should
+
Now click Run, and the Android Emulator should start and open the application.
+Once it's booted up your application will appear. (Once booted, you may need to unlock the emulator's phone screen
+by pressing the device MENU key.) When all is said and done, you should
see something like this:
+
That's "Hello, World" in Android. Pretty straightforward, eh?
The next sections of the tutorial offer more detailed information that you may find valuable as you
learn more about Android.
+
Upgrading the UI to an XML Layout
The "Hello, World" example you just completed uses what we call "programmatic"
@@ -220,12 +235,12 @@ programmatically-constructed example you just completed:
The general structure of an Android XML layout file is simple: it's a tree
of XML elements, where each element is the name of a View class
(this example, however, is just one element). You can use the
-name of any class that extends View as an element in your XML layouts,
+name of any class that extends {@link android.view.View} as an element in your XML layouts,
including custom View classes you define in your own code. This
structure makes it very easy to quickly build up UIs, using a more simple
structure and syntax than you would in source code. This model is inspired
@@ -274,14 +289,20 @@ which has four XML attributes. Here's a summary of what they mean:
android:text
- This sets the text that the TextView should contain. In this example, it's our usual "Hello, Android" message.
+ This sets the text that the TextView should display. In this example, we use a string
+ resource instead of a hard-coded string value.
+ The hello string is defined in the res/values/strings.xml file. This is the
+ recommended practice for inserting strings to your application, because it makes the localization
+ of your application to other languages graceful, without need to hard-code changes to the layout file.
+ For more information, see Resources
+ and Internationalization.
-
This layout file belongs in the res/layout/ directory in your project. The "res" is
+
These layout files belong in the res/layout/ directory in your project. The "res" is
short for "resources" and that directory contains all the non-code assets that
your application requires. Resources also include things like images, localized
strings, and XML layout files.
@@ -293,17 +314,43 @@ strings, and XML layout files.
Without it the layout will just be stretched.
-
The Eclipse plugin creates one of these XML files for you (main.xml). In our example
-above, we just ignored it and created our layout programmatically. In the Eclipse Package Explorer, expand the
-folder res/layout/, and open the file main.xml (once opened, you might need to click
+
The Eclipse plugin automatically creates one of these layout files for you (main.xml). In our example
+above, we just ignored it and created our layout programmatically. We did so just to teach you a little more
+about the framework, but you should almost always define your layout in an XML file instead of in your code.
+
+
So, let's put it to use and change the "Hello, Android" sample to use the XML layout.
+
+
+
In the Eclipse Package Explorer, expand the
+folder res/layout/, and open the file main.xml (once opened, you might need to click
the "main.xml" tab at the bottom to see the XML source). Replace its contents with
-the sample XML above and save your changes.
-
-
Now open and modify your HelloAndroid class source code to read the
-XML layout, instead of the hard-coded version. Edit the file to look like this:
Inside the project folder res/values/, open the file strings.xml.
+This is where you should save all default text strings for your user interface. If you're using Eclipse, then
+ADT will have started you with two strings, hello and app_name.
+Revise hello to something else. Perhaps "Hello, Android! I am a string resource!"
+The entire file should now look like this:
-package com.android.hello;
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="hello">Hello, Android! I am a string resource!</string>
+ <string name="app_name">Hello, Android</string>
+</resources>
+
+
+
+
Now open and modify your HelloAndroid class source code to read the
+XML layout, instead of the hard-coded version. Edit the file to look like this:
+
+package com.example.hello;
import android.app.Activity;
import android.os.Bundle;
@@ -319,39 +366,50 @@ public class HelloAndroid extends Activity {
When you make this change, type it by hand to try the code-completion feature on that R class. You'll probably find that it helps a lot.
-
The setContentView() method we're now using expects a reference to a layout resource.
-We pass it R.layout.main, which is the reference to the layout/main.xml once it's
-compiled into our R class by the Eclipse plugin. (More about the R class in a moment.)
+
Now, instead of passing setContentView() a View object, we give it a reference to our layout resource.
+The resource is identified as R.layout.main, which is actually a compiled object representation of
+the layout defined in layout/main.xml. The Eclipse plugin automatically creates this reference for
+us inside the project's R.java class. If you're not using Eclipse, then the R.java class will be generated for you
+when you run Ant to build the application. (More about the R class in a moment.)
+
+
Now that you've made this change, go ahead and re-run your application — all
you need to do is click the green Run arrow icon, or select
-Run > Run History > Hello, Android from the menu. You should see.... well, exactly the same thing
+Run > Run History > Hello, Android from the menu. You should see pretty much the same thing
you saw before! After all, the point was to show that the two different
layout approaches produce identical results.
-
There's a lot more to creating these XML layouts, but that's as far as we'll go
-here. Read the User Interface documentation for more
-information on creating layouts.
+
Tip: Use the shortcut Ctrl-Shift-F11
+(Cmd-Shift-F11, on Mac) to run your currently visible application.
+
+
You've just completed your first Android application! Continue reading for an introduction
+to debugging and a little more information on using other IDEs. Once you're ready to move on,
+please begin by reading Application
+Fundamentals. Also refer to the Developer's Guide
+introduction page for an overview of the Dev Guide documentation.
+
R class
-
Open the file named R.java in your source code folder in the Package
+
In Eclipse, open the file named R.java in your source code folder in the Package
Explorer. It should look something like this:
public final class R {
public static final class attr {
- };
+ }
public static final class drawable {
public static final int icon=0x7f020000;
- };
+ }
public static final class layout {
public static final int main=0x7f030000;
- };
+ }
public static final class string {
- public static final int app_name=0x7f040000;
- };
-};
+ public static final int app_name=0x7f040001;
+ public static final int hello=0x7f040000;
+ }
+}
A project's R.java file is an index into all the resources defined in the
@@ -361,10 +419,13 @@ particularly powerful with the code-completion features of IDEs like Eclipse
because it lets you quickly and interactively locate the specific reference
you're looking for.
-
For now, notice the inner class named "layout", and its
+
It's possible yours looks slighly different than this (perhaps the hexadecimal values are different).
+For now, notice the inner class named "layout", and its
member field "main". The Eclipse plugin noticed the XML
layout file named main.xml and generated a class for it here. As you add other
-resources to your project (in the res/ directory), you'll see R.java change to keep up.
+resources to your project (such as strings in the res/values/string.xml file or drawables inside
+the res/drawable/ direcory) you'll see R.java change to keep up.
+
When not using Eclipse, this class file will be generated for you at build time (with the Ant tool).
You should never edit this file by hand.
@@ -436,4 +497,4 @@ just as you would for any other application.
installed and run in your emulator using the 'adb' tool.
For more information on how to use these tools, please read the documentation
- cited above.
\ No newline at end of file
+ cited above.
diff --git a/docs/html/images/judgebio_charles.jpg b/docs/html/images/judgebio_charles.jpg
deleted file mode 100644
index 2449cfe8cd58e..0000000000000
Binary files a/docs/html/images/judgebio_charles.jpg and /dev/null differ
diff --git a/docs/html/images/judgebio_dibona.jpg b/docs/html/images/judgebio_dibona.jpg
deleted file mode 100644
index 91869fb0ad7c3..0000000000000
Binary files a/docs/html/images/judgebio_dibona.jpg and /dev/null differ
diff --git a/docs/html/images/judgebio_gadi.jpg b/docs/html/images/judgebio_gadi.jpg
deleted file mode 100644
index d1e40c3734b3b..0000000000000
Binary files a/docs/html/images/judgebio_gadi.jpg and /dev/null differ
diff --git a/docs/html/images/judgebio_jens.jpg b/docs/html/images/judgebio_jens.jpg
deleted file mode 100644
index 6f07254aa5362..0000000000000
Binary files a/docs/html/images/judgebio_jens.jpg and /dev/null differ
diff --git a/docs/html/images/judgebio_jeremiah.jpg b/docs/html/images/judgebio_jeremiah.jpg
deleted file mode 100644
index c91b43f772c76..0000000000000
Binary files a/docs/html/images/judgebio_jeremiah.jpg and /dev/null differ
diff --git a/docs/html/images/judgebio_kristian.jpg b/docs/html/images/judgebio_kristian.jpg
deleted file mode 100644
index 19e93dd38fb04..0000000000000
Binary files a/docs/html/images/judgebio_kristian.jpg and /dev/null differ
diff --git a/docs/html/images/judgebio_leon.jpg b/docs/html/images/judgebio_leon.jpg
deleted file mode 100644
index c648bd36e493c..0000000000000
Binary files a/docs/html/images/judgebio_leon.jpg and /dev/null differ
diff --git a/docs/html/index.jd b/docs/html/index.jd
index 8db339d2e69f2..bd681e2c6d977 100644
--- a/docs/html/index.jd
+++ b/docs/html/index.jd
@@ -1,5 +1,4 @@
home=true
-page.title=Home
@jd:body
diff --git a/docs/html/license.jd b/docs/html/license.jd
index 39fb3a0930a82..88932b60b5fc4 100644
--- a/docs/html/license.jd
+++ b/docs/html/license.jd
@@ -1,4 +1,5 @@
-page.title=Content License
+page.title=Content License
+hide_license_footer=true
@jd:body
@@ -30,8 +31,8 @@ is licensed under GPLv2 or other license. In those cases, the license
covering the source code module will apply to the documentation
extracted from it.
-
If you're upgrading from a previously installed version, then refer to the
Upgrading guide.
-
Once you've completed the SDK installation, you can start learning about development on the Android framework
-by reading the Dev Guide. And don't forget that the SDK comes packaged with
-a wide variety of very helpful code samples.
+
Once you've completed the SDK installation, you can start learning about
+development on the Android framework by reading the Developer's Guide. The SDK package
+also includes a wide variety of very helpful code samples.
-
Please note that you are currently viewing a local, offline version of the Android developer documentation.
-The offline documentation will behave just like the online documentation, except searches in the above
-search bar will not work. However, the search bar is still able to provide auto-completion for package and class names,
-which can help you quickly find reference documentation for specific classes that you remember.
-If you'd like fully searchable documentation, please visit
-http://developer.android.com.
+
Please note that you are currently viewing a local, offline version of the
+Android developer documentation. The offline documentation offers the same
+content and features as the online documentation, but since the search
+capability is network-based, it will not work while you are offline.
+Autocompletion for API packages and classes, also offered from the search box,
+is available both online and offline and loads the reference documentation for
+the item you select.
-
\ No newline at end of file
+
For the most current, fully searchable documentation, please visit
-On 12 November, 2007, we made available the first early look at the Android
-SDK to give developers an opportunity to explore Android and build
-applications for the Android Developer Challenge. That was followed by the
-"M5" early look build.
-
-Since then, we've been hard at work with our partners preparing the first
-device for launch and finalizing the APIs and platform. The developer
-feedback we received via the "early look" SDKs has been extremely valuable in
-that process. This Roadmap outlines our plans for
-the coming months, and lets you know what to expect as we near device
-availability.
-
-This is the top-level Roadmap. Individual components of Android (such as
-the Dalvik virtual machine, the Android Developer Tools, and so on) will have
-their own roadmaps, once we complete the source code release. Those roadmaps
-will be linked to this page, as they become available.
-
-
Timeline
-
-To orient yourself, consult this brief timeline. Read on for details on these
-milestones.
-
-
12 November, 2007 - "Early Look" SDK released
-
January to August, 2008 - Android Developer Challenge I
-
18 August, 2008 - Android 0.9 SDK beta released
-
28 August, 2008 - Android Market introduced
-
23 September, 2008 - Android 1.0 SDK Release 1 available (first actual
-1.0-compatible SDK)
-
22 October, 2008 - Android 1.0 devices available at retail
-
Q4 2008 - Source code released
-
Q4 2008 - Key Announcement on Android Developer Challenge II
-
-
SDK Naming and Compatibility
-
-Before we dive into details, here is a quick note on how we name SDKs.
-
-We've adopted the following naming convention for Android SDKs:
- "Android <Platform> SDK, release <Release>"
-
-The downloadable file names for the SDKs will have this naming convention:
- "android-sdk-<Host-OS>-<Platform>_r<Release>.zip"
-
-The "<Platform>" refers to the version of the Android platform with which the
-SDK is compatible. For instance, an SDK that can be used to build
-applications that will run on Android 1.0 is considered to be an "Android 1.0
-SDK". However, since we do expect to release bug fixes and enhancements for
-the various tools included in the SDK (such as the emulator, Eclipse plugin,
-DDMS, and so on) we need to distinguish between releases of the SDK that can
-be used to build for the same Android platform. That's what we will use the
-"<Release>" for.
-
-For example, the first SDK that is compatible with Android 1.0 is named
-"Android 1.0 SDK, release 1", and will have file names such as
-"android-sdk-windows-1.0_r1.zip". In the future, after we release a
-hypothetical Android 2.0 platform version, you might see an SDK named "Android
-2.0 SDK, release 3", which would refer to the third released SDK compatible
-with Android 2.0.
-
-
Details of Key Events
-
Ongoing SDK Releases
-
-The SDK consists of two general pieces: a version of the Android platform
-itself (that runs in the emulator), and the accompanying developer tools that
-surround it. This means that when we ship SDK releases, all releases within a
-given series (such as all the SDKs for Android 1.0) will consist of
-essentially the same platform image, but with different, updated tools.
-
-In August, we released Android 0.9 SDK, beta. The Android
-platform image was not quite 1.0-final (which is why we identified it as 0.9),
-and the tools were not yet final (which is why we referred to it as
-beta.)
-
-
For the SDK that includes the Android 1.0 platform and updated tools,
-we've dropped the beta labeling and released "Android 1.0 SDK, release
-1". Applications developed on this SDK version will be compatible with
-devices that run the Android 1.0 platform.
-
-
Device Availability
-
The first Android-powered device, the T-Mobile G1, was announced on 23 September,
-2008. To learn more about the T-Mobile G1, see the T-Mobile G1 site.
-
-
Other partners will be releasing Android-powered devices in the future.
-We will update this space with more specific information about each device
-release, as it becomes
-available.
-
-
Source Code Release
-
-We are currently in the process of preparing for the release of the source
-code. This includes a few key tasks:
-
-
Selection of hosting infrastructure
-
Updating the build infrastructure for general use
-
Creation of a project governance framework
-
Final examination of source code for release approval
-
Physical upload and release packaging of the source code
-
-This work is already under way, but since Android contains some 8 million
-lines of code, it's a lengthy process. We expect this process to conclude
-(and source code to be released) in Q4 of 2008.
-
-
Android Developer Challenge II
-
-When Android was announced on 5 November, 2007, Google also announced a $10
-million Android Developer Challenge, split into two separate $5 million
-events. The first Android Developer Challenge ran from January 2008 through
-August 2008, and was intended to give developers an opportunity to explore
-their ideas using the early look SDK and build prototype applications -- to
-"get in on the ground floor." The second Challenge will give developers a
-chance to build polished applications once hardware is available.
-
-We'll be making some interesting announcements regarding ADC II soon, in Q3 or
-Q4.
-
This page describes how to install the Android 1.1 SDK, Release 1, and set up your development environment.
-If you haven't downloaded the SDK yet, you can so so from the Download page.
+If you haven't downloaded the SDK yet, you can so from the Download page.
Before you begin, be sure that your development environment meets the SDK
-System Requirements.
If you have already developed applications using an earlier version of the
@@ -20,7 +21,7 @@ SDK, please skip this page and read the
Installing the SDK
-
After downloading the SDK, unpack the .zip archive to a suitable location on your machine. By default, the SDK files are unpacked into a directory named android_sdk_<platform>_<release>_<build>. The directory contains the subdirectories tools/, samples/, and others.
+
After downloading the SDK, unpack the .zip archive to a suitable location on your machine. By default, the SDK files are unpacked into a directory named android_sdk_<platform>_<release>_<build>. The directory contains a link to a local copy of the documentation and the subdirectories tools/, samples/, and others.
Make a note of the name and location of the unpacked SDK directory on your system — you will need to refer to the SDK directory later, when setting up the Android plugin or using SDK tools.
@@ -44,25 +45,16 @@ SDK, please skip this page and read the
Adding tools to your path lets you run Android Debug Bridge (adb) and the other command line tools without needing to supply the full path to the tools directory. Note that, if you update your SDK, you should remember to update your PATH settings to point to the new location, if different.
+
+
If you will be using the Eclipse IDE as your environment for developing Android applications, continue reading the next
+section in order to install the Android Development Tools plugin and setup Eclipse. If you choose not to use Eclipse, you can
+develop Android applications using other tools — read the guide to developing
+In other IDEs.
+
+
Setting up Eclipse
-
If you'll be developing with the Eclipse IDE, follow the following procedure to setup the IDE
-to use the Android SDK.
-
Basically, you just need to update your Eclipse preferences to point to the Android SDK directory:
-
-
Select Window > Preferences... to open the Preferences
- panel. (Mac OS X: Eclipse > Preferences)
-
Select Android from the left panel.
-
For the SDK Location in the main panel, click Browse... and locate the SDK directory.
-
Click Apply, then OK.
-
-
Done! We now recommend that you install the ADT Eclipse plugin, which will provide some much-appreciated assistance in developing Android apps with Eclipse...
-
-
Installing the Eclipse Plugin (ADT)
-
-
If you will be using the Eclipse IDE as your environment for developing Android applications, you can install a custom plugin called Android Development Tools (ADT), which adds integrated support for Android projects and tools. The ADT plugin includes a variety of powerful extensions that make creating, running, and debugging Android applications faster and easier. Developing in ADT/Eclipse is highly recommended for Eclipse users and those new to Android.
-
-
If you will not be using the Eclipse IDE, you do not need to download or install the ADT plugin. You can still develop Android applications using other tools.
+
First, you should install a custom plugin called Android Development Tools (ADT), which adds integrated support for Android projects and tools. The ADT plugin includes a variety of powerful extensions that make creating, running, and debugging Android applications faster and easier. Developing in ADT/Eclipse is highly recommended for Eclipse users and those new to Android.
To download and install the ADT plugin, follow the steps below for your respective Eclipse version.
@@ -131,6 +123,21 @@ to use the Android SDK.
+
+
Now, you just need to modify your Eclipse preferences to point to the Android SDK directory:
+
+
Select Window > Preferences... to open the Preferences
+ panel. (Mac OS X: Eclipse > Preferences)
+
Select Android from the left panel.
+
For the SDK Location in the main panel, click Browse... and locate the SDK directory.
+
Click Apply, then OK.
+
+
+
Done! If you haven't encountered any problems, then you're ready to begin developing Android applications.
+We recommend you begin with the Hello World tutorial,
+which will teach you some basics about Android applications and how to create projects using Eclipse.
+
+
Troubleshooting ADT Installation
If you are having trouble downloading the ADT plugin after following the steps above, here are some suggestions:
This document describes how to move your devlopment environment and existing
+
This document describes how to move your development environment and existing
Android applications from an Android 1.0 SDK to the Android 1.1, Release 1 SDK.
If you are migrating applications from an earlier SDK, please read the upgrading
document available in the Android 1.0 SDK package.
@@ -38,18 +38,18 @@ document available in the Android 1.0 SDK package.
To ensure that your applications are compliant with the Android 1.1 system available
on mobile devices, you need to install the Android 1.1 SDK and port your existing Android
-applications to it. The sections below guide you through the process.
+applications to it. The sections below will guide you through the process.
After unpacking the new SDK and saving it an appropriate location, you should:
Wipe your emulator data.
Some data formats have changed since the last
SDK release, so any previously saved data in your emulator must be removed. Open a console/terminal
- and navigate to the /tools directory of your SDK. Launch the
+ and navigate to the /tools directory of your new SDK. Launch the
emulator with the -wipe-data option.
If you are migrating from an earlier version of the SDK, you will
need to update the ADT plugin.
You may also want to upgrade your
@@ -111,7 +111,9 @@ version available.
-
After restart, update your Eclipse preferences to point to the SDK directory:
+
Update your Eclipse SDK Preferences
+
+
The last step is to update your Eclipse preferences to point to the new SDK directory:
Select Window > Preferences... to open the Preferences panel. (Mac OSX: Eclipse > Preferences)
Select Android from the left panel.
@@ -119,43 +121,6 @@ version available.
Click Apply, then OK.
-
-
-
Migrate Your Applications, if Necessary
If (and only if) you have written apps in an SDK released previous to
diff --git a/docs/html/sdk/RELEASENOTES.jd b/docs/html/sdk/RELEASENOTES.jd
index 6e0716c18bb99..bad71a2a59da3 100644
--- a/docs/html/sdk/RELEASENOTES.jd
+++ b/docs/html/sdk/RELEASENOTES.jd
@@ -1,10 +1,9 @@
page.title=SDK Release Notes
-sdk.version=1.1_r1
@jd:body
This document provides version-specific information about Android SDK releases. For the latest known issues, please ensure that you're viewing this page at: http://developer.android.com/sdk/RELEASENOTES.html.
-
Android 1.1 SDK, Release 1
+
Android 1.1 SDK, Release 1
This SDK provides the development tools and Android system image you need to create applications for Android-powered devices. Applications developed on this SDK will be compatible with mobile devices running the Android 1.1 platform.
By setting android:minSdkVersion in this way, you ensure that users will only be able to install your application if their devices are running the Android 1.1 platform. In turn, this ensures that your application will function properly on their devices, especially if it uses APIs introduced in Android 1.1.
-
If your application uses APIs introduced in Android 1.1 but does not declare <uses-sdk minSdkVersion="2">, then it will run properly on Android 1.1 devices but not on Android 1.0 devices.
+
If your application uses APIs introduced in Android 1.1 but does not declare <uses-sdk minSdkVersion="2" />, then it will run properly on Android 1.1 devices but not on Android 1.0 devices.
If your application does not use any new APIs introduced in Android 1.1, you can indicate Android 1.0 compatibility by removing minSdkVersion or setting the attribute to "1". However, before publishing your application, you must make sure to compile your application against the Android 1.0 system image (available in the Android 1.0 SDK), to ensure that it builds and functions properly for Android 1.0 devices. You should test the application against system images corresponding to the API Levels that the application is designed to be compatible with.
@@ -115,7 +114,196 @@ in Eclipse.
It is not possible to send MMS messages between emulator instances.
In some cases, you may encounter problems when using the browser on an
emulator started with the command-line option -http-proxy.
-
We regret to inform developers that Android 1.1 will not include support for
+
On the OSX platform, if you manually remove the ~/.android directory
+using rm -rf ~/.android, then try to run
+the emulator, it crashes. This happens because the emulator fails to create
+a new .android directory before attempting to create the child SDK1.0 directory.
+To work around this issue, manually create a new .android directory using
+mkdir ~/.android, then run the emulator. The emulator
+creates the SDK1.0 directory and starts normally.
+
We regret to inform developers that Android 1.1 will not include support
+for ARCNet network interfaces.
+
The final set of Intent patterns honored by Android 1.0 has not yet been
+fully documented. Documentation will be provided in future releases.
+
In ADT Editor, you can add at most ten new resource values at a time,
+in a given res/values/*.xml, using the form in the Android Resources pane.
+If you add more than ten, the Android Resources pane will not display the
+attributes fields for the additional resource entries. To work around this
+problem, you can close the file in the editor and open it again, or you
+can edit the resource entries in the XML text mode.
+
The emulator's battery-control commands (power <option>)
+are not working in this release.
+
+
+
+
+
+
+
Android 1.0 SDK, Release 2
+
+
This SDK release includes the Android 1.0 platform and application API.
+Applications developed on this SDK will be compatible with mobile devices
+running the Android 1.0 platform.
+
+
This release includes mainly bug fixes, although some smaller features were
+added.
+
+
ADT Plugin Compatibility
+
+
For this release of the SDK, the compatible version of the Android
+Development Tools (ADT) Plugin for Eclipse is 0.8.0. If you are
+using a previous version of ADT, you should update to the latest version for use
+with this SDK. For information about how to update your ADT plugin, see Upgrading the SDK.
+
+
Installation and Upgrade Notes
+
+
If you're installing the Android SDK for the first time, please see the
+instructions in Installing the
+SDK.
+
+
Other Notes
+
+
T-Mobile G1 Compatability
+
+
This version of the SDK has been tested for compatability with the first
+Android-powered mobile device, the T-Mobile
+G1.
+
+
MapView API Key
+
+
MapView is a class that lets you easily integrate Google Maps into your
+application. Before you can access the maps data, you will need to register with
+the Google Maps service and receive a Maps API Key, which you then add to your
+MapView for authentication to the server.
+
+
Developers should note that the registration service for MapView is now
+active and Google Maps is actively enforcing the Maps API Key requirement. For
+information about how to register for a Maps API Key, see http://code.
+google.com/android/toolbox/apis/mapkey.html.
+
+
USB Driver for Windows
+
If you using Windows and want to develop or test your application on an
+Android-powered device (such as the T-Mobile G1), you need an appropriate USB
+driver. For your convenience, the Windows version of the Android SDK includes a
+USB driver that you can install, to let you develop on the device. The USB
+driver files are located in the <SDK>/usb_driver directory.
+
+
+
+
Resolved Issues, Changes
+
+
The android.jar in this SDK release now includes several classes that were
+missing from the previous SDK.
+
The android.R.styleable class and its fields were removed from the public
+API, to better ensure forward-compatibility for applications. The constants
+declared in android.R.styleable were platform-specific and subject to arbitrary
+change across versions, so were not suitable for use by applications. You can
+still access the platform's styleable attributes from your resources or code. To
+do so, declare a custom resource element using a
+<declare-styleable> in your project's res/values/R.attrs
+file, then declare the attribute inside. For examples, see
+<sdk>/samples/ApiDemos/res/values/attrs.xml. For more information about
+custom resources, see Custom
+Layout Resources. Note that the android.R.styleable documentation is still
+provided in the SDK, but only as a reference of the platform's styleable
+attributes for the various elements.
+
The VM now properly ensures that private classes are not
+available to applications through reflection. If you were using reflection
+to access private classes in a previous release, you will now get a run-time
+error.
+
+
The Settings and Email applications are now included in the SDK and
+available in the emulator.
+
We regret to inform developers that SDK 1.0_r2 does not support MFM, RLL,
+or Winchester hard disk drives.
+
In the emulator, the control key for enabling/disabling trackball mode
+is changed from Control-T to F6. You can also enter trackball mode temporarily
+using the Delete key. While the key is pressed, you can send trackball events.
+
+
+
Unless otherwise noted, Known Issues from the previous SDK release also apply
+to this release.
+
+
+
+
+
+
+
Android 1.0 SDK, Release 1
+
+
This SDK release is the first to include the Android 1.0 platform and application API. Applications developed on this SDK will be compatible with mobile devices running the Android 1.0 platform, when such devices are available.
+
+
This release includes mainly bug fixes, although some smaller features were added. The Android 1.0 also includes several API changes from the 0.9 version. For more information on API changes, see the Overview of Changes and the API Differences Report. For those porting from the M5 release, the SDK also includes the legacy changes overview and API Differences Reports. See the current Overview of Changes for more information.
+
+
ADT Plugin Compatibility
+
+
For this version of the SDK — Android 1.0 SDK, Release 1 — the compatible version of the Android Development Tools (ADT) Plugin for Eclipse is 0.8.0. If you are using a previous version of ADT, you should update to the latest version for use with this SDK. For information about how to update your ADT plugin, see Upgrading the SDK.
+
+
Installation and Upgrade Notes
+
+
If you've been developing an application using a previous SDK version and you want the application to run on Android-powered mobile devices, you must port the application to the Android 1.0 SDK. Please see Upgrading the SDK for detailed instructions on how to make the transition to this release. Be sure to wipe application user data (emulator option -wipe-data) when running your application on the Android 1.0 SDK emulator.
+
+
If you're installing the Android SDK for the first time, please see the instructions in Installing the SDK.
+
+
Other Notes
+
+
MapView API Key
+
+
MapView is a class that lets you easily integrate Google Maps into your application. Before you can access the maps data, you will need to register with the Google Maps service and receive a Maps API Key, which you then add to your MapView for authentication to the server.
+
+
Currently, the registration service for MapView is not yet active and Google Maps is not yet enforcing the Maps API Key requirement. However, note that the registration service will be activated soon, so that MapViews in any application deployed to a mobile device will require registration and a valid Maps API Key.
+
+
As soon as the registration service becomes available, we will update the page at http://code.google.com/android/toolbox/apis/mapkey.html with details about how and where to register. Please check that page periodically for registration information, if you are using a MapView.
+
+
+
Resolved Issues, Changes
+
+
Emulator
+
+
Emulator now saves the user image in <android>/SDK1.0/
+
Fixed EsounD-related freezes on Linux.
+
Fixed the documentation in -help-audio. '-audio list' doesn't work, one
+ needs to call -help-audio-out and -help-audio-in to get the list of valid
+ audio backends.
+
Fixed scrollwheel Dpad emulation in rotated mode. before that, using the
+ scroll-wheel would always generated Dpad Up/Down events, even when in
+ landscape mode.
+
+
Several Obsolete command options were removed.
+
Setting the network speed through the console or the -netspeed option will
+ properly modify the connectivity icon on the device.
+
Setting the GSM voice registration state to 'roaming' in the console will
+ properly modify the voice icon on the device
+
+
+
SQLite
+
+
SQLite is now included in the SDK package on all platforms.
+
+
+
Known Issues
+
+
JUnit and Eclipse/ADT
+
+
If you are developing in Eclipse/ADT and want to add JUnit test
+classes, you can do so. However, you need to set up a custom JUnit configuration
+before your tests will run properly. For detailed information about how to set
+up the JUnit configuration, see the troubleshooting topic Running a Junit test class
+in Eclipse.
+
+
+
Other
+
+
+
It is not possible to send MMS messages between emulator instances.
+
In some cases, you may encounter problems when using the browser on an
+emulator started with the command-line option -http-proxy.
+
+
We regret to inform developers that Android 1.0 will not include support for
dot-matrix printers.
On the OSX platform, if you manually remove the ~/.android directory
using rm -rf ~/.android, then try to run
@@ -134,5 +322,6 @@ problem, you can close the file in the editor and open it again, or you
can edit the resource entries in the XML text mode.
The emulator's battery-control commands (power <option>)
are not working in this release.
+
diff --git a/docs/html/sdk/android-1.1.jd b/docs/html/sdk/android-1.1.jd
index 8e63ba3df8860..f70ad262a5145 100644
--- a/docs/html/sdk/android-1.1.jd
+++ b/docs/html/sdk/android-1.1.jd
@@ -59,7 +59,7 @@ attribute looks like this:
@@ -71,7 +71,7 @@ your application will function properly on their devices, especially if
it uses APIs introduced in Android 1.1.
If your application uses APIs introduced in Android 1.1 but does not
-declare <uses-sdk minSdkVersion="2">, then it will
+declare <uses-sdk minSdkVersion="2" />, then it will
run properly on Android 1.1 devices but not on Android 1.0
devices. In the latter case, the application will crash at runtime when
it tries to use the Android 1.1 APIs.
@@ -175,14 +175,13 @@ AM/PM).
Improves recovery from POP3 connection failures.
POP3 parser rules loosened, so the application can work with
non-compliant email servers.
-
Removes green CALL button as a shortcut for "add a new call".
New Features
Maps: Adds details and reviews when a user does a search on Maps and
-clicks on a business to view it's details.
+clicks on a business to view its details.
Dialer: In-call screen timeout default is now longer when using the
speakerphone.
Dialer: Adds a "Show dialpad" / "Hide dialpad" item to the in-call
@@ -216,9 +215,9 @@ SDK-bound system images.
Module or Feature
Change Description
Annotations for test systems
-
Added class {@link android.test.suitebuilder.annotation.LargeTest LargeTest} to package {@link android.test.suitebuilder.annotation}
-
Added class {@link android.test.suitebuilder.annotation.MediumTest MediumTest} to package {@link android.test.suitebuilder.annotation}
-
Added class {@link android.test.suitebuilder.annotation.SmallTest SmallTest} to package {@link android.test.suitebuilder.annotation}
Please carefully review the Android SDK License Agreement before downloading the SDK.
-The License Agreement constitutes a contract between you and Google with respect to your use of the SDK.
-
-
-
+
+
Please carefully review the Android SDK License Agreement before downloading the SDK.
+The License Agreement constitutes a contract between you and Google with respect to your use of the SDK.
If you are upgrading from a previously installed version of the Android SDK, see
+ Upgrading the SDK.
+
If you are installing for the first time, read
+ Installing the Android SDK to get your environment set up.
+ Once you have completed your installation, visit the Dev Guide tab and begin with the
+ Hello World tutorial to create your first
+ Android application. From there, learn more about Android with the
+ Application Fundamentals documentation.
+
If you want to re-read the license agreement, it's available to you in the SDK tab.