summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/java/android/animation/AnimatorSet.java14
-rw-r--r--core/java/android/app/Activity.java2
-rw-r--r--core/java/android/app/ActivityManagerNative.java20
-rw-r--r--core/java/android/app/Fragment.java2
-rw-r--r--core/java/android/app/IActivityManager.java4
-rw-r--r--core/java/android/app/Notification.java29
-rw-r--r--core/java/android/app/Service.java4
-rw-r--r--core/java/android/content/ContentProvider.java2
-rw-r--r--core/java/android/content/SyncManager.java59
-rw-r--r--core/java/android/content/SyncStorageEngine.java20
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl4
-rw-r--r--core/java/android/content/pm/PackageManager.java5
-rwxr-xr-xcore/java/android/content/res/Resources.java51
-rw-r--r--core/java/android/hardware/Camera.java12
-rw-r--r--core/java/android/hardware/input/IInputDevicesChangedListener.aidl29
-rw-r--r--core/java/android/hardware/input/IInputManager.aidl4
-rwxr-xr-xcore/java/android/hardware/input/InputManager.java306
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java4
-rw-r--r--core/java/android/net/nsd/DnsSdServiceInfo.java47
-rw-r--r--core/java/android/net/nsd/DnsSdTxtRecord.java22
-rw-r--r--core/java/android/net/nsd/NsdManager.java50
-rw-r--r--core/java/android/provider/BrowserContract.java191
-rw-r--r--core/java/android/provider/ContactsContract.java20
-rw-r--r--core/java/android/provider/Downloads.java31
-rw-r--r--core/java/android/text/SpannableStringBuilder.java220
-rw-r--r--core/java/android/view/HardwareRenderer.java53
-rwxr-xr-xcore/java/android/view/InputDevice.java20
-rw-r--r--core/java/android/view/KeyCharacterMap.java2
-rw-r--r--core/java/android/view/TextureView.java17
-rw-r--r--core/java/android/view/View.java17
-rw-r--r--core/java/android/view/ViewRootImpl.java31
-rw-r--r--core/java/android/view/WindowManagerPolicy.java2
-rw-r--r--core/java/android/webkit/CallbackProxy.java100
-rw-r--r--core/java/android/webkit/DeviceMotionAndOrientationManager.java11
-rwxr-xr-xcore/java/android/webkit/DeviceMotionService.java2
-rwxr-xr-xcore/java/android/webkit/DeviceOrientationService.java2
-rwxr-xr-xcore/java/android/webkit/GeolocationPermissions.java10
-rw-r--r--core/java/android/webkit/JsPromptResult.java28
-rw-r--r--core/java/android/webkit/JsResult.java64
-rw-r--r--core/java/android/webkit/WebChromeClient.java4
-rw-r--r--core/java/android/webkit/WebStorage.java10
-rw-r--r--core/java/android/webkit/WebView.java3
-rw-r--r--core/java/android/webkit/WebViewClassic.java149
-rw-r--r--core/java/android/webkit/WebViewCore.java36
-rw-r--r--core/java/android/webkit/WebViewInputDispatcher.java11
-rw-r--r--core/java/android/widget/CheckBox.java12
-rw-r--r--core/java/android/widget/NumberPicker.java11
-rw-r--r--core/java/android/widget/ShareActionProvider.java14
-rw-r--r--core/java/android/widget/Spinner.java2
-rw-r--r--core/java/android/widget/Switch.java11
-rw-r--r--core/java/com/android/internal/util/IndentingPrintWriter.java4
-rw-r--r--core/java/com/android/internal/widget/PointerLocationView.java68
-rw-r--r--core/jni/AndroidRuntime.cpp4
-rw-r--r--core/jni/android/graphics/Paint.cpp8
-rw-r--r--core/jni/android/graphics/TextLayoutCache.cpp5
-rw-r--r--core/jni/android_net_wifi_Wifi.cpp3
-rw-r--r--core/jni/android_view_InputDevice.cpp7
-rw-r--r--core/res/res/anim/lock_screen_behind_enter.xml4
-rw-r--r--core/res/res/anim/lock_screen_wallpaper_behind_enter.xml36
-rw-r--r--core/res/res/anim/screen_rotate_180_enter.xml2
-rw-r--r--core/res/res/anim/screen_rotate_180_exit.xml5
-rw-r--r--core/res/res/anim/screen_rotate_180_frame.xml2
-rw-r--r--core/res/res/anim/screen_rotate_minus_90_enter.xml8
-rw-r--r--core/res/res/anim/screen_rotate_minus_90_exit.xml20
-rw-r--r--core/res/res/anim/screen_rotate_plus_90_enter.xml8
-rw-r--r--core/res/res/anim/screen_rotate_plus_90_exit.xml20
-rw-r--r--core/res/res/values/public.xml20
-rwxr-xr-xcore/res/res/values/strings.xml54
-rw-r--r--core/res/res/xml/sms_short_codes.xml189
69 files changed, 1738 insertions, 503 deletions
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index c5a4171..f9fa444 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -420,11 +420,7 @@ public final class AnimatorSet extends Animator {
if (duration < 0) {
throw new IllegalArgumentException("duration must be a value of zero or greater");
}
- for (Node node : mNodes) {
- // TODO: don't set the duration of the timing-only nodes created by AnimatorSet to
- // insert "play-after" delays
- node.animation.setDuration(duration);
- }
+ // Just record the value for now - it will be used later when the AnimatorSet starts
mDuration = duration;
return this;
}
@@ -456,6 +452,14 @@ public final class AnimatorSet extends Animator {
mTerminated = false;
mStarted = true;
+ if (mDuration >= 0) {
+ // If the duration was set on this AnimatorSet, pass it along to all child animations
+ for (Node node : mNodes) {
+ // TODO: don't set the duration of the timing-only nodes created by AnimatorSet to
+ // insert "play-after" delays
+ node.animation.setDuration(mDuration);
+ }
+ }
// First, sort the nodes (if necessary). This will ensure that sortedNodes
// contains the animation nodes in the correct order.
sortNodes();
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 227900e..1c820dc 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -4656,7 +4656,7 @@ public class Activity extends ContextThemeWrapper
/**
* Print the Activity's state into the given stream. This gets invoked if
- * you run "adb shell dumpsys activity <activity_component_name>".
+ * you run "adb shell dumpsys activity &lt;activity_component_name&gt;".
*
* @param prefix Desired prefix to prepend at each line of output.
* @param fd The raw file descriptor that the dump is being sent to.
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index a3fdf3e..7e1589f 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1000,7 +1000,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
}
return true;
}
-
+
case GOING_TO_SLEEP_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
goingToSleep();
@@ -1015,6 +1015,13 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true;
}
+ case SET_LOCK_SCREEN_SHOWN_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ setLockScreenShown(data.readInt() != 0);
+ reply.writeNoException();
+ return true;
+ }
+
case SET_DEBUG_APP_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
String pn = data.readString();
@@ -2912,6 +2919,17 @@ class ActivityManagerProxy implements IActivityManager
data.recycle();
reply.recycle();
}
+ public void setLockScreenShown(boolean shown) throws RemoteException
+ {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeInt(shown ? 1 : 0);
+ mRemote.transact(SET_LOCK_SCREEN_SHOWN_TRANSACTION, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
public void setDebugApp(
String packageName, boolean waitForDebugger, boolean persistent)
throws RemoteException
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index c493f0f..d3ba497 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -203,7 +203,7 @@ final class FragmentState implements Parcelable {
* <li> {@link #onCreateView} creates and returns the view hierarchy associated
* with the fragment.
* <li> {@link #onActivityCreated} tells the fragment that its activity has
- * completed its own {@link Activity#onCreate Activity.onCreaate}.
+ * completed its own {@link Activity#onCreate Activity.onCreate()}.
* <li> {@link #onStart} makes the fragment visible to the user (based on its
* containing activity being started).
* <li> {@link #onResume} makes the fragment interacting with the user (based on its
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index c71b186..3fc2280 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -205,7 +205,8 @@ public interface IActivityManager extends IInterface {
// Note: probably don't want to allow applications access to these.
public void goingToSleep() throws RemoteException;
public void wakingUp() throws RemoteException;
-
+ public void setLockScreenShown(boolean shown) throws RemoteException;
+
public void unhandledBack() throws RemoteException;
public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException;
public void setDebugApp(
@@ -588,4 +589,5 @@ public interface IActivityManager extends IInterface {
int GET_CURRENT_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+144;
int TARGET_TASK_AFFINITY_MATCHES_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+145;
int NAVIGATE_UP_TO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+146;
+ int SET_LOCK_SCREEN_SHOWN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+147;
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 04c64a0..5cce25f 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -196,10 +196,9 @@ public class Notification implements Parcelable
public RemoteViews intruderView;
/**
- * A larger version of {@link #contentView}, giving the Notification an
+ * A large-format version of {@link #contentView}, giving the Notification an
* opportunity to show more detail. The system UI may choose to show this
* instead of the normal content view at its discretion.
- * @hide
*/
public RemoteViews bigContentView;
@@ -987,8 +986,6 @@ public class Notification implements Parcelable
}
/**
- * @hide
- *
* Show the {@link Notification#when} field as a countdown (or count-up) timer instead of a timestamp.
*
* @see Notification#when
@@ -1609,23 +1606,21 @@ public class Notification implements Parcelable
}
/**
- * @hide because this API is still very rough
+ * Helper class for generating large-format notifications that include a large image attachment.
*
- * This is a "rebuilder": It consumes a Builder object and modifies its output.
- *
- * This represents the "big picture" style notification, with a large Bitmap atop the usual notification.
- *
- * Usage:
+ * This class is a "rebuilder": It consumes a Builder object and modifies its behavior, like so:
* <pre class="prettyprint">
* Notification noti = new Notification.BigPictureStyle(
* new Notification.Builder()
- * .setContentTitle(&quot;New mail from &quot; + sender.toString())
+ * .setContentTitle(&quot;New photo from &quot; + sender.toString())
* .setContentText(subject)
- * .setSmallIcon(R.drawable.new_mail)
+ * .setSmallIcon(R.drawable.new_post)
* .setLargeIcon(aBitmap))
* .bigPicture(aBigBitmap)
* .build();
* </pre>
+ *
+ * @see Notification#bigContentView
*/
public static class BigPictureStyle {
private Builder mBuilder;
@@ -1656,13 +1651,9 @@ public class Notification implements Parcelable
}
/**
- * @hide because this API is still very rough
- *
- * This is a "rebuilder": It consumes a Builder object and modifies its output.
+ * Helper class for generating large-format notifications that include a lot of text.
*
- * This represents the "big text" style notification, with more area for the main content text to be read in its entirety.
- *
- * Usage:
+ * This class is a "rebuilder": It consumes a Builder object and modifies its behavior, like so:
* <pre class="prettyprint">
* Notification noti = new Notification.BigPictureStyle(
* new Notification.Builder()
@@ -1673,6 +1664,8 @@ public class Notification implements Parcelable
* .bigText(aVeryLongString)
* .build();
* </pre>
+ *
+ * @see Notification#bigContentView
*/
public static class BigTextStyle {
private Builder mBuilder;
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index 207ae76..cb43d4c 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -666,8 +666,8 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac
/**
* Print the Service's state into the given stream. This gets invoked if
- * you run "adb shell dumpsys activity service <yourservicename>".
- * This is distinct from "dumpsys <servicename>", which only works for
+ * you run "adb shell dumpsys activity service &lt;yourservicename&gt;".
+ * This is distinct from "dumpsys &lt;servicename&gt;", which only works for
* named system services and which invokes the {@link IBinder#dump} method
* on the {@link IBinder} interface registered with ServiceManager.
*
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 05ef194..1206056 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -1127,7 +1127,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
/**
* Print the Provider's state into the given stream. This gets invoked if
- * you run "adb shell dumpsys activity provider <provider_component_name>".
+ * you run "adb shell dumpsys activity provider &lt;provider_component_name&gt;".
*
* @param prefix Desired prefix to prepend at each line of output.
* @param fd The raw file descriptor that the dump is being sent to.
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 6219de7..34c40a0 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -205,6 +205,9 @@ public class SyncManager implements OnAccountsUpdateListener {
private final PowerManager mPowerManager;
+ // Use this as a random offset to seed all periodic syncs
+ private int mSyncRandomOffsetMillis;
+
private static final long SYNC_ALARM_TIMEOUT_MIN = 30 * 1000; // 30 seconds
private static final long SYNC_ALARM_TIMEOUT_MAX = 2 * 60 * 60 * 1000; // two hours
@@ -438,6 +441,9 @@ public class SyncManager implements OnAccountsUpdateListener {
// do this synchronously to ensure we have the accounts before this call returns
onAccountsUpdated(null);
}
+
+ // Pick a random second in a day to seed all periodic syncs
+ mSyncRandomOffsetMillis = mSyncStorageEngine.getSyncRandomOffset() * 1000;
}
/**
@@ -666,6 +672,7 @@ public class SyncManager implements OnAccountsUpdateListener {
private void sendCheckAlarmsMessage() {
if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "sending MESSAGE_CHECK_ALARMS");
+ mSyncHandler.removeMessages(SyncHandler.MESSAGE_CHECK_ALARMS);
mSyncHandler.sendEmptyMessage(SyncHandler.MESSAGE_CHECK_ALARMS);
}
@@ -714,6 +721,8 @@ public class SyncManager implements OnAccountsUpdateListener {
}
private void increaseBackoffSetting(SyncOperation op) {
+ // TODO: Use this function to align it to an already scheduled sync
+ // operation in the specified window
final long now = SystemClock.elapsedRealtime();
final Pair<Long, Long> previousSettings =
@@ -1060,6 +1069,8 @@ public class SyncManager implements OnAccountsUpdateListener {
final long now = SystemClock.elapsedRealtime();
pw.print("now: "); pw.print(now);
pw.println(" (" + formatTime(System.currentTimeMillis()) + ")");
+ pw.print("offset: "); pw.print(DateUtils.formatElapsedTime(mSyncRandomOffsetMillis/1000));
+ pw.println(" (HH:MM:SS)");
pw.print("uptime: "); pw.print(DateUtils.formatElapsedTime(now/1000));
pw.println(" (HH:MM:SS)");
pw.print("time spent syncing: ");
@@ -1771,6 +1782,9 @@ public class SyncManager implements OnAccountsUpdateListener {
AccountAndUser[] accounts = mAccounts;
final long nowAbsolute = System.currentTimeMillis();
+ final long shiftedNowAbsolute = (0 < nowAbsolute - mSyncRandomOffsetMillis)
+ ? (nowAbsolute - mSyncRandomOffsetMillis) : 0;
+
ArrayList<SyncStorageEngine.AuthorityInfo> infos = mSyncStorageEngine.getAuthorities();
for (SyncStorageEngine.AuthorityInfo info : infos) {
// skip the sync if the account of this operation no longer exists
@@ -1792,16 +1806,32 @@ public class SyncManager implements OnAccountsUpdateListener {
SyncStatusInfo status = mSyncStorageEngine.getOrCreateSyncStatus(info);
for (int i = 0, N = info.periodicSyncs.size(); i < N; i++) {
final Bundle extras = info.periodicSyncs.get(i).first;
- final Long periodInSeconds = info.periodicSyncs.get(i).second;
+ final Long periodInMillis = info.periodicSyncs.get(i).second * 1000;
// find when this periodic sync was last scheduled to run
final long lastPollTimeAbsolute = status.getPeriodicSyncTime(i);
- // compute when this periodic sync should next run - this can be in the future
- // for example if the user changed the time, synced and changed back.
- final long nextPollTimeAbsolute = lastPollTimeAbsolute > nowAbsolute
- ? nowAbsolute
- : lastPollTimeAbsolute + periodInSeconds * 1000;
- // if it is ready to run then schedule it and mark it as having been scheduled
- if (nextPollTimeAbsolute <= nowAbsolute) {
+
+ long remainingMillis
+ = periodInMillis - (shiftedNowAbsolute % periodInMillis);
+
+ /*
+ * Sync scheduling strategy:
+ * Set the next periodic sync based on a random offset (in seconds).
+ *
+ * Also sync right now if any of the following cases hold
+ * and mark it as having been scheduled
+ *
+ * Case 1: This sync is ready to run now.
+ * Case 2: If the lastPollTimeAbsolute is in the future,
+ * sync now and reinitialize. This can happen for
+ * example if the user changed the time, synced and
+ * changed back.
+ * Case 3: If we failed to sync at the last scheduled time
+ */
+ if (remainingMillis == periodInMillis // Case 1
+ || lastPollTimeAbsolute > nowAbsolute // Case 2
+ || (nowAbsolute - lastPollTimeAbsolute
+ >= periodInMillis)) { // Case 3
+ // Sync now
final Pair<Long, Long> backoff = mSyncStorageEngine.getBackoff(
info.account, info.userId, info.authority);
final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo =
@@ -1819,12 +1849,13 @@ public class SyncManager implements OnAccountsUpdateListener {
info.account, info.userId, info.authority),
syncAdapterInfo.type.allowParallelSyncs()));
status.setPeriodicSyncTime(i, nowAbsolute);
- } else {
- // it isn't ready to run, remember this time if it is earlier than
- // earliestFuturePollTime
- if (nextPollTimeAbsolute < earliestFuturePollTime) {
- earliestFuturePollTime = nextPollTimeAbsolute;
- }
+ }
+ // Compute when this periodic sync should next run
+ final long nextPollTimeAbsolute = nowAbsolute + remainingMillis;
+
+ // remember this time if it is earlier than earliestFuturePollTime
+ if (nextPollTimeAbsolute < earliestFuturePollTime) {
+ earliestFuturePollTime = nextPollTimeAbsolute;
}
}
}
diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java
index d3baf70..d821918 100644
--- a/core/java/android/content/SyncStorageEngine.java
+++ b/core/java/android/content/SyncStorageEngine.java
@@ -37,6 +37,7 @@ import android.os.Message;
import android.os.Parcel;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.util.Log;
import android.util.SparseArray;
import android.util.Xml;
@@ -49,6 +50,7 @@ import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.Random;
import java.util.TimeZone;
import java.util.List;
@@ -65,6 +67,7 @@ public class SyncStorageEngine extends Handler {
private static final String XML_ATTR_NEXT_AUTHORITY_ID = "nextAuthorityId";
private static final String XML_ATTR_LISTEN_FOR_TICKLES = "listen-for-tickles";
+ private static final String XML_ATTR_SYNC_RANDOM_OFFSET = "offsetInSeconds";
private static final String XML_ATTR_ENABLED = "enabled";
private static final String XML_ATTR_USER = "user";
private static final String XML_TAG_LISTEN_FOR_TICKLES = "listenForTickles";
@@ -277,6 +280,8 @@ public class SyncStorageEngine extends Handler {
private static volatile SyncStorageEngine sSyncStorageEngine = null;
+ private int mSyncRandomOffset;
+
/**
* This file contains the core engine state: all accounts and the
* settings for them. It must never be lost, and should be changed
@@ -375,6 +380,10 @@ public class SyncStorageEngine extends Handler {
}
}
+ public int getSyncRandomOffset() {
+ return mSyncRandomOffset;
+ }
+
public void addStatusChangeListener(int mask, ISyncStatusObserver callback) {
synchronized (mAuthorities) {
mChangeListeners.register(callback, mask);
@@ -1465,6 +1474,16 @@ public class SyncStorageEngine extends Handler {
} catch (NumberFormatException e) {
// don't care
}
+ String offsetString = parser.getAttributeValue(null, XML_ATTR_SYNC_RANDOM_OFFSET);
+ try {
+ mSyncRandomOffset = (offsetString == null) ? 0 : Integer.parseInt(offsetString);
+ } catch (NumberFormatException e) {
+ mSyncRandomOffset = 0;
+ }
+ if (mSyncRandomOffset == 0) {
+ Random random = new Random(System.currentTimeMillis());
+ mSyncRandomOffset = random.nextInt(86400);
+ }
mMasterSyncAutomatically.put(0, listen == null || Boolean.parseBoolean(listen));
eventType = parser.next();
AuthorityInfo authority = null;
@@ -1705,6 +1724,7 @@ public class SyncStorageEngine extends Handler {
out.startTag(null, "accounts");
out.attribute(null, "version", Integer.toString(ACCOUNTS_VERSION));
out.attribute(null, XML_ATTR_NEXT_AUTHORITY_ID, Integer.toString(mNextAuthorityId));
+ out.attribute(null, XML_ATTR_SYNC_RANDOM_OFFSET, Integer.toString(mSyncRandomOffset));
// Write the Sync Automatically flags for each user
final int M = mMasterSyncAutomatically.size();
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 56fd5f8..9b8454a 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -373,6 +373,6 @@ interface IPackageManager {
List<UserInfo> getUsers();
UserInfo getUser(int userId);
- void setPermissionEnforcement(String permission, int enforcement);
- int getPermissionEnforcement(String permission);
+ void setPermissionEnforced(String permission, boolean enforced);
+ boolean isPermissionEnforced(String permission);
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index b06b4a5..675f77e 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -28,6 +28,7 @@ import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.Build;
import android.os.Environment;
import android.util.AndroidException;
import android.util.DisplayMetrics;
@@ -1091,9 +1092,7 @@ public abstract class PackageManager {
= "android.content.pm.extra.VERIFICATION_INSTALL_FLAGS";
/** {@hide} */
- public static final int ENFORCEMENT_DEFAULT = 0;
- /** {@hide} */
- public static final int ENFORCEMENT_YES = 1;
+ public static final boolean DEFAULT_ENFORCE_READ_EXTERNAL_STORAGE = !"user".equals(Build.TYPE);
/**
* Retrieve overall information about an application package that is
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 2af58be..c682852 100755
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -32,7 +32,6 @@ import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Slog;
-import android.util.SparseArray;
import android.util.TypedValue;
import android.util.LongSparseArray;
@@ -86,8 +85,8 @@ public class Resources {
// single-threaded, and after that these are immutable.
private static final LongSparseArray<Drawable.ConstantState> sPreloadedDrawables
= new LongSparseArray<Drawable.ConstantState>();
- private static final SparseArray<ColorStateList> mPreloadedColorStateLists
- = new SparseArray<ColorStateList>();
+ private static final LongSparseArray<ColorStateList> sPreloadedColorStateLists
+ = new LongSparseArray<ColorStateList>();
private static final LongSparseArray<Drawable.ConstantState> sPreloadedColorDrawables
= new LongSparseArray<Drawable.ConstantState>();
private static boolean mPreloaded;
@@ -98,8 +97,8 @@ public class Resources {
// These are protected by the mTmpValue lock.
private final LongSparseArray<WeakReference<Drawable.ConstantState> > mDrawableCache
= new LongSparseArray<WeakReference<Drawable.ConstantState> >();
- private final SparseArray<WeakReference<ColorStateList> > mColorStateListCache
- = new SparseArray<WeakReference<ColorStateList> >();
+ private final LongSparseArray<WeakReference<ColorStateList> > mColorStateListCache
+ = new LongSparseArray<WeakReference<ColorStateList> >();
private final LongSparseArray<WeakReference<Drawable.ConstantState> > mColorDrawableCache
= new LongSparseArray<WeakReference<Drawable.ConstantState> >();
private boolean mPreloading;
@@ -118,22 +117,6 @@ public class Resources {
private CompatibilityInfo mCompatibilityInfo;
- private static final LongSparseArray<Object> EMPTY_ARRAY = new LongSparseArray<Object>(0) {
- @Override
- public void put(long k, Object o) {
- throw new UnsupportedOperationException();
- }
- @Override
- public void append(long k, Object o) {
- throw new UnsupportedOperationException();
- }
- };
-
- @SuppressWarnings("unchecked")
- private static <T> LongSparseArray<T> emptySparseArray() {
- return (LongSparseArray<T>) EMPTY_ARRAY;
- }
-
/** @hide */
public static int selectDefaultTheme(int curTheme, int targetSdkVersion) {
return selectSystemTheme(curTheme, targetSdkVersion,
@@ -180,9 +163,8 @@ public class Resources {
* @param config Desired device configuration to consider when
* selecting/computing resource values (optional).
*/
- public Resources(AssetManager assets, DisplayMetrics metrics,
- Configuration config) {
- this(assets, metrics, config, (CompatibilityInfo) null);
+ public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config) {
+ this(assets, metrics, config, null);
}
/**
@@ -1883,7 +1865,8 @@ public class Resources {
return dr;
}
- Drawable.ConstantState cs = isColorDrawable ? sPreloadedColorDrawables.get(key) : sPreloadedDrawables.get(key);
+ Drawable.ConstantState cs = isColorDrawable ?
+ sPreloadedColorDrawables.get(key) : sPreloadedDrawables.get(key);
if (cs != null) {
dr = cs.newDrawable(this);
} else {
@@ -2005,21 +1988,21 @@ public class Resources {
}
}
- final int key = (value.assetCookie << 24) | value.data;
+ final long key = (((long) value.assetCookie) << 32) | value.data;
ColorStateList csl;
if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT &&
value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
- csl = mPreloadedColorStateLists.get(key);
+ csl = sPreloadedColorStateLists.get(key);
if (csl != null) {
return csl;
}
csl = ColorStateList.valueOf(value.data);
if (mPreloading) {
- mPreloadedColorStateLists.put(key, csl);
+ sPreloadedColorStateLists.put(key, csl);
}
return csl;
@@ -2030,7 +2013,7 @@ public class Resources {
return csl;
}
- csl = mPreloadedColorStateLists.get(key);
+ csl = sPreloadedColorStateLists.get(key);
if (csl != null) {
return csl;
}
@@ -2063,14 +2046,13 @@ public class Resources {
if (csl != null) {
if (mPreloading) {
- mPreloadedColorStateLists.put(key, csl);
+ sPreloadedColorStateLists.put(key, csl);
} else {
synchronized (mTmpValue) {
//Log.i(TAG, "Saving cached color state list @ #" +
// Integer.toHexString(key.intValue())
// + " in " + this + ": " + csl);
- mColorStateListCache.put(
- key, new WeakReference<ColorStateList>(csl));
+ mColorStateListCache.put(key, new WeakReference<ColorStateList>(csl));
}
}
}
@@ -2078,7 +2060,7 @@ public class Resources {
return csl;
}
- private ColorStateList getCachedColorStateList(int key) {
+ private ColorStateList getCachedColorStateList(long key) {
synchronized (mTmpValue) {
WeakReference<ColorStateList> wr = mColorStateListCache.get(key);
if (wr != null) { // we have the key
@@ -2088,8 +2070,7 @@ public class Resources {
// Integer.toHexString(((Integer)key).intValue())
// + " in " + this + ": " + entry);
return entry;
- }
- else { // our entry has been purged
+ } else { // our entry has been purged
mColorStateListCache.delete(key);
}
}
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 83b6986..640b47b 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -950,11 +950,10 @@ public class Camera {
/**
* Callback interface used to notify on auto focus start and stop.
*
- * <p>This is useful for continuous autofocus -- {@link Parameters#FOCUS_MODE_CONTINUOUS_VIDEO}
- * and {@link Parameters#FOCUS_MODE_CONTINUOUS_PICTURE}. Applications can
- * show autofocus animation.</p>
- *
- * @hide
+ * <p>This is only supported in continuous autofocus modes -- {@link
+ * Parameters#FOCUS_MODE_CONTINUOUS_VIDEO} and {@link
+ * Parameters#FOCUS_MODE_CONTINUOUS_PICTURE}. Applications can show
+ * autofocus animation based on this.</p>
*/
public interface AutoFocusMoveCallback
{
@@ -962,7 +961,7 @@ public class Camera {
* Called when the camera auto focus starts or stops.
*
* @param start true if focus starts to move, false if focus stops to move
- * @param camera the Camera service object
+ * @param camera the Camera service object
*/
void onAutoFocusMoving(boolean start, Camera camera);
}
@@ -971,7 +970,6 @@ public class Camera {
* Sets camera auto-focus move callback.
*
* @param cb the callback to run
- * @hide
*/
public void setAutoFocusMoveCallback(AutoFocusMoveCallback cb) {
mAutoFocusMoveCallback = cb;
diff --git a/core/java/android/hardware/input/IInputDevicesChangedListener.aidl b/core/java/android/hardware/input/IInputDevicesChangedListener.aidl
new file mode 100644
index 0000000..5d8ada1
--- /dev/null
+++ b/core/java/android/hardware/input/IInputDevicesChangedListener.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2012 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.hardware.input;
+
+/** @hide */
+interface IInputDevicesChangedListener {
+ /* Called when input devices changed, such as a device being added,
+ * removed or changing configuration.
+ *
+ * The parameter is an array of pairs (deviceId, generation) indicating the current
+ * device id and generation of all input devices. The client can determine what
+ * has happened by comparing the result to its prior observations.
+ */
+ oneway void onInputDevicesChanged(in int[] deviceIdAndGeneration);
+}
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index 47e0d1e..ca8321f 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -17,6 +17,7 @@
package android.hardware.input;
import android.hardware.input.KeyboardLayout;
+import android.hardware.input.IInputDevicesChangedListener;
import android.view.InputDevice;
import android.view.InputEvent;
@@ -42,4 +43,7 @@ interface IInputManager {
String getKeyboardLayoutForInputDevice(String inputDeviceDescriptor);
void setKeyboardLayoutForInputDevice(String inputDeviceDescriptor,
String keyboardLayoutDescriptor);
+
+ // Registers an input devices changed listener.
+ void registerInputDevicesChangedListener(IInputDevicesChangedListener listener);
}
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 3b3c237..35c49a1 100755
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -19,7 +19,10 @@ package android.hardware.input;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.Context;
+import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.provider.Settings;
@@ -29,6 +32,8 @@ import android.util.SparseArray;
import android.view.InputDevice;
import android.view.InputEvent;
+import java.util.ArrayList;
+
/**
* Provides information about input devices and available key layouts.
* <p>
@@ -40,11 +45,22 @@ import android.view.InputEvent;
*/
public final class InputManager {
private static final String TAG = "InputManager";
+ private static final boolean DEBUG = false;
+
+ private static final int MSG_DEVICE_ADDED = 1;
+ private static final int MSG_DEVICE_REMOVED = 2;
+ private static final int MSG_DEVICE_CHANGED = 3;
private static InputManager sInstance;
private final IInputManager mIm;
- private final SparseArray<InputDevice> mInputDevices = new SparseArray<InputDevice>();
+
+ // Guarded by mInputDevicesLock
+ private final Object mInputDevicesLock = new Object();
+ private SparseArray<InputDevice> mInputDevices;
+ private InputDevicesChangedListener mInputDevicesChangedListener;
+ private final ArrayList<InputDeviceListenerDelegate> mInputDeviceListeners =
+ new ArrayList<InputDeviceListenerDelegate>();
/**
* Broadcast Action: Query available keyboard layouts.
@@ -169,6 +185,103 @@ public final class InputManager {
}
/**
+ * Gets information about the input device with the specified id.
+ * @param id The device id.
+ * @return The input device or null if not found.
+ */
+ public InputDevice getInputDevice(int id) {
+ synchronized (mInputDevicesLock) {
+ populateInputDevicesLocked();
+
+ int index = mInputDevices.indexOfKey(id);
+ if (index < 0) {
+ return null;
+ }
+
+ InputDevice inputDevice = mInputDevices.valueAt(index);
+ if (inputDevice == null) {
+ try {
+ inputDevice = mIm.getInputDevice(id);
+ } catch (RemoteException ex) {
+ throw new RuntimeException("Could not get input device information.", ex);
+ }
+ }
+ mInputDevices.setValueAt(index, inputDevice);
+ return inputDevice;
+ }
+ }
+
+ /**
+ * Gets the ids of all input devices in the system.
+ * @return The input device ids.
+ */
+ public int[] getInputDeviceIds() {
+ synchronized (mInputDevicesLock) {
+ populateInputDevicesLocked();
+
+ final int count = mInputDevices.size();
+ final int[] ids = new int[count];
+ for (int i = 0; i < count; i++) {
+ ids[i] = mInputDevices.keyAt(i);
+ }
+ return ids;
+ }
+ }
+
+ /**
+ * Registers an input device listener to receive notifications about when
+ * input devices are added, removed or changed.
+ *
+ * @param listener The listener to register.
+ * @param handler The handler on which the listener should be invoked, or null
+ * if the listener should be invoked on the calling thread's looper.
+ *
+ * @see #unregisterInputDeviceListener
+ */
+ public void registerInputDeviceListener(InputDeviceListener listener, Handler handler) {
+ if (listener == null) {
+ throw new IllegalArgumentException("listener must not be null");
+ }
+
+ synchronized (mInputDevicesLock) {
+ int index = findInputDeviceListenerLocked(listener);
+ if (index < 0) {
+ mInputDeviceListeners.add(new InputDeviceListenerDelegate(listener, handler));
+ }
+ }
+ }
+
+ /**
+ * Unregisters an input device listener.
+ *
+ * @param listener The listener to unregister.
+ *
+ * @see #registerInputDeviceListener
+ */
+ public void unregisterInputDeviceListener(InputDeviceListener listener) {
+ if (listener == null) {
+ throw new IllegalArgumentException("listener must not be null");
+ }
+
+ synchronized (mInputDevicesLock) {
+ int index = findInputDeviceListenerLocked(listener);
+ if (index >= 0) {
+ mInputDeviceListeners.remove(index);
+ }
+ }
+ }
+
+ private int findInputDeviceListenerLocked(InputDeviceListener listener) {
+ final int numListeners = mInputDeviceListeners.size();
+ for (int i = 0; i < numListeners; i++) {
+ if (mInputDeviceListeners.get(i).mListener == listener) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
* Gets information about all supported keyboard layouts.
* <p>
* The input manager consults the built-in keyboard layouts as well
@@ -327,50 +440,6 @@ public final class InputManager {
}
/**
- * Gets information about the input device with the specified id.
- * @param id The device id.
- * @return The input device or null if not found.
- *
- * @hide
- */
- public InputDevice getInputDevice(int id) {
- synchronized (mInputDevices) {
- InputDevice inputDevice = mInputDevices.get(id);
- if (inputDevice != null) {
- return inputDevice;
- }
- }
- final InputDevice newInputDevice;
- try {
- newInputDevice = mIm.getInputDevice(id);
- } catch (RemoteException ex) {
- throw new RuntimeException("Could not get input device information.", ex);
- }
- synchronized (mInputDevices) {
- InputDevice inputDevice = mInputDevices.get(id);
- if (inputDevice != null) {
- return inputDevice;
- }
- mInputDevices.put(id, newInputDevice);
- return newInputDevice;
- }
- }
-
- /**
- * Gets the ids of all input devices in the system.
- * @return The input device ids.
- *
- * @hide
- */
- public int[] getInputDeviceIds() {
- try {
- return mIm.getInputDeviceIds();
- } catch (RemoteException ex) {
- throw new RuntimeException("Could not get input device ids.", ex);
- }
- }
-
- /**
* Queries the framework about whether any physical keys exist on the
* any keyboard attached to the device that are capable of producing the given
* array of key codes.
@@ -429,4 +498,151 @@ public final class InputManager {
return false;
}
}
+
+ private void populateInputDevicesLocked() {
+ if (mInputDevicesChangedListener == null) {
+ final InputDevicesChangedListener listener = new InputDevicesChangedListener();
+ try {
+ mIm.registerInputDevicesChangedListener(listener);
+ } catch (RemoteException ex) {
+ throw new RuntimeException(
+ "Could not get register input device changed listener", ex);
+ }
+ mInputDevicesChangedListener = listener;
+ }
+
+ if (mInputDevices == null) {
+ final int[] ids;
+ try {
+ ids = mIm.getInputDeviceIds();
+ } catch (RemoteException ex) {
+ throw new RuntimeException("Could not get input device ids.", ex);
+ }
+
+ mInputDevices = new SparseArray<InputDevice>();
+ for (int i = 0; i < ids.length; i++) {
+ mInputDevices.put(ids[i], null);
+ }
+ }
+ }
+
+ private void onInputDevicesChanged(int[] deviceIdAndGeneration) {
+ if (DEBUG) {
+ Log.d(TAG, "Received input devices changed.");
+ }
+
+ synchronized (mInputDevicesLock) {
+ for (int i = mInputDevices.size(); --i > 0; ) {
+ final int deviceId = mInputDevices.keyAt(i);
+ if (!containsDeviceId(deviceIdAndGeneration, deviceId)) {
+ if (DEBUG) {
+ Log.d(TAG, "Device removed: " + deviceId);
+ }
+ mInputDevices.removeAt(i);
+ sendMessageToInputDeviceListenersLocked(MSG_DEVICE_REMOVED, deviceId);
+ }
+ }
+
+ for (int i = 0; i < deviceIdAndGeneration.length; i += 2) {
+ final int deviceId = deviceIdAndGeneration[i];
+ int index = mInputDevices.indexOfKey(deviceId);
+ if (index >= 0) {
+ final InputDevice device = mInputDevices.valueAt(index);
+ if (device != null) {
+ final int generation = deviceIdAndGeneration[i + 1];
+ if (device.getGeneration() != generation) {
+ if (DEBUG) {
+ Log.d(TAG, "Device changed: " + deviceId);
+ }
+ mInputDevices.setValueAt(index, null);
+ sendMessageToInputDeviceListenersLocked(MSG_DEVICE_CHANGED, deviceId);
+ }
+ }
+ } else {
+ if (DEBUG) {
+ Log.d(TAG, "Device added: " + deviceId);
+ }
+ mInputDevices.put(deviceId, null);
+ sendMessageToInputDeviceListenersLocked(MSG_DEVICE_ADDED, deviceId);
+ }
+ }
+ }
+ }
+
+ private void sendMessageToInputDeviceListenersLocked(int what, int deviceId) {
+ final int numListeners = mInputDeviceListeners.size();
+ for (int i = 0; i < numListeners; i++) {
+ InputDeviceListenerDelegate listener = mInputDeviceListeners.get(i);
+ listener.sendMessage(listener.obtainMessage(what, deviceId, 0));
+ }
+ }
+
+ private static boolean containsDeviceId(int[] deviceIdAndGeneration, int deviceId) {
+ for (int i = 0; i < deviceIdAndGeneration.length; i += 2) {
+ if (deviceIdAndGeneration[i] == deviceId) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Listens for changes in input devices.
+ */
+ public interface InputDeviceListener {
+ /**
+ * Called whenever an input device has been added to the system.
+ * Use {@link InputManager#getInputDevice} to get more information about the device.
+ *
+ * @param deviceId The id of the input device that was added.
+ */
+ void onInputDeviceAdded(int deviceId);
+
+ /**
+ * Called whenever an input device has been removed from the system.
+ *
+ * @param deviceId The id of the input device that was removed.
+ */
+ void onInputDeviceRemoved(int deviceId);
+
+ /**
+ * Called whenever the properties of an input device have changed since they
+ * were last queried. Use {@link InputManager#getInputDevice} to get
+ * a fresh {@link InputDevice} object with the new properties.
+ *
+ * @param deviceId The id of the input device that changed.
+ */
+ void onInputDeviceChanged(int deviceId);
+ }
+
+ private final class InputDevicesChangedListener extends IInputDevicesChangedListener.Stub {
+ @Override
+ public void onInputDevicesChanged(int[] deviceIdAndGeneration) throws RemoteException {
+ InputManager.this.onInputDevicesChanged(deviceIdAndGeneration);
+ }
+ }
+
+ private static final class InputDeviceListenerDelegate extends Handler {
+ public final InputDeviceListener mListener;
+
+ public InputDeviceListenerDelegate(InputDeviceListener listener, Handler handler) {
+ super(handler != null ? handler.getLooper() : Looper.myLooper());
+ mListener = listener;
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_DEVICE_ADDED:
+ mListener.onInputDeviceAdded(msg.arg1);
+ break;
+ case MSG_DEVICE_REMOVED:
+ mListener.onInputDeviceRemoved(msg.arg1);
+ break;
+ case MSG_DEVICE_CHANGED:
+ mListener.onInputDeviceChanged(msg.arg1);
+ break;
+ }
+ }
+ }
}
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index ba7dc4a..332f40a 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -1712,8 +1712,8 @@ public class InputMethodService extends AbstractInputMethodService {
/**
* Override this to intercept key down events before they are processed by the
- * application. If you return true, the application will not itself
- * process the event. If you return true, the normal application processing
+ * application. If you return true, the application will not
+ * process the event itself. If you return false, the normal application processing
* will occur as if the IME had not seen the event at all.
*
* <p>The default implementation intercepts {@link KeyEvent#KEYCODE_BACK
diff --git a/core/java/android/net/nsd/DnsSdServiceInfo.java b/core/java/android/net/nsd/DnsSdServiceInfo.java
index 47d6ec6..33c3eb9 100644
--- a/core/java/android/net/nsd/DnsSdServiceInfo.java
+++ b/core/java/android/net/nsd/DnsSdServiceInfo.java
@@ -19,6 +19,8 @@ package android.net.nsd;
import android.os.Parcelable;
import android.os.Parcel;
+import java.net.InetAddress;
+
/**
* Defines a service based on DNS service discovery
* {@hide}
@@ -27,20 +29,20 @@ public class DnsSdServiceInfo implements NetworkServiceInfo, Parcelable {
private String mServiceName;
- private String mRegistrationType;
+ private String mServiceType;
private DnsSdTxtRecord mTxtRecord;
- private String mHostname;
+ private InetAddress mHost;
private int mPort;
- DnsSdServiceInfo() {
+ public DnsSdServiceInfo() {
}
- DnsSdServiceInfo(String sn, String rt, DnsSdTxtRecord tr) {
+ public DnsSdServiceInfo(String sn, String rt, DnsSdTxtRecord tr) {
mServiceName = sn;
- mRegistrationType = rt;
+ mServiceType = rt;
mTxtRecord = tr;
}
@@ -59,13 +61,13 @@ public class DnsSdServiceInfo implements NetworkServiceInfo, Parcelable {
@Override
/** @hide */
public String getServiceType() {
- return mRegistrationType;
+ return mServiceType;
}
@Override
/** @hide */
public void setServiceType(String s) {
- mRegistrationType = s;
+ mServiceType = s;
}
public DnsSdTxtRecord getTxtRecord() {
@@ -76,12 +78,12 @@ public class DnsSdServiceInfo implements NetworkServiceInfo, Parcelable {
mTxtRecord = new DnsSdTxtRecord(t);
}
- public String getHostName() {
- return mHostname;
+ public InetAddress getHost() {
+ return mHost;
}
- public void setHostName(String s) {
- mHostname = s;
+ public void setHost(InetAddress s) {
+ mHost = s;
}
public int getPort() {
@@ -96,7 +98,9 @@ public class DnsSdServiceInfo implements NetworkServiceInfo, Parcelable {
StringBuffer sb = new StringBuffer();
sb.append("name: ").append(mServiceName).
- append("type: ").append(mRegistrationType).
+ append("type: ").append(mServiceType).
+ append("host: ").append(mHost).
+ append("port: ").append(mPort).
append("txtRecord: ").append(mTxtRecord);
return sb.toString();
}
@@ -109,9 +113,14 @@ public class DnsSdServiceInfo implements NetworkServiceInfo, Parcelable {
/** Implement the Parcelable interface */
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mServiceName);
- dest.writeString(mRegistrationType);
+ dest.writeString(mServiceType);
dest.writeParcelable(mTxtRecord, flags);
- dest.writeString(mHostname);
+ if (mHost != null) {
+ dest.writeByte((byte)1);
+ dest.writeByteArray(mHost.getAddress());
+ } else {
+ dest.writeByte((byte)0);
+ }
dest.writeInt(mPort);
}
@@ -121,9 +130,15 @@ public class DnsSdServiceInfo implements NetworkServiceInfo, Parcelable {
public DnsSdServiceInfo createFromParcel(Parcel in) {
DnsSdServiceInfo info = new DnsSdServiceInfo();
info.mServiceName = in.readString();
- info.mRegistrationType = in.readString();
+ info.mServiceType = in.readString();
info.mTxtRecord = in.readParcelable(null);
- info.mHostname = in.readString();
+
+ if (in.readByte() == 1) {
+ try {
+ info.mHost = InetAddress.getByAddress(in.createByteArray());
+ } catch (java.net.UnknownHostException e) {}
+ }
+
info.mPort = in.readInt();
return info;
}
diff --git a/core/java/android/net/nsd/DnsSdTxtRecord.java b/core/java/android/net/nsd/DnsSdTxtRecord.java
index 6d4342c..952e02f 100644
--- a/core/java/android/net/nsd/DnsSdTxtRecord.java
+++ b/core/java/android/net/nsd/DnsSdTxtRecord.java
@@ -24,6 +24,8 @@ package android.net.nsd;
import android.os.Parcelable;
import android.os.Parcel;
+import java.util.Arrays;
+
/**
* This class handles TXT record data for DNS based service discovery as specified at
* http://tools.ietf.org/html/draft-cheshire-dnsext-dns-sd-11
@@ -160,7 +162,7 @@ public class DnsSdTxtRecord implements Parcelable {
/* Gets the raw data in bytes */
public byte[] getRawData() {
- return mData;
+ return (byte[]) mData.clone();
}
private void insert(byte[] keyBytes, byte[] value, int index) {
@@ -279,6 +281,24 @@ public class DnsSdTxtRecord implements Parcelable {
return result != null ? result : "";
}
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof DnsSdTxtRecord)) {
+ return false;
+ }
+
+ DnsSdTxtRecord record = (DnsSdTxtRecord)o;
+ return Arrays.equals(record.mData, mData);
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(mData);
+ }
+
/** Implement the Parcelable interface */
public int describeContents() {
return 0;
diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java
index a109a98..505f11b 100644
--- a/core/java/android/net/nsd/NsdManager.java
+++ b/core/java/android/net/nsd/NsdManager.java
@@ -93,6 +93,15 @@ public class NsdManager {
/** @hide */
public static final int RESOLVE_SERVICE_SUCCEEDED = BASE + 17;
+ /** @hide */
+ public static final int STOP_RESOLVE = BASE + 18;
+ /** @hide */
+ public static final int STOP_RESOLVE_FAILED = BASE + 19;
+ /** @hide */
+ public static final int STOP_RESOLVE_SUCCEEDED = BASE + 20;
+
+
+
/**
* Create a new Nsd instance. Applications use
* {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
@@ -117,10 +126,23 @@ public class NsdManager {
/**
* Indicates that the operation failed because the framework is busy and
- * unable to service the request
+ * unable to service the request.
*/
public static final int BUSY = 2;
+ /**
+ * Indicates that the operation failed because it is already active.
+ */
+ public static final int ALREADY_ACTIVE = 3;
+
+ /**
+ * Indicates that the operation failed because maximum limit on
+ * service registrations has reached.
+ */
+ public static final int MAX_REGS_REACHED = 4;
+
+
+
/** Interface for callback invocation when framework channel is connected or lost */
public interface ChannelListener {
public void onChannelConnected(Channel c);
@@ -188,6 +210,7 @@ public class NsdManager {
private DnsSdRegisterListener mDnsSdRegisterListener;
private DnsSdUpdateRegistrationListener mDnsSdUpdateListener;
private DnsSdResolveListener mDnsSdResolveListener;
+ private ActionListener mDnsSdStopResolveListener;
AsyncChannel mAsyncChannel;
ServiceHandler mHandler;
@@ -278,6 +301,16 @@ public class NsdManager {
(DnsSdServiceInfo) message.obj);
}
break;
+ case STOP_RESOLVE_FAILED:
+ if (mDnsSdStopResolveListener!= null) {
+ mDnsSdStopResolveListener.onFailure(message.arg1);
+ }
+ break;
+ case STOP_RESOLVE_SUCCEEDED:
+ if (mDnsSdStopResolveListener != null) {
+ mDnsSdStopResolveListener.onSuccess();
+ }
+ break;
default:
Log.d(TAG, "Ignored " + message);
break;
@@ -345,6 +378,14 @@ public class NsdManager {
c.mDnsSdResolveListener = b;
}
+ /**
+ * Set the listener for stopping service resolution. Can be null.
+ */
+ public void setStopResolveListener(Channel c, ActionListener b) {
+ if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+ c.mDnsSdStopResolveListener = b;
+ }
+
public void registerService(Channel c, DnsSdServiceInfo serviceInfo) {
if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
if (serviceInfo == null) throw new IllegalArgumentException("Null serviceInfo");
@@ -378,6 +419,13 @@ public class NsdManager {
c.mAsyncChannel.sendMessage(RESOLVE_SERVICE, serviceInfo);
}
+ public void stopServiceResolve(Channel c) {
+ if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+ if (c.mDnsSdResolveListener == null) throw new
+ IllegalStateException("Resolve listener needs to be set first");
+ c.mAsyncChannel.sendMessage(STOP_RESOLVE);
+ }
+
/**
* Get a reference to NetworkService handler. This is used to establish
* an AsyncChannel communication with the service
diff --git a/core/java/android/provider/BrowserContract.java b/core/java/android/provider/BrowserContract.java
index d678205..118b5eb 100644
--- a/core/java/android/provider/BrowserContract.java
+++ b/core/java/android/provider/BrowserContract.java
@@ -30,6 +30,15 @@ import android.os.RemoteException;
import android.util.Pair;
/**
+ * <p>
+ * The contract between the browser provider and applications. Contains the definition
+ * for the supported URIS and columns.
+ * </p>
+ * <h3>Overview</h3>
+ * <p>
+ * BrowserContract defines an database of browser-related information which are bookmarks,
+ * history, images and the mapping between the image and URL.
+ * </p>
* @hide
*/
public class BrowserContract {
@@ -45,12 +54,14 @@ public class BrowserContract {
* the dirty flag is not automatically set and the "syncToNetwork" parameter
* is set to false when calling
* {@link ContentResolver#notifyChange(android.net.Uri, android.database.ContentObserver, boolean)}.
+ * @hide
*/
public static final String CALLER_IS_SYNCADAPTER = "caller_is_syncadapter";
/**
* A parameter for use when querying any table that allows specifying a limit on the number
* of rows returned.
+ * @hide
*/
public static final String PARAM_LIMIT = "limit";
@@ -58,6 +69,8 @@ public class BrowserContract {
* Generic columns for use by sync adapters. The specific functions of
* these columns are private to the sync adapter. Other clients of the API
* should not attempt to either read or write these columns.
+ *
+ * @hide
*/
interface BaseSyncColumns {
/** Generic column for use by sync adapters. */
@@ -74,6 +87,7 @@ public class BrowserContract {
/**
* Convenience definitions for use in implementing chrome bookmarks sync in the Bookmarks table.
+ * @hide
*/
public static final class ChromeSyncColumns {
private ChromeSyncColumns() {}
@@ -93,6 +107,7 @@ public class BrowserContract {
/**
* Columns that appear when each row of a table belongs to a specific
* account, including sync information that an account may need.
+ * @hide
*/
interface SyncColumns extends BaseSyncColumns {
/**
@@ -144,13 +159,14 @@ public class BrowserContract {
public static final String _ID = "_id";
/**
- * The URL of the bookmark.
+ * This column is valid when the row is a URL. The history table's URL
+ * can not be updated.
* <P>Type: TEXT (URL)</P>
*/
public static final String URL = "url";
/**
- * The user visible title of the bookmark.
+ * The user visible title.
* <P>Type: TEXT</P>
*/
public static final String TITLE = "title";
@@ -159,10 +175,14 @@ public class BrowserContract {
* The time that this row was created on its originating client (msecs
* since the epoch).
* <P>Type: INTEGER</P>
+ * @hide
*/
public static final String DATE_CREATED = "created";
}
+ /**
+ * @hide
+ */
interface ImageColumns {
/**
* The favicon of the bookmark, may be NULL.
@@ -182,7 +202,6 @@ public class BrowserContract {
* The touch icon for the web page, may be NULL.
* Must decode via {@link BitmapFactory#decodeByteArray}.
* <p>Type: BLOB (image)</p>
- * @hide
*/
public static final String TOUCH_ICON = "touch_icon";
}
@@ -200,9 +219,26 @@ public class BrowserContract {
*/
public static final String VISITS = "visits";
+ /**
+ * @hide
+ */
public static final String USER_ENTERED = "user_entered";
}
+ interface ImageMappingColumns {
+ /**
+ * The ID of the image in Images. One image can map onto the multiple URLs.
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String IMAGE_ID = "image_id";
+
+ /**
+ * The URL. The URL can map onto the different type of images.
+ * <P>Type: TEXT (URL)</P>
+ */
+ public static final String URL = "url";
+ }
+
/**
* The bookmarks table, which holds the user's browser bookmarks.
*/
@@ -218,24 +254,71 @@ public class BrowserContract {
public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "bookmarks");
/**
+ * Used in {@link Bookmarks#TYPE} column and indicats the row is a bookmark.
+ */
+ public static final int BOOKMARK_TYPE_BOOKMARK = 1;
+
+ /**
+ * Used in {@link Bookmarks#TYPE} column and indicats the row is a folder.
+ */
+ public static final int BOOKMARK_TYPE_FOLDER = 2;
+
+ /**
+ * Used in {@link Bookmarks#TYPE} column and indicats the row is the bookmark bar folder.
+ */
+ public static final int BOOKMARK_TYPE_BOOKMARK_BAR_FOLDER = 3;
+
+ /**
+ * Used in {@link Bookmarks#TYPE} column and indicats the row is other folder and
+ */
+ public static final int BOOKMARK_TYPE_OTHER_FOLDER = 4;
+
+ /**
+ * Used in {@link Bookmarks#TYPE} column and indicats the row is other folder, .
+ */
+ public static final int BOOKMARK_TYPE_MOBILE_FOLDER = 5;
+
+ /**
+ * The type of the item.
+ * <P>Type: INTEGER</P>
+ * <p>Allowed values are:</p>
+ * <p>
+ * <ul>
+ * <li>{@link #BOOKMARK_TYPE_BOOKMARK}</li>
+ * <li>{@link #BOOKMARK_TYPE_FOLDER}</li>
+ * <li>{@link #BOOKMARK_TYPE_BOOKMARK_BAR_FOLDER}</li>
+ * <li>{@link #BOOKMARK_TYPE_OTHER_FOLDER}</li>
+ * <li>{@link #BOOKMARK_TYPE_MOBILE_FOLDER}</li>
+ * </ul>
+ * </p>
+ * <p> The TYPE_BOOKMARK_BAR_FOLDER, TYPE_OTHER_FOLDER and TYPE_MOBILE_FOLDER
+ * can not be updated or deleted.</p>
+ */
+ public static final String TYPE = "type";
+
+ /**
* The content:// style URI for the default folder
+ * @hide
*/
public static final Uri CONTENT_URI_DEFAULT_FOLDER =
Uri.withAppendedPath(CONTENT_URI, "folder");
/**
* Query parameter used to specify an account name
+ * @hide
*/
public static final String PARAM_ACCOUNT_NAME = "acct_name";
/**
* Query parameter used to specify an account type
+ * @hide
*/
public static final String PARAM_ACCOUNT_TYPE = "acct_type";
/**
* Builds a URI that points to a specific folder.
* @param folderId the ID of the folder to point to
+ * @hide
*/
public static final Uri buildFolderUri(long folderId) {
return ContentUris.withAppendedId(CONTENT_URI_DEFAULT_FOLDER, folderId);
@@ -255,6 +338,7 @@ public class BrowserContract {
* Query parameter to use if you want to see deleted bookmarks that are still
* around on the device and haven't been synced yet.
* @see #IS_DELETED
+ * @hide
*/
public static final String QUERY_PARAMETER_SHOW_DELETED = "show_deleted";
@@ -262,6 +346,7 @@ public class BrowserContract {
* Flag indicating if an item is a folder or bookmark. Non-zero values indicate
* a folder and zero indicates a bookmark.
* <P>Type: INTEGER (boolean)</P>
+ * @hide
*/
public static final String IS_FOLDER = "folder";
@@ -274,6 +359,7 @@ public class BrowserContract {
/**
* The source ID for an item's parent. Read-only.
* @see #PARENT
+ * @hide
*/
public static final String PARENT_SOURCE_ID = "parent_source";
@@ -281,6 +367,7 @@ public class BrowserContract {
* The position of the bookmark in relation to it's siblings that share the same
* {@link #PARENT}. May be negative.
* <P>Type: INTEGER</P>
+ * @hide
*/
public static final String POSITION = "position";
@@ -288,6 +375,7 @@ public class BrowserContract {
* The item that the bookmark should be inserted after.
* May be negative.
* <P>Type: INTEGER</P>
+ * @hide
*/
public static final String INSERT_AFTER = "insert_after";
@@ -296,6 +384,7 @@ public class BrowserContract {
* May be negative.
* <P>Type: INTEGER</P>
* @see #INSERT_AFTER
+ * @hide
*/
public static final String INSERT_AFTER_SOURCE_ID = "insert_after_source";
@@ -305,12 +394,14 @@ public class BrowserContract {
* to the URI when performing your query.
* <p>Type: INTEGER (non-zero if the item has been deleted, zero if it hasn't)
* @see #QUERY_PARAMETER_SHOW_DELETED
+ * @hide
*/
public static final String IS_DELETED = "deleted";
}
/**
* Read-only table that lists all the accounts that are used to provide bookmarks.
+ * @hide
*/
public static final class Accounts {
/**
@@ -410,6 +501,7 @@ public class BrowserContract {
* A table provided for sync adapters to use for storing private sync state data.
*
* @see SyncStateContract
+ * @hide
*/
public static final class SyncState implements SyncStateContract.Columns {
/**
@@ -459,8 +551,18 @@ public class BrowserContract {
}
/**
- * Stores images for URLs. Only support query() and update().
- * @hide
+ * <p>
+ * Stores images for URLs.
+ * </p>
+ * <p>
+ * The rows in this table can not be updated since there might have multiple URLs mapping onto
+ * the same image. If you want to update a URL's image, you need to add the new image in this
+ * table, then update the mapping onto the added image.
+ * </p>
+ * <p>
+ * Every image should be at least associated with one URL, otherwise it will be removed after a
+ * while.
+ * </p>
*/
public static final class Images implements ImageColumns {
/**
@@ -474,15 +576,93 @@ public class BrowserContract {
public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "images");
/**
+ * The MIME type of {@link #CONTENT_URI} providing a directory of images.
+ */
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/images";
+
+ /**
+ * The MIME type of a {@link #CONTENT_URI} of a single image.
+ */
+ public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/images";
+
+ /**
+ * Used in {@link Images#TYPE} column and indicats the row is a favicon.
+ */
+ public static final int IMAGE_TYPE_FAVICON = 1;
+
+ /**
+ * Used in {@link Images#TYPE} column and indicats the row is a precomposed touch icon.
+ */
+ public static final int IMAGE_TYPE_PRECOMPOSED_TOUCH_ICON = 2;
+
+ /**
+ * Used in {@link Images#TYPE} column and indicats the row is a touch icon.
+ */
+ public static final int IMAGE_TYPE_TOUCH_ICON = 4;
+
+ /**
+ * The type of item in the table.
+ * <P>Type: INTEGER</P>
+ * <p>Allowed values are:</p>
+ * <p>
+ * <ul>
+ * <li>{@link #IMAGE_TYPE_FAVICON}</li>
+ * <li>{@link #IMAGE_TYPE_PRECOMPOSED_TOUCH_ICON}</li>
+ * <li>{@link #IMAGE_TYPE_TOUCH_ICON}</li>
+ * </ul>
+ * </p>
+ */
+ public static final String TYPE = "type";
+
+ /**
+ * The image data.
+ * <p>Type: BLOB (image)</p>
+ */
+ public static final String DATA = "data";
+
+ /**
* The URL the images came from.
* <P>Type: TEXT (URL)</P>
+ * @hide
*/
public static final String URL = "url_key";
}
/**
+ * <p>
+ * A table that stores the mappings between the image and the URL.
+ * </p>
+ * <p>
+ * Deleting or Updating a mapping might also deletes the mapped image if there is no other URL
+ * maps onto it.
+ * </p>
+ */
+ public static final class ImageMappings implements ImageMappingColumns {
+ /**
+ * This utility class cannot be instantiated
+ */
+ private ImageMappings() {}
+
+ /**
+ * The content:// style URI for this table
+ */
+ public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "image_mappings");
+
+ /**
+ * The MIME type of {@link #CONTENT_URI} providing a directory of image mappings.
+ */
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/image_mappings";
+
+ /**
+ * The MIME type of a {@link #CONTENT_URI} of a single image mapping.
+ */
+ public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/image_mappings";
+ }
+
+ /**
* A combined view of bookmarks and history. All bookmarks in all folders are included and
* no folders are included.
+ * @hide
*/
public static final class Combined implements CommonColumns, HistoryColumns, ImageColumns {
/**
@@ -505,6 +685,7 @@ public class BrowserContract {
/**
* A table that stores settings specific to the browser. Only support query and insert.
+ * @hide
*/
public static final class Settings {
/**
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 0e9306b..035d8c4 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -1536,7 +1536,11 @@ public final class ContactsContract {
*
* @param resolver the ContentResolver to use
* @param contactId the person who was contacted
+ *
+ * @deprecated The class DataUsageStatUpdater of the Android support library should
+ * be used instead.
*/
+ @Deprecated
public static void markAsContacted(ContentResolver resolver, long contactId) {
Uri uri = ContentUris.withAppendedId(CONTENT_URI, contactId);
ContentValues values = new ContentValues();
@@ -7452,7 +7456,7 @@ public final class ContactsContract {
/**
* <p>
* API allowing applications to send usage information for each {@link Data} row to the
- * Contacts Provider.
+ * Contacts Provider. Applications can also clear all usage information.
* </p>
* <p>
* With the feedback, Contacts Provider may return more contextually appropriate results for
@@ -7497,6 +7501,12 @@ public final class ContactsContract {
* boolean successful = resolver.update(uri, new ContentValues(), null, null) > 0;
* </pre>
* </p>
+ * <p>
+ * Applications can also clear all usage information with:
+ * <pre>
+ * boolean successful = resolver.delete(DataUsageFeedback.DELETE_USAGE_URI, null, null) > 0;
+ * </pre>
+ * </p>
*/
public static final class DataUsageFeedback {
@@ -7508,6 +7518,14 @@ public final class ContactsContract {
Uri.withAppendedPath(Data.CONTENT_URI, "usagefeedback");
/**
+ * The content:// style URI for deleting all usage information.
+ * Must be used with {@link ContentResolver#delete(Uri, String, String[])}.
+ * The {@code where} and {@code selectionArgs} parameters are ignored.
+ */
+ public static final Uri DELETE_USAGE_URI =
+ Uri.withAppendedPath(Contacts.CONTENT_URI, "delete_usage");
+
+ /**
* <p>
* Name for query parameter specifying the type of data usage.
* </p>
diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java
index bd6170b..cd8d51f 100644
--- a/core/java/android/provider/Downloads.java
+++ b/core/java/android/provider/Downloads.java
@@ -704,6 +704,37 @@ public final class Downloads {
*/
public static final int STATUS_BLOCKED = 498;
+ /** {@hide} */
+ public static String statusToString(int status) {
+ switch (status) {
+ case STATUS_PENDING: return "PENDING";
+ case STATUS_RUNNING: return "RUNNING";
+ case STATUS_PAUSED_BY_APP: return "PAUSED_BY_APP";
+ case STATUS_WAITING_TO_RETRY: return "WAITING_TO_RETRY";
+ case STATUS_WAITING_FOR_NETWORK: return "WAITING_FOR_NETWORK";
+ case STATUS_QUEUED_FOR_WIFI: return "QUEUED_FOR_WIFI";
+ case STATUS_INSUFFICIENT_SPACE_ERROR: return "INSUFFICIENT_SPACE_ERROR";
+ case STATUS_DEVICE_NOT_FOUND_ERROR: return "DEVICE_NOT_FOUND_ERROR";
+ case STATUS_SUCCESS: return "SUCCESS";
+ case STATUS_BAD_REQUEST: return "BAD_REQUEST";
+ case STATUS_NOT_ACCEPTABLE: return "NOT_ACCEPTABLE";
+ case STATUS_LENGTH_REQUIRED: return "LENGTH_REQUIRED";
+ case STATUS_PRECONDITION_FAILED: return "PRECONDITION_FAILED";
+ case STATUS_FILE_ALREADY_EXISTS_ERROR: return "FILE_ALREADY_EXISTS_ERROR";
+ case STATUS_CANNOT_RESUME: return "CANNOT_RESUME";
+ case STATUS_CANCELED: return "CANCELED";
+ case STATUS_UNKNOWN_ERROR: return "UNKNOWN_ERROR";
+ case STATUS_FILE_ERROR: return "FILE_ERROR";
+ case STATUS_UNHANDLED_REDIRECT: return "UNHANDLED_REDIRECT";
+ case STATUS_UNHANDLED_HTTP_CODE: return "UNHANDLED_HTTP_CODE";
+ case STATUS_HTTP_DATA_ERROR: return "HTTP_DATA_ERROR";
+ case STATUS_HTTP_EXCEPTION: return "HTTP_EXCEPTION";
+ case STATUS_TOO_MANY_REDIRECTS: return "TOO_MANY_REDIRECTS";
+ case STATUS_BLOCKED: return "BLOCKED";
+ default: return Integer.toString(status);
+ }
+ }
+
/**
* This download is visible but only shows in the notifications
* while it's in progress.
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index 6056c75..11c169e 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -75,7 +75,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
if (spans[i] instanceof NoCopySpan) {
continue;
}
-
+
int st = sp.getSpanStart(spans[i]) - start;
int en = sp.getSpanEnd(spans[i]) - start;
int fl = sp.getSpanFlags(spans[i]);
@@ -212,7 +212,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
if (mGapLength > 2 * length())
resizeFor(length());
-
+
return ret; // == this
}
@@ -220,7 +220,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
public void clear() {
replace(0, length(), "", 0, 0);
}
-
+
// Documentation from interface
public void clearSpans() {
for (int i = mSpanCount - 1; i >= 0; i--) {
@@ -257,45 +257,50 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
return append(String.valueOf(text));
}
- private void change(int start, int end, CharSequence tb, int tbstart, int tbend) {
- checkRange("replace", start, end);
+ private void change(int start, int end, CharSequence cs, int csStart, int csEnd) {
+ // Can be negative
+ final int nbNewChars = (csEnd - csStart) - (end - start);
for (int i = mSpanCount - 1; i >= 0; i--) {
- if ((mSpanFlags[i] & SPAN_PARAGRAPH) == SPAN_PARAGRAPH) {
- int st = mSpanStarts[i];
- if (st > mGapStart)
- st -= mGapLength;
+ int spanStart = mSpanStarts[i];
+ if (spanStart > mGapStart)
+ spanStart -= mGapLength;
- int en = mSpanEnds[i];
- if (en > mGapStart)
- en -= mGapLength;
+ int spanEnd = mSpanEnds[i];
+ if (spanEnd > mGapStart)
+ spanEnd -= mGapLength;
- int ost = st;
- int oen = en;
+ if ((mSpanFlags[i] & SPAN_PARAGRAPH) == SPAN_PARAGRAPH) {
+ int ost = spanStart;
+ int oen = spanEnd;
int clen = length();
- if (st > start && st <= end) {
- for (st = end; st < clen; st++)
- if (st > end && charAt(st - 1) == '\n')
+ if (spanStart > start && spanStart <= end) {
+ for (spanStart = end; spanStart < clen; spanStart++)
+ if (spanStart > end && charAt(spanStart - 1) == '\n')
break;
}
- if (en > start && en <= end) {
- for (en = end; en < clen; en++)
- if (en > end && charAt(en - 1) == '\n')
+ if (spanEnd > start && spanEnd <= end) {
+ for (spanEnd = end; spanEnd < clen; spanEnd++)
+ if (spanEnd > end && charAt(spanEnd - 1) == '\n')
break;
}
- if (st != ost || en != oen)
- setSpan(false, mSpans[i], st, en, mSpanFlags[i]);
+ if (spanStart != ost || spanEnd != oen)
+ setSpan(false, mSpans[i], spanStart, spanEnd, mSpanFlags[i]);
}
+
+ int flags = 0;
+ if (spanStart == start) flags |= SPAN_START_AT_START;
+ else if (spanStart == end + nbNewChars) flags |= SPAN_START_AT_END;
+ if (spanEnd == start) flags |= SPAN_END_AT_START;
+ else if (spanEnd == end + nbNewChars) flags |= SPAN_END_AT_END;
+ mSpanFlags[i] |= flags;
}
moveGapTo(end);
- // Can be negative
- final int nbNewChars = (tbend - tbstart) - (end - start);
-
if (nbNewChars >= mGapLength) {
resizeFor(mText.length + nbNewChars - mGapLength);
}
@@ -306,7 +311,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
if (mGapLength < 1)
new Exception("mGapLength < 1").printStackTrace();
- TextUtils.getChars(tb, tbstart, tbend, mText, start);
+ TextUtils.getChars(cs, csStart, csEnd, mText, start);
if (end > start) {
// no need for span fixup on pure insertion
@@ -340,21 +345,23 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
}
}
- if (tb instanceof Spanned) {
- Spanned sp = (Spanned) tb;
- Object[] spans = sp.getSpans(tbstart, tbend, Object.class);
+ mSpanCountBeforeAdd = mSpanCount;
+
+ if (cs instanceof Spanned) {
+ Spanned sp = (Spanned) cs;
+ Object[] spans = sp.getSpans(csStart, csEnd, Object.class);
for (int i = 0; i < spans.length; i++) {
int st = sp.getSpanStart(spans[i]);
int en = sp.getSpanEnd(spans[i]);
- if (st < tbstart) st = tbstart;
- if (en > tbend) en = tbend;
+ if (st < csStart) st = csStart;
+ if (en > csEnd) en = csEnd;
// Add span only if this object is not yet used as a span in this string
- if (getSpanStart(spans[i]) < 0) {
- setSpan(false, spans[i], st - tbstart + start, en - tbstart + start,
- sp.getSpanFlags(spans[i]));
+ if (getSpanStart(spans[i]) < 0 && !(spans[i] instanceof SpanWatcher)) {
+ setSpan(false, spans[i], st - csStart + start, en - csStart + start,
+ sp.getSpanFlags(spans[i]));
}
}
}
@@ -390,6 +397,8 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
// Documentation from interface
public SpannableStringBuilder replace(final int start, final int end,
CharSequence tb, int tbstart, int tbend) {
+ checkRange("replace", start, end);
+
int filtercount = mFilters.length;
for (int i = 0; i < filtercount; i++) {
CharSequence repl = mFilters[i].filter(tb, tbstart, tbend, this, start, end);
@@ -404,10 +413,6 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
final int origLen = end - start;
final int newLen = tbend - tbstart;
- if (origLen == 0 && newLen == 0) {
- return this;
- }
-
TextWatcher[] textWatchers = getSpans(start, start + origLen, TextWatcher.class);
sendBeforeTextChanged(textWatchers, start, origLen, newLen);
@@ -415,43 +420,101 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
// a text replacement. If replaced or replacement text length is zero, this
// is already taken care of.
boolean adjustSelection = origLen != 0 && newLen != 0;
- int selstart = 0;
- int selend = 0;
+ int selectionStart = 0;
+ int selectionEnd = 0;
if (adjustSelection) {
- selstart = Selection.getSelectionStart(this);
- selend = Selection.getSelectionEnd(this);
+ selectionStart = Selection.getSelectionStart(this);
+ selectionEnd = Selection.getSelectionEnd(this);
}
- checkRange("replace", start, end);
-
change(start, end, tb, tbstart, tbend);
if (adjustSelection) {
- if (selstart > start && selstart < end) {
- long off = selstart - start;
-
- off = off * newLen / origLen;
- selstart = (int) off + start;
+ if (selectionStart > start && selectionStart < end) {
+ final int offset = (selectionStart - start) * newLen / origLen;
+ selectionStart = start + offset;
- setSpan(false, Selection.SELECTION_START, selstart, selstart,
+ setSpan(false, Selection.SELECTION_START, selectionStart, selectionStart,
Spanned.SPAN_POINT_POINT);
}
- if (selend > start && selend < end) {
- long off = selend - start;
+ if (selectionEnd > start && selectionEnd < end) {
+ final int offset = (selectionEnd - start) * newLen / origLen;
+ selectionEnd = start + offset;
- off = off * newLen / origLen;
- selend = (int) off + start;
-
- setSpan(false, Selection.SELECTION_END, selend, selend, Spanned.SPAN_POINT_POINT);
+ setSpan(false, Selection.SELECTION_END, selectionEnd, selectionEnd,
+ Spanned.SPAN_POINT_POINT);
}
}
sendTextChanged(textWatchers, start, origLen, newLen);
sendAfterTextChanged(textWatchers);
+ // Span watchers need to be called after text watchers, which may update the layout
+ sendToSpanWatchers(start, end, newLen - origLen);
+
return this;
}
+ private void sendToSpanWatchers(int replaceStart, int replaceEnd, int nbNewChars) {
+ for (int i = 0; i < mSpanCountBeforeAdd; i++) {
+ int spanStart = mSpanStarts[i];
+ int spanEnd = mSpanEnds[i];
+ if (spanStart > mGapStart) spanStart -= mGapLength;
+ if (spanEnd > mGapStart) spanEnd -= mGapLength;
+ int spanFlags = mSpanFlags[i];
+
+ int newReplaceEnd = replaceEnd + nbNewChars;
+ boolean spanChanged = false;
+ int previousSpanStart = spanStart;
+ if (spanStart > newReplaceEnd) {
+ if (nbNewChars != 0) {
+ previousSpanStart -= nbNewChars;
+ spanChanged = true;
+ }
+ } else if (spanStart >= replaceStart) {
+ // No change if span start was already at replace interval boundaries before replace
+ if ((spanStart != replaceStart ||
+ ((spanFlags & SPAN_START_AT_START) != SPAN_START_AT_START)) &&
+ (spanStart != newReplaceEnd ||
+ ((spanFlags & SPAN_START_AT_END) != SPAN_START_AT_END))) {
+ // TODO previousSpanStart is incorrect, but we would need to save all the
+ // previous spans' positions before replace to provide it
+ spanChanged = true;
+ }
+ }
+ int previousSpanEnd = spanEnd;
+ if (spanEnd > newReplaceEnd) {
+ if (nbNewChars != 0) {
+ previousSpanEnd -= nbNewChars;
+ spanChanged = true;
+ }
+ } else if (spanEnd >= replaceStart) {
+ // No change if span start was already at replace interval boundaries before replace
+ if ((spanEnd != replaceStart ||
+ ((spanFlags & SPAN_END_AT_START) != SPAN_END_AT_START)) &&
+ (spanEnd != newReplaceEnd ||
+ ((spanFlags & SPAN_END_AT_END) != SPAN_END_AT_END))) {
+ // TODO same as above for previousSpanEnd
+ spanChanged = true;
+ }
+ }
+
+ if (spanChanged) {
+ sendSpanChanged(mSpans[i], previousSpanStart, previousSpanEnd, spanStart, spanEnd);
+ }
+ mSpanFlags[i] &= ~SPAN_START_END_MASK;
+ }
+
+ // The spans starting at mIntermediateSpanCount were added from the replacement text
+ for (int i = mSpanCountBeforeAdd; i < mSpanCount; i++) {
+ int spanStart = mSpanStarts[i];
+ int spanEnd = mSpanEnds[i];
+ if (spanStart > mGapStart) spanStart -= mGapLength;
+ if (spanEnd > mGapStart) spanEnd -= mGapLength;
+ sendSpanAdded(mSpans[i], spanStart, spanEnd);
+ }
+ }
+
/**
* Mark the specified range of text with the specified object.
* The flags determine how the span will behave when text is
@@ -788,13 +851,12 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
if (end <= mGapStart) {
System.arraycopy(mText, start, dest, destoff, end - start);
} else if (start >= mGapStart) {
- System.arraycopy(mText, start + mGapLength,
- dest, destoff, end - start);
+ System.arraycopy(mText, start + mGapLength, dest, destoff, end - start);
} else {
System.arraycopy(mText, start, dest, destoff, mGapStart - start);
System.arraycopy(mText, mGapStart + mGapLength,
- dest, destoff + (mGapStart - start),
- end - mGapStart);
+ dest, destoff + (mGapStart - start),
+ end - mGapStart);
}
}
@@ -863,12 +925,14 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
}
}
- private void sendSpanChanged(Object what, int s, int e, int st, int en) {
- SpanWatcher[] recip = getSpans(Math.min(s, st), Math.max(e, en), SpanWatcher.class);
- int n = recip.length;
-
+ private void sendSpanChanged(Object what, int oldStart, int oldEnd, int start, int end) {
+ // The bounds of a possible SpanWatcher are guaranteed to be set before this method is
+ // called, so that the order of the span does not affect this broadcast.
+ SpanWatcher[] spanWatchers = getSpans(Math.min(oldStart, start),
+ Math.min(Math.max(oldEnd, end), length()), SpanWatcher.class);
+ int n = spanWatchers.length;
for (int i = 0; i < n; i++) {
- recip[i].onSpanChanged(this, what, s, e, st, en);
+ spanWatchers[i].onSpanChanged(this, what, oldStart, oldEnd, start, end);
}
}
@@ -879,26 +943,23 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
private void checkRange(final String operation, int start, int end) {
if (end < start) {
throw new IndexOutOfBoundsException(operation + " " +
- region(start, end) +
- " has end before start");
+ region(start, end) + " has end before start");
}
int len = length();
if (start > len || end > len) {
throw new IndexOutOfBoundsException(operation + " " +
- region(start, end) +
- " ends beyond length " + len);
+ region(start, end) + " ends beyond length " + len);
}
if (start < 0 || end < 0) {
throw new IndexOutOfBoundsException(operation + " " +
- region(start, end) +
- " starts before 0");
+ region(start, end) + " starts before 0");
}
}
-/*
+ /*
private boolean isprint(char c) { // XXX
if (c >= ' ' && c <= '~')
return true;
@@ -977,7 +1038,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
System.out.print("\n");
}
-*/
+ */
/**
* Don't call this yourself -- exists for Canvas to use internally.
@@ -1023,7 +1084,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
}
}
- /**
+ /**
* Don't call this yourself -- exists for Paint to use internally.
* {@hide}
*/
@@ -1059,8 +1120,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
if (end <= mGapStart) {
ret = p.getTextWidths(mText, start, end - start, widths);
} else if (start >= mGapStart) {
- ret = p.getTextWidths(mText, start + mGapLength, end - start,
- widths);
+ ret = p.getTextWidths(mText, start + mGapLength, end - start, widths);
} else {
char[] buf = TextUtils.obtain(end - start);
@@ -1205,6 +1265,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
private int[] mSpanEnds;
private int[] mSpanFlags;
private int mSpanCount;
+ private int mSpanCountBeforeAdd;
// TODO These value are tightly related to the public SPAN_MARK/POINT values in {@link Spanned}
private static final int MARK = 1;
@@ -1214,4 +1275,11 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
private static final int START_MASK = 0xF0;
private static final int END_MASK = 0x0F;
private static final int START_SHIFT = 4;
+
+ // These bits are not (currently) used by SPANNED flags
+ private static final int SPAN_START_AT_START = 0x1000;
+ private static final int SPAN_START_AT_END = 0x2000;
+ private static final int SPAN_END_AT_START = 0x4000;
+ private static final int SPAN_END_AT_END = 0x8000;
+ private static final int SPAN_START_END_MASK = 0xF000;
}
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index aa0ac74..8bc36b7 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -237,6 +237,17 @@ public abstract class HardwareRenderer {
abstract boolean validate();
/**
+ * This method ensures the hardware renderer is in a valid state
+ * before executing the specified action.
+ *
+ * This method will attempt to set a valid state even if the window
+ * the renderer is attached to was destroyed.
+ *
+ * @return true if the action was run
+ */
+ abstract boolean safelyRun(Runnable action);
+
+ /**
* Setup the hardware renderer for drawing. This is called whenever the
* size of the target surface changes or when the surface is first created.
*
@@ -1380,26 +1391,40 @@ public abstract class HardwareRenderer {
}
@Override
- void destroyHardwareResources(View view) {
- if (view != null) {
- boolean needsContext = true;
- if (isEnabled() && checkCurrent() != SURFACE_STATE_ERROR) needsContext = false;
-
- if (needsContext) {
- Gl20RendererEglContext managedContext =
- (Gl20RendererEglContext) sEglContextStorage.get();
- if (managedContext == null) return;
- usePbufferSurface(managedContext.getContext());
- }
-
- destroyResources(view);
- GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
+ boolean safelyRun(Runnable action) {
+ boolean needsContext = true;
+ if (isEnabled() && checkCurrent() != SURFACE_STATE_ERROR) needsContext = false;
+
+ if (needsContext) {
+ Gl20RendererEglContext managedContext =
+ (Gl20RendererEglContext) sEglContextStorage.get();
+ if (managedContext == null) return false;
+ usePbufferSurface(managedContext.getContext());
+ }
+ try {
+ action.run();
+ } finally {
if (needsContext) {
sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE,
EGL_NO_SURFACE, EGL_NO_CONTEXT);
}
}
+
+ return true;
+ }
+
+ @Override
+ void destroyHardwareResources(final View view) {
+ if (view != null) {
+ safelyRun(new Runnable() {
+ @Override
+ public void run() {
+ destroyResources(view);
+ GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
+ }
+ });
+ }
}
private static void destroyResources(View view) {
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index 75b2c746..4ebb679 100755
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -40,6 +40,7 @@ import java.util.List;
*/
public final class InputDevice implements Parcelable {
private final int mId;
+ private final int mGeneration;
private final String mName;
private final String mDescriptor;
private final int mSources;
@@ -302,9 +303,10 @@ public final class InputDevice implements Parcelable {
};
// Called by native code.
- private InputDevice(int id, String name, String descriptor, int sources,
+ private InputDevice(int id, int generation, String name, String descriptor, int sources,
int keyboardType, KeyCharacterMap keyCharacterMap) {
mId = id;
+ mGeneration = generation;
mName = name;
mDescriptor = descriptor;
mSources = sources;
@@ -314,6 +316,7 @@ public final class InputDevice implements Parcelable {
private InputDevice(Parcel in) {
mId = in.readInt();
+ mGeneration = in.readInt();
mName = in.readString();
mDescriptor = in.readString();
mSources = in.readInt();
@@ -364,6 +367,19 @@ public final class InputDevice implements Parcelable {
}
/**
+ * Gets a generation number for this input device.
+ * The generation number is incremented whenever the device is reconfigured and its
+ * properties may have changed.
+ *
+ * @return The generation number.
+ *
+ * @hide
+ */
+ public int getGeneration() {
+ return mGeneration;
+ }
+
+ /**
* Gets the input device descriptor, which is a stable identifier for an input device.
* <p>
* An input device descriptor uniquely identifies an input device. Its value
@@ -595,6 +611,7 @@ public final class InputDevice implements Parcelable {
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mId);
+ out.writeInt(mGeneration);
out.writeString(mName);
out.writeString(mDescriptor);
out.writeInt(mSources);
@@ -624,6 +641,7 @@ public final class InputDevice implements Parcelable {
StringBuilder description = new StringBuilder();
description.append("Input Device ").append(mId).append(": ").append(mName).append("\n");
description.append(" Descriptor: ").append(mDescriptor).append("\n");
+ description.append(" Generation: ").append(mGeneration).append("\n");
description.append(" Keyboard Type: ");
switch (mKeyboardType) {
diff --git a/core/java/android/view/KeyCharacterMap.java b/core/java/android/view/KeyCharacterMap.java
index 3d165ea..12d7b12 100644
--- a/core/java/android/view/KeyCharacterMap.java
+++ b/core/java/android/view/KeyCharacterMap.java
@@ -22,8 +22,6 @@ import android.text.method.MetaKeyKeyListener;
import android.util.AndroidRuntimeException;
import android.util.SparseIntArray;
import android.hardware.input.InputManager;
-import android.util.SparseArray;
-import android.view.InputDevice.MotionRange;
import java.lang.Character;
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 3cd8b71..32029ba 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -187,7 +187,9 @@ public class TextureView extends View {
public void setOpaque(boolean opaque) {
if (opaque != mOpaque) {
mOpaque = opaque;
- updateLayer();
+ if (mLayer != null) {
+ updateLayer();
+ }
}
}
@@ -204,7 +206,18 @@ public class TextureView extends View {
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
- destroySurface();
+ if (mLayer != null && mAttachInfo != null && mAttachInfo.mHardwareRenderer != null) {
+ boolean success = mAttachInfo.mHardwareRenderer.safelyRun(new Runnable() {
+ @Override
+ public void run() {
+ destroySurface();
+ }
+ });
+
+ if (!success) {
+ Log.w(LOG_TAG, "TextureView was not able to destroy its surface: " + this);
+ }
+ }
}
private void destroySurface() {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 0be7a87..1fa19d1 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4483,10 +4483,8 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
getDrawingRect(bounds);
info.setBoundsInParent(bounds);
- int[] locationOnScreen = mAttachInfo.mInvalidateChildLocation;
- getLocationOnScreen(locationOnScreen);
- bounds.offsetTo(0, 0);
- bounds.offset(locationOnScreen[0], locationOnScreen[1]);
+ getGlobalVisibleRect(bounds);
+ bounds.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
info.setBoundsInScreen(bounds);
if ((mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
@@ -9792,7 +9790,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* @attr ref android.R.styleable#View_scrollbarSize
*/
public int getScrollBarSize() {
- return mScrollCache == null ? ViewConfiguration.getScrollBarSize() :
+ return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
mScrollCache.scrollBarSize;
}
@@ -12971,6 +12969,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* background
*/
public void setBackground(Drawable background) {
+ //noinspection deprecation
setBackgroundDrawable(background);
}
@@ -14296,7 +14295,15 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
*/
public void setAnimation(Animation animation) {
mCurrentAnimation = animation;
+
if (animation != null) {
+ // If the screen is off assume the animation start time is now instead of
+ // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
+ // would cause the animation to start when the screen turns back on
+ if (mAttachInfo != null && !mAttachInfo.mScreenOn &&
+ animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
+ animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
+ }
animation.reset();
}
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 899fb32..7a43cf1 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -5065,6 +5065,23 @@ public final class ViewRootImpl implements ViewParent,
}
/**
+ * Computes whether a view is visible on the screen.
+ *
+ * @param view The view to check.
+ * @return Whether the view is visible on the screen.
+ */
+ private boolean isDisplayedOnScreen(View view) {
+ // The first two checks are made also made by isShown() which
+ // however traverses the tree up to the parent to catch that.
+ // Therefore, we do some fail fast check to minimize the up
+ // tree traversal.
+ return (view.mAttachInfo != null
+ && view.mAttachInfo.mWindowVisibility == View.VISIBLE
+ && view.isShown()
+ && view.getGlobalVisibleRect(mTempRect));
+ }
+
+ /**
* Class for managing accessibility interactions initiated from the system
* and targeting the view hierarchy. A *ClientThread method is to be
* called from the interaction connection this ViewAncestor gives the
@@ -5175,7 +5192,7 @@ public final class ViewRootImpl implements ViewParent,
} else {
target = findViewByAccessibilityId(accessibilityViewId);
}
- if (target != null && target.getVisibility() == View.VISIBLE) {
+ if (target != null && isDisplayedOnScreen(target)) {
getAccessibilityNodePrefetcher().prefetchAccessibilityNodeInfos(target,
virtualDescendantId, prefetchFlags, infos);
}
@@ -5231,7 +5248,7 @@ public final class ViewRootImpl implements ViewParent,
}
if (root != null) {
View target = root.findViewById(viewId);
- if (target != null && target.getVisibility() == View.VISIBLE) {
+ if (target != null && isDisplayedOnScreen(target)) {
info = target.createAccessibilityNodeInfo();
}
}
@@ -5287,7 +5304,7 @@ public final class ViewRootImpl implements ViewParent,
} else {
target = ViewRootImpl.this.mView;
}
- if (target != null && target.getVisibility() == View.VISIBLE) {
+ if (target != null && isDisplayedOnScreen(target)) {
AccessibilityNodeProvider provider = target.getAccessibilityNodeProvider();
if (provider != null) {
infos = provider.findAccessibilityNodeInfosByText(text,
@@ -5304,7 +5321,7 @@ public final class ViewRootImpl implements ViewParent,
final int viewCount = foundViews.size();
for (int i = 0; i < viewCount; i++) {
View foundView = foundViews.get(i);
- if (foundView.getVisibility() == View.VISIBLE) {
+ if (isDisplayedOnScreen(foundView)) {
provider = foundView.getAccessibilityNodeProvider();
if (provider != null) {
List<AccessibilityNodeInfo> infosFromProvider =
@@ -5367,7 +5384,7 @@ public final class ViewRootImpl implements ViewParent,
boolean succeeded = false;
try {
View target = findViewByAccessibilityId(accessibilityViewId);
- if (target != null && target.getVisibility() == View.VISIBLE) {
+ if (target != null && isDisplayedOnScreen(target)) {
AccessibilityNodeProvider provider = target.getAccessibilityNodeProvider();
if (provider != null) {
succeeded = provider.performAccessibilityAction(action,
@@ -5505,7 +5522,7 @@ public final class ViewRootImpl implements ViewParent,
View child = parentGroup.getChildAt(i);
if (outInfos.size() < MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE
&& child.getAccessibilityViewId() != current.getAccessibilityViewId()
- && child.getVisibility() == View.VISIBLE) {
+ && isDisplayedOnScreen(child)) {
final long childNodeId = AccessibilityNodeInfo.makeNodeId(
child.getAccessibilityViewId(), AccessibilityNodeInfo.UNDEFINED);
AccessibilityNodeInfo info = null;
@@ -5533,7 +5550,7 @@ public final class ViewRootImpl implements ViewParent,
final int childCount = rootGroup.getChildCount();
for (int i = 0; i < childCount; i++) {
View child = rootGroup.getChildAt(i);
- if (child.getVisibility() == View.VISIBLE
+ if (isDisplayedOnScreen(child)
&& outInfos.size() < MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
final long childNodeId = AccessibilityNodeInfo.makeNodeId(
child.getAccessibilityViewId(), AccessibilityNodeInfo.UNDEFINED);
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 66bdc5d..27baaea 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -667,7 +667,7 @@ public interface WindowManagerPolicy {
/**
* Create and return an animation to re-display a force hidden window.
*/
- public Animation createForceHideEnterAnimation();
+ public Animation createForceHideEnterAnimation(boolean onWallpaper);
/**
* Called from the input reader thread before a key is enqueued.
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index 800ebc8..79bd5d3 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -147,6 +147,40 @@ class CallbackProxy extends Handler {
}
}
+ private class JsResultReceiver implements JsResult.ResultReceiver {
+ // This prevents a user from interacting with the result before WebCore is
+ // ready to handle it.
+ private boolean mReady;
+ // Tells us if the user tried to confirm or cancel the result before WebCore
+ // is ready.
+ private boolean mTriedToNotifyBeforeReady;
+
+ public JsPromptResult mJsResult = new JsPromptResult(this);
+
+ final void setReady() {
+ mReady = true;
+ if (mTriedToNotifyBeforeReady) {
+ notifyCallbackProxy();
+ }
+ }
+
+ /* Wake up the WebCore thread. */
+ @Override
+ public void onJsResultComplete(JsResult result) {
+ if (mReady) {
+ notifyCallbackProxy();
+ } else {
+ mTriedToNotifyBeforeReady = true;
+ }
+ }
+
+ private void notifyCallbackProxy() {
+ synchronized (CallbackProxy.this) {
+ CallbackProxy.this.notify();
+ }
+ }
+}
+
/**
* Construct a new CallbackProxy.
*/
@@ -531,14 +565,15 @@ class CallbackProxy extends Handler {
case JS_ALERT:
if (mWebChromeClient != null) {
- final JsResult res = (JsResult) msg.obj;
+ final JsResultReceiver receiver = (JsResultReceiver) msg.obj;
+ final JsResult res = receiver.mJsResult;
String message = msg.getData().getString("message");
String url = msg.getData().getString("url");
if (!mWebChromeClient.onJsAlert(mWebView.getWebView(), url, message,
res)) {
if (!canShowAlertDialog()) {
res.cancel();
- res.setReady();
+ receiver.setReady();
break;
}
new AlertDialog.Builder(mContext)
@@ -561,20 +596,21 @@ class CallbackProxy extends Handler {
})
.show();
}
- res.setReady();
+ receiver.setReady();
}
break;
case JS_CONFIRM:
if (mWebChromeClient != null) {
- final JsResult res = (JsResult) msg.obj;
+ final JsResultReceiver receiver = (JsResultReceiver) msg.obj;
+ final JsResult res = receiver.mJsResult;
String message = msg.getData().getString("message");
String url = msg.getData().getString("url");
if (!mWebChromeClient.onJsConfirm(mWebView.getWebView(), url, message,
res)) {
if (!canShowAlertDialog()) {
res.cancel();
- res.setReady();
+ receiver.setReady();
break;
}
new AlertDialog.Builder(mContext)
@@ -605,13 +641,14 @@ class CallbackProxy extends Handler {
}
// Tell the JsResult that it is ready for client
// interaction.
- res.setReady();
+ receiver.setReady();
}
break;
case JS_PROMPT:
if (mWebChromeClient != null) {
- final JsPromptResult res = (JsPromptResult) msg.obj;
+ final JsResultReceiver receiver = (JsResultReceiver) msg.obj;
+ final JsPromptResult res = receiver.mJsResult;
String message = msg.getData().getString("message");
String defaultVal = msg.getData().getString("default");
String url = msg.getData().getString("url");
@@ -619,7 +656,7 @@ class CallbackProxy extends Handler {
defaultVal, res)) {
if (!canShowAlertDialog()) {
res.cancel();
- res.setReady();
+ receiver.setReady();
break;
}
final LayoutInflater factory = LayoutInflater
@@ -662,20 +699,21 @@ class CallbackProxy extends Handler {
}
// Tell the JsResult that it is ready for client
// interaction.
- res.setReady();
+ receiver.setReady();
}
break;
case JS_UNLOAD:
if (mWebChromeClient != null) {
- final JsResult res = (JsResult) msg.obj;
+ final JsResultReceiver receiver = (JsResultReceiver) msg.obj;
+ final JsResult res = receiver.mJsResult;
String message = msg.getData().getString("message");
String url = msg.getData().getString("url");
if (!mWebChromeClient.onJsBeforeUnload(mWebView.getWebView(), url,
message, res)) {
if (!canShowAlertDialog()) {
res.cancel();
- res.setReady();
+ receiver.setReady();
break;
}
final String m = mContext.getString(
@@ -700,19 +738,20 @@ class CallbackProxy extends Handler {
})
.show();
}
- res.setReady();
+ receiver.setReady();
}
break;
case JS_TIMEOUT:
if(mWebChromeClient != null) {
- final JsResult res = (JsResult) msg.obj;
+ final JsResultReceiver receiver = (JsResultReceiver) msg.obj;
+ final JsResult res = receiver.mJsResult;
if(mWebChromeClient.onJsTimeout()) {
res.confirm();
} else {
res.cancel();
}
- res.setReady();
+ receiver.setReady();
}
break;
@@ -791,7 +830,8 @@ class CallbackProxy extends Handler {
case OPEN_FILE_CHOOSER:
if (mWebChromeClient != null) {
UploadFileMessageData data = (UploadFileMessageData)msg.obj;
- mWebChromeClient.openFileChooser(data.getUploadFile(), data.getAcceptType());
+ mWebChromeClient.openFileChooser(data.getUploadFile(), data.getAcceptType(),
+ data.getCapture());
}
break;
@@ -1331,7 +1371,7 @@ class CallbackProxy extends Handler {
if (mWebChromeClient == null) {
return;
}
- JsResult result = new JsResult(this, false);
+ JsResultReceiver result = new JsResultReceiver();
Message alert = obtainMessage(JS_ALERT, result);
alert.getData().putString("message", message);
alert.getData().putString("url", url);
@@ -1352,7 +1392,7 @@ class CallbackProxy extends Handler {
if (mWebChromeClient == null) {
return false;
}
- JsResult result = new JsResult(this, false);
+ JsResultReceiver result = new JsResultReceiver();
Message confirm = obtainMessage(JS_CONFIRM, result);
confirm.getData().putString("message", message);
confirm.getData().putString("url", url);
@@ -1365,7 +1405,7 @@ class CallbackProxy extends Handler {
Log.e(LOGTAG, Log.getStackTraceString(e));
}
}
- return result.getResult();
+ return result.mJsResult.getResult();
}
public String onJsPrompt(String url, String message, String defaultValue) {
@@ -1374,7 +1414,7 @@ class CallbackProxy extends Handler {
if (mWebChromeClient == null) {
return null;
}
- JsPromptResult result = new JsPromptResult(this);
+ JsResultReceiver result = new JsResultReceiver();
Message prompt = obtainMessage(JS_PROMPT, result);
prompt.getData().putString("message", message);
prompt.getData().putString("default", defaultValue);
@@ -1388,7 +1428,7 @@ class CallbackProxy extends Handler {
Log.e(LOGTAG, Log.getStackTraceString(e));
}
}
- return result.getStringResult();
+ return result.mJsResult.getStringResult();
}
public boolean onJsBeforeUnload(String url, String message) {
@@ -1397,7 +1437,7 @@ class CallbackProxy extends Handler {
if (mWebChromeClient == null) {
return true;
}
- JsResult result = new JsResult(this, true);
+ JsResultReceiver result = new JsResultReceiver();
Message confirm = obtainMessage(JS_UNLOAD, result);
confirm.getData().putString("message", message);
confirm.getData().putString("url", url);
@@ -1410,7 +1450,7 @@ class CallbackProxy extends Handler {
Log.e(LOGTAG, Log.getStackTraceString(e));
}
}
- return result.getResult();
+ return result.mJsResult.getResult();
}
/**
@@ -1540,7 +1580,7 @@ class CallbackProxy extends Handler {
if (mWebChromeClient == null) {
return true;
}
- JsResult result = new JsResult(this, true);
+ JsResultReceiver result = new JsResultReceiver();
Message timeout = obtainMessage(JS_TIMEOUT, result);
synchronized (this) {
sendMessage(timeout);
@@ -1551,7 +1591,7 @@ class CallbackProxy extends Handler {
Log.e(LOGTAG, Log.getStackTraceString(e));
}
}
- return result.getResult();
+ return result.mJsResult.getResult();
}
public void getVisitedHistory(ValueCallback<String[]> callback) {
@@ -1566,10 +1606,12 @@ class CallbackProxy extends Handler {
private static class UploadFileMessageData {
private UploadFile mCallback;
private String mAcceptType;
+ private String mCapture;
- public UploadFileMessageData(UploadFile uploadFile, String acceptType) {
+ public UploadFileMessageData(UploadFile uploadFile, String acceptType, String capture) {
mCallback = uploadFile;
mAcceptType = acceptType;
+ mCapture = capture;
}
public UploadFile getUploadFile() {
@@ -1579,6 +1621,10 @@ class CallbackProxy extends Handler {
public String getAcceptType() {
return mAcceptType;
}
+
+ public String getCapture() {
+ return mCapture;
+ }
}
private class UploadFile implements ValueCallback<Uri> {
@@ -1597,13 +1643,13 @@ class CallbackProxy extends Handler {
/**
* Called by WebViewCore to open a file chooser.
*/
- /* package */ Uri openFileChooser(String acceptType) {
+ /* package */ Uri openFileChooser(String acceptType, String capture) {
if (mWebChromeClient == null) {
return null;
}
Message myMessage = obtainMessage(OPEN_FILE_CHOOSER);
UploadFile uploadFile = new UploadFile();
- UploadFileMessageData data = new UploadFileMessageData(uploadFile, acceptType);
+ UploadFileMessageData data = new UploadFileMessageData(uploadFile, acceptType, capture);
myMessage.obj = data;
synchronized (this) {
sendMessage(myMessage);
diff --git a/core/java/android/webkit/DeviceMotionAndOrientationManager.java b/core/java/android/webkit/DeviceMotionAndOrientationManager.java
index 79b78d8..ea1e9ff 100644
--- a/core/java/android/webkit/DeviceMotionAndOrientationManager.java
+++ b/core/java/android/webkit/DeviceMotionAndOrientationManager.java
@@ -22,9 +22,8 @@ package android.webkit;
*
* This could be part of WebViewCore, but have moved it to its own class to
* avoid bloat there.
- * @hide
*/
-public final class DeviceMotionAndOrientationManager {
+final class DeviceMotionAndOrientationManager {
private WebViewCore mWebViewCore;
public DeviceMotionAndOrientationManager(WebViewCore webViewCore) {
@@ -32,12 +31,12 @@ public final class DeviceMotionAndOrientationManager {
}
/**
- * Sets whether the Page for this WebViewCore should use a mock DeviceOrientation
+ * Sets that the Page for this WebViewCore should use a mock DeviceOrientation
* client.
*/
- public void useMock() {
+ public void setUseMock() {
assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName());
- nativeUseMock(mWebViewCore);
+ nativeSetUseMock(mWebViewCore);
}
/**
@@ -66,7 +65,7 @@ public final class DeviceMotionAndOrientationManager {
}
// Native functions
- private static native void nativeUseMock(WebViewCore webViewCore);
+ private static native void nativeSetUseMock(WebViewCore webViewCore);
private static native void nativeSetMockOrientation(WebViewCore webViewCore,
boolean canProvideAlpha, double alpha, boolean canProvideBeta, double beta,
boolean canProvideGamma, double gamma);
diff --git a/core/java/android/webkit/DeviceMotionService.java b/core/java/android/webkit/DeviceMotionService.java
index b4d5759..9121429 100755
--- a/core/java/android/webkit/DeviceMotionService.java
+++ b/core/java/android/webkit/DeviceMotionService.java
@@ -153,6 +153,7 @@ final class DeviceMotionService implements SensorEventListener {
* SensorEventListener implementation.
* Callbacks happen on the thread on which we registered - the WebCore thread.
*/
+ @Override
public void onSensorChanged(SensorEvent event) {
assert(event.values.length == 3);
assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName());
@@ -170,6 +171,7 @@ final class DeviceMotionService implements SensorEventListener {
}
}
+ @Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName());
}
diff --git a/core/java/android/webkit/DeviceOrientationService.java b/core/java/android/webkit/DeviceOrientationService.java
index 47c8ab7..2e8656c 100755
--- a/core/java/android/webkit/DeviceOrientationService.java
+++ b/core/java/android/webkit/DeviceOrientationService.java
@@ -184,6 +184,7 @@ final class DeviceOrientationService implements SensorEventListener {
* SensorEventListener implementation.
* Callbacks happen on the thread on which we registered - the WebCore thread.
*/
+ @Override
public void onSensorChanged(SensorEvent event) {
assert(event.values.length == 3);
assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName());
@@ -217,6 +218,7 @@ final class DeviceOrientationService implements SensorEventListener {
}
}
+ @Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName());
}
diff --git a/core/java/android/webkit/GeolocationPermissions.java b/core/java/android/webkit/GeolocationPermissions.java
index 93eb082..1160d57 100755
--- a/core/java/android/webkit/GeolocationPermissions.java
+++ b/core/java/android/webkit/GeolocationPermissions.java
@@ -293,6 +293,16 @@ public final class GeolocationPermissions {
postMessage(Message.obtain(null, CLEAR_ALL));
}
+ /**
+ * This class should not be instantiated directly, applications must only use
+ * {@link #getInstance()} to obtain the instance.
+ * Note this constructor was erroneously public and published in SDK levels prior to 16, but
+ * applications using it would receive a non-functional instance of this class (there was no
+ * way to call createHandler() and createUIHandler(), so it would not work).
+ * @hide
+ */
+ public GeolocationPermissions() {}
+
// Native functions, run on the WebKit thread.
private static native Set nativeGetOrigins();
private static native boolean nativeGetAllowed(String origin);
diff --git a/core/java/android/webkit/JsPromptResult.java b/core/java/android/webkit/JsPromptResult.java
index 9fcd1bc..a1bf124 100644
--- a/core/java/android/webkit/JsPromptResult.java
+++ b/core/java/android/webkit/JsPromptResult.java
@@ -18,11 +18,11 @@ package android.webkit;
/**
- * Public class for handling javascript prompt requests. A
- * JsDialogHandlerInterface implentation will receive a jsPrompt call with a
- * JsPromptResult parameter. This parameter is used to return a result to
- * WebView. The client can call cancel() to cancel the dialog or confirm() with
- * the user's input to confirm the dialog.
+ * Public class for handling JavaScript prompt requests. The WebChromeClient will receive a
+ * {@link WebChromeClient#onJsPrompt(WebView, String, String, String, JsPromptResult)} call with a
+ * JsPromptResult instance as a parameter. This parameter is used to return the result of this user
+ * dialog prompt back to the WebView instance. The client can call cancel() to cancel the dialog or
+ * confirm() with the user's input to confirm the dialog.
*/
public class JsPromptResult extends JsResult {
// String result of the prompt
@@ -36,17 +36,17 @@ public class JsPromptResult extends JsResult {
confirm();
}
- /*package*/ JsPromptResult(CallbackProxy proxy) {
- super(proxy, /* unused */ false);
+ /**
+ * @hide Only for use by WebViewProvider implementations
+ */
+ public JsPromptResult(ResultReceiver receiver) {
+ super(receiver);
}
- /*package*/ String getStringResult() {
+ /**
+ * @hide Only for use by WebViewProvider implementations
+ */
+ public String getStringResult() {
return mStringResult;
}
-
- @Override
- /*package*/ void handleDefault() {
- mStringResult = null;
- super.handleDefault();
- }
}
diff --git a/core/java/android/webkit/JsResult.java b/core/java/android/webkit/JsResult.java
index e61ab21..07b686f 100644
--- a/core/java/android/webkit/JsResult.java
+++ b/core/java/android/webkit/JsResult.java
@@ -16,23 +16,27 @@
package android.webkit;
-
+/**
+ * An instance of this class is passed as a parameter in various {@link WebChromeClient} action
+ * notifications. The object is used as a handle onto the underlying JavaScript-originated request,
+ * and provides a means for the client to indicate whether this action should proceed.
+ */
public class JsResult {
- // This prevents a user from interacting with the result before WebCore is
- // ready to handle it.
- private boolean mReady;
- // Tells us if the user tried to confirm or cancel the result before WebCore
- // is ready.
- private boolean mTriedToNotifyBeforeReady;
// This is a basic result of a confirm or prompt dialog.
protected boolean mResult;
/**
- * This is the caller of the prompt and is the object that is waiting.
- * @hide
+ * Callback interface, implemented by the WebViewProvider implementation to receive
+ * notifications when the JavaScript result represented by a JsResult instance has
+ * @hide Only for use by WebViewProvider implementations
*/
- protected final CallbackProxy mProxy;
- // This is the default value of the result.
- private final boolean mDefaultValue;
+ public interface ResultReceiver {
+ public void onJsResultComplete(JsResult result);
+ }
+ /**
+ * This is the caller of the prompt and is the object that is waiting.
+ * @hide
+ */
+ protected final ResultReceiver mReceiver;
/**
* Handle the result if the user cancelled the dialog.
@@ -50,36 +54,22 @@ public class JsResult {
wakeUp();
}
- /*package*/ JsResult(CallbackProxy proxy, boolean defaultVal) {
- mProxy = proxy;
- mDefaultValue = defaultVal;
+ /**
+ * @hide Only for use by WebViewProvider implementations
+ */
+ public JsResult(ResultReceiver receiver) {
+ mReceiver = receiver;
}
- /*package*/ final boolean getResult() {
+ /**
+ * @hide Only for use by WebViewProvider implementations
+ */
+ public final boolean getResult() {
return mResult;
}
- /*package*/ final void setReady() {
- mReady = true;
- if (mTriedToNotifyBeforeReady) {
- wakeUp();
- }
- }
-
- /*package*/ void handleDefault() {
- setReady();
- mResult = mDefaultValue;
- wakeUp();
- }
-
- /* Wake up the WebCore thread. */
+ /* Notify the caller that the JsResult has completed */
protected final void wakeUp() {
- if (mReady) {
- synchronized (mProxy) {
- mProxy.notify();
- }
- } else {
- mTriedToNotifyBeforeReady = true;
- }
+ mReceiver.onJsResultComplete(this);
}
}
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index a6ef0ce..5cb0d41 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -346,9 +346,11 @@ public class WebChromeClient {
* onReceiveValue must be called to wake up the thread.a
* @param acceptType The value of the 'accept' attribute of the input tag
* associated with this file picker.
+ * @param capture The value of the 'capture' attribute of the input tag
+ * associated with this file picker.
* @hide
*/
- public void openFileChooser(ValueCallback<Uri> uploadFile, String acceptType) {
+ public void openFileChooser(ValueCallback<Uri> uploadFile, String acceptType, String capture) {
uploadFile.onReceiveValue(null);
}
diff --git a/core/java/android/webkit/WebStorage.java b/core/java/android/webkit/WebStorage.java
index 2300c2e..3745258 100644
--- a/core/java/android/webkit/WebStorage.java
+++ b/core/java/android/webkit/WebStorage.java
@@ -418,6 +418,16 @@ public final class WebStorage {
}
}
+ /**
+ * This class should not be instantiated directly, applications must only use
+ * {@link #getInstance()} to obtain the instance.
+ * Note this constructor was erroneously public and published in SDK levels prior to 16, but
+ * applications using it would receive a non-functional instance of this class (there was no
+ * way to call createHandler() and createUIHandler(), so it would not work).
+ * @hide
+ */
+ public WebStorage() {}
+
// Native functions
private static native Set nativeGetOrigins();
private static native long nativeGetUsageForOrigin(String origin);
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 84632c6..5498622 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1281,8 +1281,10 @@ public class WebView extends AbsoluteLayout
* @deprecated {@link #findAllAsync} is preferred.
* @see #setFindListener
*/
+ @Deprecated
public int findAll(String find) {
checkThread();
+ StrictMode.noteSlowCall("findAll blocks UI: prefer findAllAsync");
return mProvider.findAll(find);
}
@@ -1539,6 +1541,7 @@ public class WebView extends AbsoluteLayout
*
* @deprecated The built-in zoom mechanism is preferred, see
* {@link WebSettings#setBuiltInZoomControls(boolean)}.
+ * @hide since API version 16.
*/
@Deprecated
public View getZoomControls() {
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index 5dc2681..504788e 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -828,6 +828,13 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
// if AUTO_REDRAW_HACK is true, then the CALL key will toggle redrawing
// the screen all-the-time. Good for profiling our drawing code
static private final boolean AUTO_REDRAW_HACK = false;
+
+ // The rate at which edit text is scrolled in content pixels per millisecond
+ static private final float TEXT_SCROLL_RATE = 0.01f;
+
+ // The presumed scroll rate for the first scroll of edit text
+ static private final long TEXT_SCROLL_FIRST_SCROLL_MS = 16;
+
// true means redraw the screen all-the-time. Only with AUTO_REDRAW_HACK
private boolean mAutoRedraw;
@@ -853,6 +860,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
boolean mIsEditingText = false;
ArrayList<Message> mBatchedTextChanges = new ArrayList<Message>();
boolean mIsBatchingTextChanges = false;
+ private long mLastEditScroll = 0;
private static class OnTrimMemoryListener implements ComponentCallbacks2 {
private static OnTrimMemoryListener sInstance = null;
@@ -1037,9 +1045,6 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
// pages with the space bar, in pixels.
private static final int PAGE_SCROLL_OVERLAP = 24;
- // Time between successive calls to text scroll fling animation
- private static final int TEXT_SCROLL_ANIMATION_DELAY_MS = 16;
-
/**
* These prevent calling requestLayout if either dimension is fixed. This
* depends on the layout parameters and the measure specs.
@@ -1207,7 +1212,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
static final int RELOCATE_AUTO_COMPLETE_POPUP = 146;
static final int FOCUS_NODE_CHANGED = 147;
static final int AUTOFILL_FORM = 148;
- static final int ANIMATE_TEXT_SCROLL = 149;
+ static final int SCROLL_EDIT_TEXT = 149;
static final int EDIT_TEXT_SIZE_CHANGED = 150;
static final int SHOW_CARET_HANDLE = 151;
static final int UPDATE_CONTENT_BOUNDS = 152;
@@ -5049,8 +5054,8 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
*
* debug only
*/
- public void useMockDeviceOrientation() {
- mWebViewCore.sendMessage(EventHub.USE_MOCK_DEVICE_ORIENTATION);
+ public void setUseMockDeviceOrientation() {
+ mWebViewCore.sendMessage(EventHub.SET_USE_MOCK_DEVICE_ORIENTATION);
}
/**
@@ -6002,9 +6007,9 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
data.mNativeLayer = nativeScrollableLayer(
contentX, contentY, data.mNativeLayerRect, null);
data.mSlop = viewToContentDimension(mNavSlop);
- mTouchHighlightRegion.setEmpty();
+ removeTouchHighlight();
if (!mBlockWebkitViewMessages) {
- mTouchHighlightRequested = System.currentTimeMillis();
+ mTouchHighlightRequested = SystemClock.uptimeMillis();
mWebViewCore.sendMessageAtFrontOfQueue(
EventHub.HIT_TEST, data);
}
@@ -6091,6 +6096,11 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
mSelectDraggingTextQuad.containsPoint(handleX, handleY);
boolean inEditBounds = mEditTextContentBounds
.contains(handleX, handleY);
+ if (mIsEditingText && !inEditBounds) {
+ beginScrollEdit();
+ } else {
+ endScrollEdit();
+ }
if (inCursorText || (mIsEditingText && !inEditBounds)) {
snapDraggingCursor();
}
@@ -6240,6 +6250,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
break;
}
case MotionEvent.ACTION_UP: {
+ endScrollEdit();
if (!mConfirmMove && mIsEditingText && mSelectionStarted &&
mIsCaretSelection) {
showPasteWindow();
@@ -6335,6 +6346,86 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
}
}
+ /**
+ * Returns the text scroll speed in content pixels per millisecond based on
+ * the touch location.
+ * @param coordinate The x or y touch coordinate in content space
+ * @param min The minimum coordinate (x or y) of the edit content bounds
+ * @param max The maximum coordinate (x or y) of the edit content bounds
+ */
+ private static float getTextScrollSpeed(int coordinate, int min, int max) {
+ if (coordinate < min) {
+ return (coordinate - min) * TEXT_SCROLL_RATE;
+ } else if (coordinate >= max) {
+ return (coordinate - max + 1) * TEXT_SCROLL_RATE;
+ } else {
+ return 0.0f;
+ }
+ }
+
+ private void beginScrollEdit() {
+ if (mLastEditScroll == 0) {
+ mLastEditScroll = SystemClock.uptimeMillis() -
+ TEXT_SCROLL_FIRST_SCROLL_MS;
+ scrollEditWithCursor();
+ }
+ }
+
+ private void endScrollEdit() {
+ mLastEditScroll = 0;
+ }
+
+ private static int getTextScrollDelta(float speed, long deltaT) {
+ float distance = speed * deltaT;
+ int intDistance = (int)Math.floor(distance);
+ float probability = distance - intDistance;
+ if (Math.random() < probability) {
+ intDistance++;
+ }
+ return intDistance;
+ }
+ /**
+ * Scrolls edit text a distance based on the last touch point,
+ * the last scroll time, and the edit text content bounds.
+ */
+ private void scrollEditWithCursor() {
+ if (mLastEditScroll != 0) {
+ int x = viewToContentX(mLastTouchX + getScrollX() + mSelectDraggingOffset.x);
+ float scrollSpeedX = getTextScrollSpeed(x, mEditTextContentBounds.left,
+ mEditTextContentBounds.right);
+ int y = viewToContentY(mLastTouchY + getScrollY() + mSelectDraggingOffset.y);
+ float scrollSpeedY = getTextScrollSpeed(y, mEditTextContentBounds.top,
+ mEditTextContentBounds.bottom);
+ if (scrollSpeedX == 0.0f && scrollSpeedY == 0.0f) {
+ endScrollEdit();
+ } else {
+ long currentTime = SystemClock.uptimeMillis();
+ long timeSinceLastUpdate = currentTime - mLastEditScroll;
+ int deltaX = getTextScrollDelta(scrollSpeedX, timeSinceLastUpdate);
+ int deltaY = getTextScrollDelta(scrollSpeedY, timeSinceLastUpdate);
+ mLastEditScroll = currentTime;
+ if (deltaX == 0 && deltaY == 0) {
+ // By probability no text scroll this time. Try again later.
+ mPrivateHandler.sendEmptyMessageDelayed(SCROLL_EDIT_TEXT,
+ TEXT_SCROLL_FIRST_SCROLL_MS);
+ } else {
+ int scrollX = getTextScrollX() + deltaX;
+ scrollX = Math.min(getMaxTextScrollX(), scrollX);
+ scrollX = Math.max(0, scrollX);
+ int scrollY = getTextScrollY() + deltaY;
+ scrollY = Math.min(getMaxTextScrollY(), scrollY);
+ scrollY = Math.max(0, scrollY);
+ scrollEditText(scrollX, scrollY);
+ int cursorX = mSelectDraggingCursor.x;
+ int cursorY = mSelectDraggingCursor.y;
+ mSelectDraggingCursor.set(x - deltaX, y - deltaY);
+ updateWebkitSelection();
+ mSelectDraggingCursor.set(cursorX, cursorY);
+ }
+ }
+ }
+ }
+
private void startTouch(float x, float y, long eventTime) {
// Remember where the motion event started
mStartTouchX = mLastTouchX = Math.round(x);
@@ -7053,7 +7144,8 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
if (mFindIsUp) return false;
boolean result = false;
result = mWebViewPrivate.super_requestFocus(direction, previouslyFocusedRect);
- if (mWebViewCore.getSettings().getNeedInitialFocus() && !mWebView.isInTouchMode()) {
+ if (mWebViewCore.getSettings().getNeedInitialFocus()
+ && !mWebView.isInTouchMode()) {
// For cases such as GMail, where we gain focus from a direction,
// we want to move to the first available link.
// FIXME: If there are no visible links, we may not want to
@@ -7074,7 +7166,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
default:
return result;
}
- // TODO: Send initial focus request to webkit (b/6108927)
+ mWebViewCore.sendMessage(EventHub.SET_INITIAL_FOCUS, fakeKeyDirection);
}
return result;
}
@@ -7673,10 +7765,6 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
msg.arg1, /* unused */0);
break;
- case ANIMATE_TEXT_SCROLL:
- computeEditTextScroll();
- break;
-
case EDIT_TEXT_SIZE_CHANGED:
if (msg.arg1 == mFieldPointer) {
mEditTextContent.set((Rect)msg.obj);
@@ -7695,6 +7783,10 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
mEditTextContentBounds.set((Rect) msg.obj);
break;
+ case SCROLL_EDIT_TEXT:
+ scrollEditWithCursor();
+ break;
+
default:
super.handleMessage(msg);
break;
@@ -7777,13 +7869,16 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
if (mFocusedNode.mHasFocus && mFocusedNode.mEditable) {
return false;
}
- long delay = System.currentTimeMillis() - mTouchHighlightRequested;
+ long delay = SystemClock.uptimeMillis() - mTouchHighlightRequested;
if (delay < ViewConfiguration.getTapTimeout()) {
Rect r = mTouchHighlightRegion.getBounds();
mWebView.postInvalidateDelayed(delay, r.left, r.top, r.right, r.bottom);
return false;
}
- return true;
+ if (mInputDispatcher == null) {
+ return false;
+ }
+ return mInputDispatcher.shouldShowTapHighlight();
}
@@ -7893,8 +7988,8 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
if (viewRect.width() < getWidth() >> 1
|| viewRect.height() < getHeight() >> 1) {
mTouchHighlightRegion.union(viewRect);
- } else {
- Log.w(LOGTAG, "Skip the huge selection rect:"
+ } else if (DebugFlags.WEB_VIEW) {
+ Log.d(LOGTAG, "Skip the huge selection rect:"
+ viewRect);
}
}
@@ -7995,16 +8090,17 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
mWebView.invalidate();
}
- if (mPictureListener != null) {
- mPictureListener.onNewPicture(getWebView(), capturePicture());
- }
-
// update the zoom information based on the new picture
mZoomManager.onNewPicture(draw);
if (isPictureAfterFirstLayout) {
mViewManager.postReadyToDrawAll();
}
+ scrollEditWithCursor();
+
+ if (mPictureListener != null) {
+ mPictureListener.onNewPicture(getWebView(), capturePicture());
+ }
}
/**
@@ -8047,13 +8143,6 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
invalidate();
}
- private void computeEditTextScroll() {
- if (mEditTextScroller.computeScrollOffset()) {
- scrollEditText(mEditTextScroller.getCurrX(),
- mEditTextScroller.getCurrY());
- }
- }
-
private void scrollEditText(int scrollX, int scrollY) {
// Scrollable edit text. Scroll it.
float maxScrollX = getMaxTextScrollX();
@@ -8061,8 +8150,6 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
mEditTextContent.offsetTo(-scrollX, -scrollY);
mWebViewCore.sendMessageAtFrontOfQueue(EventHub.SCROLL_TEXT_INPUT, 0,
scrollY, (Float)scrollPercentX);
- mPrivateHandler.sendEmptyMessageDelayed(ANIMATE_TEXT_SCROLL,
- TEXT_SCROLL_ANIMATION_DELAY_MS);
}
private void beginTextBatch() {
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 6390ffe..7652417 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -394,10 +394,12 @@ public final class WebViewCore {
* Called by JNI. Open a file chooser to upload a file.
* @param acceptType The value of the 'accept' attribute of the
* input tag associated with this file picker.
+ * @param capture The value of the 'capture' attribute of the
+ * input tag associated with this file picker.
* @return String version of the URI.
*/
- private String openFileChooser(String acceptType) {
- Uri uri = mCallbackProxy.openFileChooser(acceptType);
+ private String openFileChooser(String acceptType, String capture) {
+ Uri uri = mCallbackProxy.openFileChooser(acceptType, capture);
if (uri != null) {
String filePath = "";
// Note - querying for MediaStore.Images.Media.DATA
@@ -616,9 +618,6 @@ public final class WebViewCore {
int unichar, int repeatCount, boolean isShift, boolean isAlt,
boolean isSym, boolean isDown);
- private native void nativeClick(int nativeClass, int framePtr, int nodePtr,
- boolean fake);
-
private native void nativeSendListBoxChoices(int nativeClass,
boolean[] choices, int size);
@@ -661,8 +660,6 @@ public final class WebViewCore {
int x, int y);
private native String nativeRetrieveImageSource(int nativeClass,
int x, int y);
- private native void nativeTouchUp(int nativeClass,
- int touchGeneration, int framePtr, int nodePtr, int x, int y);
private native boolean nativeMouseClick(int nativeClass);
private native boolean nativeHandleTouchEvent(int nativeClass, int action,
@@ -1073,10 +1070,8 @@ public final class WebViewCore {
static final int REPLACE_TEXT = 114;
static final int PASS_TO_JS = 115;
static final int SET_GLOBAL_BOUNDS = 116;
- static final int CLICK = 118;
static final int SET_NETWORK_STATE = 119;
static final int DOC_HAS_IMAGES = 120;
- static final int FAKE_CLICK = 121;
static final int DELETE_SELECTION = 122;
static final int LISTBOX_CHOICES = 123;
static final int SINGLE_LISTBOX_CHOICE = 124;
@@ -1145,7 +1140,7 @@ public final class WebViewCore {
// accessibility support
static final int MODIFY_SELECTION = 190;
- static final int USE_MOCK_DEVICE_ORIENTATION = 191;
+ static final int SET_USE_MOCK_DEVICE_ORIENTATION = 191;
static final int AUTOFILL_FORM = 192;
@@ -1181,6 +1176,7 @@ public final class WebViewCore {
// key was pressed (down and up)
static final int KEY_PRESS = 223;
+ static final int SET_INITIAL_FOCUS = 224;
// Private handler for WebCore messages.
private Handler mHandler;
@@ -1371,14 +1367,6 @@ public final class WebViewCore {
keyPress(msg.arg1);
break;
- case FAKE_CLICK:
- nativeClick(mNativeClass, msg.arg1, msg.arg2, true);
- break;
-
- case CLICK:
- nativeClick(mNativeClass, msg.arg1, msg.arg2, false);
- break;
-
case VIEW_SIZE_CHANGED: {
viewSizeChanged((WebViewClassic.ViewSizeData) msg.obj);
break;
@@ -1665,8 +1653,8 @@ public final class WebViewCore {
.sendToTarget();
break;
- case USE_MOCK_DEVICE_ORIENTATION:
- useMockDeviceOrientation();
+ case SET_USE_MOCK_DEVICE_ORIENTATION:
+ setUseMockDeviceOrientation();
break;
case AUTOFILL_FORM:
@@ -1761,6 +1749,9 @@ public final class WebViewCore {
WebViewClassic.UPDATE_MATCH_COUNT, request).sendToTarget();
break;
}
+ case SET_INITIAL_FOCUS:
+ nativeSetInitialFocus(mNativeClass, msg.arg1);
+ break;
}
}
};
@@ -3008,8 +2999,8 @@ public final class WebViewCore {
// TODO: Figure out what to do with this (b/6111818)
}
- private void useMockDeviceOrientation() {
- mDeviceMotionAndOrientationManager.useMock();
+ private void setUseMockDeviceOrientation() {
+ mDeviceMotionAndOrientationManager.setUseMock();
}
public void setMockDeviceOrientation(boolean canProvideAlpha, double alpha,
@@ -3084,6 +3075,7 @@ public final class WebViewCore {
private native void nativeClearTextSelection(int nativeClass);
private native boolean nativeSelectWordAt(int nativeClass, int x, int y);
private native void nativeSelectAll(int nativeClass);
+ private native void nativeSetInitialFocus(int nativeClass, int keyDirection);
private static native void nativeCertTrustChanged();
}
diff --git a/core/java/android/webkit/WebViewInputDispatcher.java b/core/java/android/webkit/WebViewInputDispatcher.java
index e7024d9..0a0afaa 100644
--- a/core/java/android/webkit/WebViewInputDispatcher.java
+++ b/core/java/android/webkit/WebViewInputDispatcher.java
@@ -269,9 +269,8 @@ final class WebViewInputDispatcher {
*/
public boolean postPointerEvent(MotionEvent event,
int webKitXOffset, int webKitYOffset, float webKitScale) {
- if (event == null
- || (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
- throw new IllegalArgumentException("event must be a pointer event");
+ if (event == null) {
+ throw new IllegalArgumentException("event cannot be null");
}
if (DEBUG) {
@@ -349,6 +348,12 @@ final class WebViewInputDispatcher {
}
}
+ public boolean shouldShowTapHighlight() {
+ synchronized (mLock) {
+ return mPostLongPressScheduled || mPostClickScheduled;
+ }
+ }
+
private void postLongPress() {
synchronized (mLock) {
if (!mPostLongPressScheduled) {
diff --git a/core/java/android/widget/CheckBox.java b/core/java/android/widget/CheckBox.java
index 0685eea..858c415 100644
--- a/core/java/android/widget/CheckBox.java
+++ b/core/java/android/widget/CheckBox.java
@@ -21,8 +21,6 @@ import android.util.AttributeSet;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
-import com.android.internal.R;
-
/**
* <p>
@@ -71,16 +69,6 @@ public class CheckBox extends CompoundButton {
}
@Override
- public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
- super.onPopulateAccessibilityEvent(event);
- if (isChecked()) {
- event.getText().add(mContext.getString(R.string.checkbox_checked));
- } else {
- event.getText().add(mContext.getString(R.string.checkbox_not_checked));
- }
- }
-
- @Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
event.setClassName(CheckBox.class.getName());
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index d897a39..b2321d9 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -579,7 +579,7 @@ public class NumberPicker extends LinearLayout {
throw new IllegalArgumentException("minWidth > maxWidth");
}
- mComputeMaxWidth = (mMaxWidth == Integer.MAX_VALUE);
+ mComputeMaxWidth = (mMaxWidth == SIZE_UNSPECIFIED);
attributesArray.recycle();
@@ -771,6 +771,8 @@ public class NumberPicker extends LinearLayout {
mLastDownEventTime = event.getEventTime();
mIngonreMoveEvents = false;
mShowSoftInputOnTap = false;
+ // Make sure we wupport flinging inside scrollables.
+ getParent().requestDisallowInterceptTouchEvent(true);
if (!mFlingScroller.isFinished()) {
mFlingScroller.forceFinished(true);
mAdjustScroller.forceFinished(true);
@@ -1096,12 +1098,7 @@ public class NumberPicker extends LinearLayout {
* @see #setMaxValue(int)
*/
public void setValue(int value) {
- if (mValue == value) {
- return;
- }
setValueInternal(value, false);
- initializeSelectorWheelIndices();
- invalidate();
}
/**
@@ -1498,6 +1495,8 @@ public class NumberPicker extends LinearLayout {
if (notifyChange) {
notifyChange(previous, current);
}
+ initializeSelectorWheelIndices();
+ invalidate();
}
/**
diff --git a/core/java/android/widget/ShareActionProvider.java b/core/java/android/widget/ShareActionProvider.java
index 22e9ef1..080b87d 100644
--- a/core/java/android/widget/ShareActionProvider.java
+++ b/core/java/android/widget/ShareActionProvider.java
@@ -80,16 +80,22 @@ public class ShareActionProvider extends ActionProvider {
/**
* Called when a share target has been selected. The client can
- * decide whether to handle the intent or rely on the default
- * behavior which is launching it.
+ * decide whether to perform some action before the sharing is
+ * actually performed.
* <p>
* <strong>Note:</strong> Modifying the intent is not permitted and
* any changes to the latter will be ignored.
* </p>
+ * <p>
+ * <strong>Note:</strong> You should <strong>not</strong> handle the
+ * intent here. This callback aims to notify the client that a
+ * sharing is being performed, so the client can update the UI
+ * if necessary.
+ * </p>
*
* @param source The source of the notification.
* @param intent The intent for launching the chosen share target.
- * @return Whether the client has handled the intent.
+ * @return The return result is ignored. Always return false for consistency.
*/
public boolean onShareTargetSelected(ShareActionProvider source, Intent intent);
}
@@ -308,7 +314,7 @@ public class ShareActionProvider extends ActionProvider {
@Override
public boolean onChooseActivity(ActivityChooserModel host, Intent intent) {
if (mOnShareTargetSelectedListener != null) {
- return mOnShareTargetSelectedListener.onShareTargetSelected(
+ mOnShareTargetSelectedListener.onShareTargetSelected(
ShareActionProvider.this, intent);
}
return false;
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index aef8a34..36d1ee0 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -907,7 +907,7 @@ public class Spinner extends AbsSpinner implements OnClickListener {
public void onItemClick(AdapterView parent, View v, int position, long id) {
Spinner.this.setSelection(position);
if (mOnItemClickListener != null) {
- Spinner.this.performItemClick(null, position, mAdapter.getItemId(position));
+ Spinner.this.performItemClick(v, position, mAdapter.getItemId(position));
}
dismiss();
}
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index a897cc3..0786909 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -806,5 +806,16 @@ public class Switch extends CompoundButton {
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(Switch.class.getName());
+ CharSequence switchText = isChecked() ? mTextOn : mTextOff;
+ if (!TextUtils.isEmpty(switchText)) {
+ CharSequence oldText = info.getText();
+ if (TextUtils.isEmpty(oldText)) {
+ info.setText(switchText);
+ } else {
+ StringBuilder newText = new StringBuilder();
+ newText.append(oldText).append(' ').append(switchText);
+ info.setText(newText);
+ }
+ }
}
}
diff --git a/core/java/com/android/internal/util/IndentingPrintWriter.java b/core/java/com/android/internal/util/IndentingPrintWriter.java
index 3dd2284..699e9b3 100644
--- a/core/java/com/android/internal/util/IndentingPrintWriter.java
+++ b/core/java/com/android/internal/util/IndentingPrintWriter.java
@@ -46,6 +46,10 @@ public class IndentingPrintWriter extends PrintWriter {
mCurrent = mBuilder.toString();
}
+ public void printPair(String key, Object value) {
+ print(key + "=" + String.valueOf(value) + " ");
+ }
+
@Override
public void println() {
super.println();
diff --git a/core/java/com/android/internal/widget/PointerLocationView.java b/core/java/com/android/internal/widget/PointerLocationView.java
index 0524c25..1d6af90 100644
--- a/core/java/com/android/internal/widget/PointerLocationView.java
+++ b/core/java/com/android/internal/widget/PointerLocationView.java
@@ -21,6 +21,8 @@ import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Paint.FontMetricsInt;
+import android.hardware.input.InputManager;
+import android.hardware.input.InputManager.InputDeviceListener;
import android.util.Log;
import android.view.InputDevice;
import android.view.KeyEvent;
@@ -32,7 +34,7 @@ import android.view.MotionEvent.PointerCoords;
import java.util.ArrayList;
-public class PointerLocationView extends View {
+public class PointerLocationView extends View implements InputDeviceListener {
private static final String TAG = "Pointer";
public static class PointerState {
@@ -82,6 +84,8 @@ public class PointerLocationView extends View {
private final int ESTIMATE_FUTURE_POINTS = 2;
private final float ESTIMATE_INTERVAL = 0.02f;
+ private final InputManager mIm;
+
private final ViewConfiguration mVC;
private final Paint mTextPaint;
private final Paint mTextBackgroundPaint;
@@ -108,6 +112,8 @@ public class PointerLocationView extends View {
super(c);
setFocusableInTouchMode(true);
+ mIm = (InputManager)c.getSystemService(Context.INPUT_SERVICE);
+
mVC = ViewConfiguration.get(c);
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
@@ -139,18 +145,6 @@ public class PointerLocationView extends View {
mActivePointerId = 0;
mVelocity = VelocityTracker.obtain();
-
- logInputDeviceCapabilities();
- }
-
- private void logInputDeviceCapabilities() {
- int[] deviceIds = InputDevice.getDeviceIds();
- for (int i = 0; i < deviceIds.length; i++) {
- InputDevice device = InputDevice.getDevice(deviceIds[i]);
- if (device != null) {
- Log.i(TAG, device.toString());
- }
- }
}
public void setPrintCoords(boolean state) {
@@ -631,7 +625,53 @@ public class PointerLocationView extends View {
logMotionEvent("Trackball", event);
return true;
}
-
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+
+ mIm.registerInputDeviceListener(this, getHandler());
+ logInputDevices();
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+
+ mIm.unregisterInputDeviceListener(this);
+ }
+
+ @Override
+ public void onInputDeviceAdded(int deviceId) {
+ logInputDeviceState(deviceId, "Device Added");
+ }
+
+ @Override
+ public void onInputDeviceChanged(int deviceId) {
+ logInputDeviceState(deviceId, "Device Changed");
+ }
+
+ @Override
+ public void onInputDeviceRemoved(int deviceId) {
+ logInputDeviceState(deviceId, "Device Removed");
+ }
+
+ private void logInputDevices() {
+ int[] deviceIds = InputDevice.getDeviceIds();
+ for (int i = 0; i < deviceIds.length; i++) {
+ logInputDeviceState(deviceIds[i], "Device Enumerated");
+ }
+ }
+
+ private void logInputDeviceState(int deviceId, String state) {
+ InputDevice device = mIm.getInputDevice(deviceId);
+ if (device != null) {
+ Log.i(TAG, state + ": " + device);
+ } else {
+ Log.i(TAG, state + ": " + deviceId);
+ }
+ }
+
// HACK
// A quick and dirty string builder implementation optimized for GC.
// Using String.format causes the application grind to a halt when
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 879b9d2..b877071 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -549,6 +549,10 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
opt.optionString = heapsizeOptsBuf;
mOptions.add(opt);
+ // Increase the main thread's interpreter stack size for bug 6315322.
+ opt.optionString = "-XX:mainThreadStackSize=24K";
+ mOptions.add(opt);
+
strcpy(heapgrowthlimitOptsBuf, "-XX:HeapGrowthLimit=");
property_get("dalvik.vm.heapgrowthlimit", heapgrowthlimitOptsBuf+20, "");
if (heapgrowthlimitOptsBuf[20] != '\0') {
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 376c841..a65262c 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -254,6 +254,13 @@ public:
obj->setTextAlign(align);
}
+ static void setTextLocale(JNIEnv* env, jobject clazz, SkPaint* obj, jstring locale) {
+ const char* localeArray = env->GetStringUTFChars(locale, NULL);
+ SkString skLocale(localeArray);
+ obj->setTextLocale(skLocale);
+ env->ReleaseStringUTFChars(locale, localeArray);
+ }
+
static jfloat getTextSize(JNIEnv* env, jobject paint) {
NPE_CHECK_RETURN_ZERO(env, paint);
return SkScalarToFloat(GraphicsJNI::getNativePaint(env, paint)->getTextSize());
@@ -817,6 +824,7 @@ static JNINativeMethod methods[] = {
{"native_setRasterizer","(II)I", (void*) SkPaintGlue::setRasterizer},
{"native_getTextAlign","(I)I", (void*) SkPaintGlue::getTextAlign},
{"native_setTextAlign","(II)V", (void*) SkPaintGlue::setTextAlign},
+ {"native_setTextLocale","(ILjava/lang/String;)V", (void*) SkPaintGlue::setTextLocale},
{"getTextSize","()F", (void*) SkPaintGlue::getTextSize},
{"setTextSize","(F)V", (void*) SkPaintGlue::setTextSize},
{"getTextScaleX","()F", (void*) SkPaintGlue::getTextScaleX},
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index a7abbfa..a97c710 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -29,10 +29,7 @@ extern "C" {
namespace android {
//--------------------------------------------------------------------------------------------------
-// Using DroidSansArabic for shaping Arabic with Harfbuzz because its metrics are more compatible
-// with the "Roboto" metrics (compared to DroidNaskh-Regular). When we will have an Arabic font
-// whose metrics are similar to the Roboto ones, then we will need to use it for shaping.
-#define TYPEFACE_ARABIC "/system/fonts/DroidSansArabic.ttf"
+#define TYPEFACE_ARABIC "/system/fonts/DroidNaskh-Regular-Shift.ttf"
#define TYPE_FACE_HEBREW_REGULAR "/system/fonts/DroidSansHebrew-Regular.ttf"
#define TYPE_FACE_HEBREW_BOLD "/system/fonts/DroidSansHebrew-Bold.ttf"
#define TYPEFACE_BENGALI "/system/fonts/Lohit-Bengali.ttf"
diff --git a/core/jni/android_net_wifi_Wifi.cpp b/core/jni/android_net_wifi_Wifi.cpp
index c5ff16e..e7c4c23 100644
--- a/core/jni/android_net_wifi_Wifi.cpp
+++ b/core/jni/android_net_wifi_Wifi.cpp
@@ -27,6 +27,7 @@
#define WIFI_PKG_NAME "android/net/wifi/WifiNative"
#define BUF_SIZE 256
+#define EVENT_BUF_SIZE 2048
namespace android {
@@ -140,7 +141,7 @@ static void android_net_wifi_closeSupplicantConnection(JNIEnv* env, jobject, jst
static jstring android_net_wifi_waitForEvent(JNIEnv* env, jobject, jstring jIface)
{
- char buf[BUF_SIZE];
+ char buf[EVENT_BUF_SIZE];
ScopedUtfChars ifname(env, jIface);
int nread = ::wifi_wait_for_event(ifname.c_str(), buf, sizeof buf);
if (nread > 0) {
diff --git a/core/jni/android_view_InputDevice.cpp b/core/jni/android_view_InputDevice.cpp
index d7d476a..e8a3a3b 100644
--- a/core/jni/android_view_InputDevice.cpp
+++ b/core/jni/android_view_InputDevice.cpp
@@ -54,8 +54,9 @@ jobject android_view_InputDevice_create(JNIEnv* env, const InputDeviceInfo& devi
}
ScopedLocalRef<jobject> inputDeviceObj(env, env->NewObject(gInputDeviceClassInfo.clazz,
- gInputDeviceClassInfo.ctor, deviceInfo.getId(), nameObj.get(),
- descriptorObj.get(), deviceInfo.getSources(), deviceInfo.getKeyboardType(),
+ gInputDeviceClassInfo.ctor, deviceInfo.getId(), deviceInfo.getGeneration(),
+ nameObj.get(), descriptorObj.get(),
+ deviceInfo.getSources(), deviceInfo.getKeyboardType(),
kcmObj.get()));
const Vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
@@ -86,7 +87,7 @@ int register_android_view_InputDevice(JNIEnv* env)
gInputDeviceClassInfo.clazz = jclass(env->NewGlobalRef(gInputDeviceClassInfo.clazz));
GET_METHOD_ID(gInputDeviceClassInfo.ctor, gInputDeviceClassInfo.clazz,
- "<init>", "(ILjava/lang/String;Ljava/lang/String;IILandroid/view/KeyCharacterMap;)V");
+ "<init>", "(IILjava/lang/String;Ljava/lang/String;IILandroid/view/KeyCharacterMap;)V");
GET_METHOD_ID(gInputDeviceClassInfo.addMotionRange, gInputDeviceClassInfo.clazz,
"addMotionRange", "(IIFFFF)V");
diff --git a/core/res/res/anim/lock_screen_behind_enter.xml b/core/res/res/anim/lock_screen_behind_enter.xml
index 4f58be4..6b06456 100644
--- a/core/res/res/anim/lock_screen_behind_enter.xml
+++ b/core/res/res/anim/lock_screen_behind_enter.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
-** Copyright 2007, The Android Open Source Project
+** Copyright 2012, 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.
@@ -18,7 +18,7 @@
-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:detachWallpaper="true" android:shareInterpolator="false">
+ android:background="#ff000000" android:shareInterpolator="false">
<scale
android:fromXScale="0.95" android:toXScale="1.0"
android:fromYScale="0.95" android:toYScale="1.0"
diff --git a/core/res/res/anim/lock_screen_wallpaper_behind_enter.xml b/core/res/res/anim/lock_screen_wallpaper_behind_enter.xml
new file mode 100644
index 0000000..a354fae
--- /dev/null
+++ b/core/res/res/anim/lock_screen_wallpaper_behind_enter.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:detachWallpaper="true" android:shareInterpolator="false">
+ <scale
+ android:fromXScale="0.95" android:toXScale="1.0"
+ android:fromYScale="0.95" android:toYScale="1.0"
+ android:pivotX="50%p" android:pivotY="50%p"
+ android:fillEnabled="true" android:fillBefore="true"
+ android:interpolator="@interpolator/decelerate_cubic"
+ android:startOffset="@android:integer/config_shortAnimTime"
+ android:duration="@android:integer/config_shortAnimTime" />
+ <alpha
+ android:fromAlpha="0.0" android:toAlpha="1.0"
+ android:fillEnabled="true" android:fillBefore="true"
+ android:interpolator="@interpolator/decelerate_quad"
+ android:startOffset="@android:integer/config_shortAnimTime"
+ android:duration="@android:integer/config_shortAnimTime"/>
+</set>
diff --git a/core/res/res/anim/screen_rotate_180_enter.xml b/core/res/res/anim/screen_rotate_180_enter.xml
index e2f3ce2..688a8d5 100644
--- a/core/res/res/anim/screen_rotate_180_enter.xml
+++ b/core/res/res/anim/screen_rotate_180_enter.xml
@@ -24,5 +24,5 @@
android:interpolator="@interpolator/decelerate_quint"
android:fillEnabled="true"
android:fillBefore="true" android:fillAfter="true"
- android:duration="@android:integer/config_longAnimTime" />
+ android:duration="@android:integer/config_mediumAnimTime" />
</set>
diff --git a/core/res/res/anim/screen_rotate_180_exit.xml b/core/res/res/anim/screen_rotate_180_exit.xml
index fe4a950..1eb6361 100644
--- a/core/res/res/anim/screen_rotate_180_exit.xml
+++ b/core/res/res/anim/screen_rotate_180_exit.xml
@@ -24,5 +24,8 @@
android:interpolator="@interpolator/decelerate_quint"
android:fillEnabled="true"
android:fillBefore="true" android:fillAfter="true"
- android:duration="@android:integer/config_longAnimTime" />
+ android:duration="@android:integer/config_mediumAnimTime" />
+ <alpha android:fromAlpha="1.0" android:toAlpha="0"
+ android:interpolator="@interpolator/decelerate_cubic"
+ android:duration="@android:integer/config_mediumAnimTime"/>
</set> \ No newline at end of file
diff --git a/core/res/res/anim/screen_rotate_180_frame.xml b/core/res/res/anim/screen_rotate_180_frame.xml
index 1a3ee67..19dade1 100644
--- a/core/res/res/anim/screen_rotate_180_frame.xml
+++ b/core/res/res/anim/screen_rotate_180_frame.xml
@@ -24,5 +24,5 @@
android:interpolator="@interpolator/decelerate_quint"
android:fillEnabled="true"
android:fillBefore="true" android:fillAfter="true"
- android:duration="@android:integer/config_longAnimTime" />
+ android:duration="@android:integer/config_mediumAnimTime" />
</set>
diff --git a/core/res/res/anim/screen_rotate_minus_90_enter.xml b/core/res/res/anim/screen_rotate_minus_90_enter.xml
index 38a674d..b16d5fc 100644
--- a/core/res/res/anim/screen_rotate_minus_90_enter.xml
+++ b/core/res/res/anim/screen_rotate_minus_90_enter.xml
@@ -19,10 +19,18 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
+ <!-- Version for two-phase anim
<rotate android:fromDegrees="-90" android:toDegrees="0"
android:pivotX="50%" android:pivotY="50%"
android:interpolator="@interpolator/decelerate_quint"
android:fillEnabled="true"
android:fillBefore="true" android:fillAfter="true"
android:duration="@android:integer/config_longAnimTime" />
+ -->
+ <rotate android:fromDegrees="-90" android:toDegrees="0"
+ android:pivotX="50%" android:pivotY="50%"
+ android:fillEnabled="true"
+ android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@interpolator/decelerate_quint"
+ android:duration="@android:integer/config_mediumAnimTime" />
</set>
diff --git a/core/res/res/anim/screen_rotate_minus_90_exit.xml b/core/res/res/anim/screen_rotate_minus_90_exit.xml
index a75aca7..9b38939 100644
--- a/core/res/res/anim/screen_rotate_minus_90_exit.xml
+++ b/core/res/res/anim/screen_rotate_minus_90_exit.xml
@@ -19,10 +19,30 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
+ <!-- Version for two-phase animation
<rotate android:fromDegrees="0" android:toDegrees="90"
android:pivotX="50%" android:pivotY="50%"
android:interpolator="@interpolator/decelerate_quint"
android:fillEnabled="true"
android:fillBefore="true" android:fillAfter="true"
android:duration="@android:integer/config_longAnimTime" />
+ -->
+ <scale android:fromXScale="100%" android:toXScale="100%p"
+ android:fromYScale="100%" android:toYScale="100%p"
+ android:pivotX="50%" android:pivotY="50%"
+ android:interpolator="@interpolator/decelerate_quint"
+ android:fillEnabled="true"
+ android:fillBefore="true" android:fillAfter="true"
+ android:duration="@android:integer/config_mediumAnimTime" />
+ <rotate android:fromDegrees="0" android:toDegrees="90"
+ android:pivotX="50%" android:pivotY="50%"
+ android:interpolator="@interpolator/decelerate_quint"
+ android:fillEnabled="true"
+ android:fillBefore="true" android:fillAfter="true"
+ android:duration="@android:integer/config_mediumAnimTime" />
+ <alpha android:fromAlpha="1.0" android:toAlpha="0"
+ android:interpolator="@interpolator/decelerate_quint"
+ android:fillEnabled="true"
+ android:fillBefore="true" android:fillAfter="true"
+ android:duration="@android:integer/config_mediumAnimTime" />
</set>
diff --git a/core/res/res/anim/screen_rotate_plus_90_enter.xml b/core/res/res/anim/screen_rotate_plus_90_enter.xml
index 583d2ba..86a8d24 100644
--- a/core/res/res/anim/screen_rotate_plus_90_enter.xml
+++ b/core/res/res/anim/screen_rotate_plus_90_enter.xml
@@ -19,10 +19,18 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
+ <!-- Version for two-phase animation
<rotate android:fromDegrees="90" android:toDegrees="0"
android:pivotX="50%" android:pivotY="50%"
android:interpolator="@interpolator/decelerate_quint"
android:fillEnabled="true"
android:fillBefore="true" android:fillAfter="true"
android:duration="@android:integer/config_longAnimTime" />
+ -->
+ <rotate android:fromDegrees="90" android:toDegrees="0"
+ android:pivotX="50%" android:pivotY="50%"
+ android:interpolator="@interpolator/decelerate_quint"
+ android:fillEnabled="true"
+ android:fillBefore="true" android:fillAfter="true"
+ android:duration="@android:integer/config_mediumAnimTime" />
</set>
diff --git a/core/res/res/anim/screen_rotate_plus_90_exit.xml b/core/res/res/anim/screen_rotate_plus_90_exit.xml
index a2bef41..fa34533 100644
--- a/core/res/res/anim/screen_rotate_plus_90_exit.xml
+++ b/core/res/res/anim/screen_rotate_plus_90_exit.xml
@@ -19,10 +19,30 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
+ <!-- Version for two-phase animation
<rotate android:fromDegrees="0" android:toDegrees="-90"
android:pivotX="50%" android:pivotY="50%"
android:interpolator="@interpolator/decelerate_quint"
android:fillEnabled="true"
android:fillBefore="true" android:fillAfter="true"
android:duration="@android:integer/config_longAnimTime" />
+ -->
+ <scale android:fromXScale="100%" android:toXScale="100%p"
+ android:fromYScale="100%" android:toYScale="100%p"
+ android:pivotX="50%" android:pivotY="50%"
+ android:interpolator="@interpolator/decelerate_quint"
+ android:fillEnabled="true"
+ android:fillBefore="true" android:fillAfter="true"
+ android:duration="@android:integer/config_mediumAnimTime" />
+ <rotate android:fromDegrees="0" android:toDegrees="-90"
+ android:pivotX="50%" android:pivotY="50%"
+ android:interpolator="@interpolator/decelerate_quint"
+ android:fillEnabled="true"
+ android:fillBefore="true" android:fillAfter="true"
+ android:duration="@android:integer/config_mediumAnimTime" />
+ <alpha android:fromAlpha="1.0" android:toAlpha="0"
+ android:interpolator="@interpolator/decelerate_quint"
+ android:fillEnabled="true"
+ android:fillBefore="true" android:fillAfter="true"
+ android:duration="@android:integer/config_mediumAnimTime" />
</set>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index aaef701..2006548 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -400,8 +400,6 @@
<java-symbol type="string" name="cfTemplateNotForwarded" />
<java-symbol type="string" name="cfTemplateRegistered" />
<java-symbol type="string" name="cfTemplateRegisteredTime" />
- <java-symbol type="string" name="checkbox_checked" />
- <java-symbol type="string" name="checkbox_not_checked" />
<java-symbol type="string" name="chooseActivity" />
<java-symbol type="string" name="config_default_dns_server" />
<java-symbol type="string" name="config_ethernet_iface_regex" />
@@ -701,8 +699,6 @@
<java-symbol type="string" name="preposition_for_time" />
<java-symbol type="string" name="progress_erasing" />
<java-symbol type="string" name="progress_unmounting" />
- <java-symbol type="string" name="radiobutton_not_selected" />
- <java-symbol type="string" name="radiobutton_selected" />
<java-symbol type="string" name="relationTypeAssistant" />
<java-symbol type="string" name="relationTypeBrother" />
<java-symbol type="string" name="relationTypeChild" />
@@ -791,14 +787,18 @@
<java-symbol type="string" name="sipAddressTypeHome" />
<java-symbol type="string" name="sipAddressTypeOther" />
<java-symbol type="string" name="sipAddressTypeWork" />
- <java-symbol type="string" name="sms_control_default_app_name" />
<java-symbol type="string" name="sms_control_message" />
- <java-symbol type="string" name="sms_control_no" />
<java-symbol type="string" name="sms_control_title" />
+ <java-symbol type="string" name="sms_control_no" />
<java-symbol type="string" name="sms_control_yes" />
+ <java-symbol type="string" name="sms_premium_short_code_confirm_message" />
+ <java-symbol type="string" name="sms_premium_short_code_confirm_title" />
+ <java-symbol type="string" name="sms_short_code_confirm_allow" />
+ <java-symbol type="string" name="sms_short_code_confirm_deny" />
+ <java-symbol type="string" name="sms_short_code_confirm_message" />
+ <java-symbol type="string" name="sms_short_code_confirm_report" />
+ <java-symbol type="string" name="sms_short_code_confirm_title" />
<java-symbol type="string" name="submit" />
- <java-symbol type="string" name="switch_off" />
- <java-symbol type="string" name="switch_on" />
<java-symbol type="string" name="sync_binding_label" />
<java-symbol type="string" name="sync_do_nothing" />
<java-symbol type="string" name="sync_really_delete" />
@@ -820,8 +820,6 @@
<java-symbol type="string" name="time_wday" />
<java-symbol type="string" name="time_wday_date" />
<java-symbol type="string" name="today" />
- <java-symbol type="string" name="togglebutton_not_pressed" />
- <java-symbol type="string" name="togglebutton_pressed" />
<java-symbol type="string" name="tomorrow" />
<java-symbol type="string" name="twelve_hour_time_format" />
<java-symbol type="string" name="twenty_four_hour_time_format" />
@@ -1103,6 +1101,7 @@
<java-symbol type="xml" name="password_kbd_symbols_shift" />
<java-symbol type="xml" name="power_profile" />
<java-symbol type="xml" name="time_zones_by_country" />
+ <java-symbol type="xml" name="sms_short_codes" />
<java-symbol type="raw" name="incognito_mode_start_page" />
<java-symbol type="raw" name="loaderror" />
@@ -1133,6 +1132,7 @@
<!-- From android.policy -->
<java-symbol type="anim" name="app_starting_exit" />
<java-symbol type="anim" name="lock_screen_behind_enter" />
+ <java-symbol type="anim" name="lock_screen_wallpaper_behind_enter" />
<java-symbol type="anim" name="dock_top_enter" />
<java-symbol type="anim" name="dock_top_exit" />
<java-symbol type="anim" name="dock_bottom_enter" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 0eb46bd..e00986c 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2789,16 +2789,30 @@
<string name="select_character">Insert character</string>
<!-- SMS per-application rate control Dialog --> <skip />
- <!-- See SMS_DIALOG. This is shown if the current application's name cannot be figuerd out. -->
- <string name="sms_control_default_app_name">Unknown app</string>
<!-- SMS_DIALOG: An SMS dialog is shown if an application tries to send too many SMSes. This is the title of that dialog. -->
<string name="sms_control_title">Sending SMS messages</string>
- <!-- See SMS_DIALOG. This is the message shown in that dialog. -->
- <string name="sms_control_message">A large number of SMS messages are being sent. Touch OK to continue, or Cancel to stop sending.</string>
- <!-- See SMS_DIALOG. This is a button choice to allow sending the SMSes. -->
- <string name="sms_control_yes">OK</string>
- <!-- See SMS_DIALOG. This is a button choice to disallow sending the SMSes.. -->
- <string name="sms_control_no">Cancel</string>
+ <!-- See SMS_DIALOG. This is the message shown in that dialog. [CHAR LIMIT=NONE] -->
+ <string name="sms_control_message">&lt;b><xliff:g id="app_name">%1$s</xliff:g>&lt;/b> is sending a large number of SMS messages. Do you want to allow this app to continue sending messages?</string>
+ <!-- See SMS_DIALOG. This is a button choice to allow sending the SMSes. [CHAR LIMIT=30] -->
+ <string name="sms_control_yes">Allow</string>
+ <!-- See SMS_DIALOG. This is a button choice to disallow sending the SMSes. [CHAR LIMIT=30] -->
+ <string name="sms_control_no">Deny</string>
+
+ <!-- SMS short code verification dialog. --> <skip />
+ <!-- The dialog title for the SMS short code confirmation dialog. [CHAR LIMIT=30] -->
+ <string name="sms_short_code_confirm_title">Send SMS to short code?</string>
+ <!-- The dialog title for the SMS premium short code confirmation dialog. [CHAR LIMIT=30] -->
+ <string name="sms_premium_short_code_confirm_title">Send premium SMS?</string>
+ <!-- The message text for the SMS short code confirmation dialog. [CHAR LIMIT=NONE] -->
+ <string name="sms_short_code_confirm_message">&lt;b><xliff:g id="app_name">%1$s</xliff:g>&lt;/b> would like to send a text message to &lt;b><xliff:g id="dest_address">%2$s</xliff:g>&lt;/b>, which appears to be an SMS short code.&lt;p>Sending text messages to some short codes may cause your mobile account to be billed for premium services.&lt;p>Do you want to allow this app to send the message?</string>
+ <!-- The message text for the SMS short code confirmation dialog. [CHAR LIMIT=NONE] -->
+ <string name="sms_premium_short_code_confirm_message">&lt;b><xliff:g id="app_name">%1$s</xliff:g>&lt;/b> would like to send a text message to &lt;b><xliff:g id="dest_address">%2$s</xliff:g>&lt;/b>, which is a premium SMS short code.&lt;p>&lt;b>Sending a message to this destination will cause your mobile account to be billed for premium services.&lt;/b>&lt;p>Do you want to allow this app to send the message?</string>
+ <!-- Text of the approval button for the SMS short code confirmation dialog. [CHAR LIMIT=50] -->
+ <string name="sms_short_code_confirm_allow">Send message</string>
+ <!-- Text of the cancel button for the SMS short code confirmation dialog. [CHAR LIMIT=30] -->
+ <string name="sms_short_code_confirm_deny">Don\'t send</string>
+ <!-- Text of the button for the SMS short code confirmation dialog to report a malicious app. [CHAR LIMIT=30] -->
+ <string name="sms_short_code_confirm_report">Report malicious app</string>
<!-- SIM swap and device reboot Dialog --> <skip />
<!-- See SIM_REMOVED_DIALOG. This is the title of that dialog. -->
@@ -3241,30 +3255,6 @@
<!-- Description of the button to decrease the DatePicker's year value. [CHAR LIMIT=NONE] -->
<string name="date_picker_decrement_year_button">Decrease year</string>
- <!-- CheckBox - accessibility support -->
- <!-- Description of the checked state of a CheckBox. [CHAR LIMIT=NONE] -->
- <string name="checkbox_checked">checked</string>
- <!-- Description of the not checked state of a CheckBox. [CHAR LIMIT=NONE] -->
- <string name="checkbox_not_checked">not checked</string>
-
- <!-- RadioButton/CheckedTextView - accessibility support -->
- <!-- Description of the selected state of a RadioButton. [CHAR LIMIT=NONE] -->
- <string name="radiobutton_selected">selected</string>
- <!-- Description of the not selected state of a RadioButton. [CHAR LIMIT=NONE] -->
- <string name="radiobutton_not_selected">not selected</string>
-
- <!-- Switch - accessibility support -->
- <!-- Description of the on state of a Switch. [CHAR LIMIT=NONE] -->
- <string name="switch_on">on</string>
- <!-- Description of the off state of a Switch. [CHAR LIMIT=NONE] -->
- <string name="switch_off">off</string>
-
- <!-- ToggleButton - accessibility support -->
- <!-- Description of the pressed state of a ToggleButton. [CHAR LIMIT=NONE] -->
- <string name="togglebutton_pressed">pressed</string>
- <!-- Description of the not pressed state of a ToggleButton. [CHAR LIMIT=NONE] -->
- <string name="togglebutton_not_pressed">not pressed</string>
-
<!-- KeyboardView - accessibility support -->
<!-- Description of the Alt button in a KeyboardView. [CHAR LIMIT=NONE] -->
<string name="keyboardview_keycode_alt">Alt</string>
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
new file mode 100644
index 0000000..8b395af
--- /dev/null
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, 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.
+*/
+-->
+
+<!-- Regex patterns for SMS short codes by country. -->
+<shortcodes>
+
+ <!-- The country attribute is the ISO country code of the user's account (from SIM card or NV).
+ The pattern attribute is a regex that matches all SMS short codes for the country.
+ The premium attribute is a regex that matches premium rate SMS short codes.
+ The free attribute matches short codes that we know will not cost the user, such as
+ emergency numbers. The standard attribute matches short codes that are billed at the
+ standard SMS rate. The user is warned when the destination phone number matches the
+ "pattern" or "premium" regexes, and does not match the "free" or "standard" regexes. -->
+
+ <!-- Harmonised European Short Codes are 6 digit numbers starting with 116 (free helplines).
+ Premium patterns include short codes from: http://aonebill.com/coverage&tariffs
+ and http://mobilcent.com/info-worldwide.asp and extracted from:
+ http://smscoin.net/software/engine/WordPress/Paid+SMS-registration/ -->
+
+ <!-- Albania: 5 digits, known short codes listed -->
+ <shortcode country="al" pattern="\\d{5}" premium="15191|55[56]00" />
+
+ <!-- Armenia: 3-4 digits, emergency numbers 10[123] -->
+ <shortcode country="am" pattern="\\d{3,4}" premium="11[2456]1|3024" free="10[123]" />
+
+ <!-- Austria: 10 digits, premium prefix 09xx, plus EU -->
+ <shortcode country="at" pattern="11\\d{4}" premium="09.*" free="116\\d{3}" />
+
+ <!-- Australia: 6 or 8 digits starting with "19" -->
+ <shortcode country="au" pattern="19(?:\\d{4}|\\d{6})" premium="19998882" />
+
+ <!-- Azerbaijan: 4-5 digits, known premium codes listed -->
+ <shortcode country="az" pattern="\\d{4,5}" premium="330[12]|87744|901[234]|93(?:94|101)|9426|9525" />
+
+ <!-- Belgium: 4 digits, plus EU: http://www.mobileweb.be/en/mobileweb/sms-numberplan.asp -->
+ <shortcode country="be" premium="\\d{4}" free="8\\d{3}|116\\d{3}" />
+
+ <!-- Bulgaria: 4-5 digits, plus EU -->
+ <shortcode country="bg" pattern="\\d{4,5}" premium="18(?:16|423)|19(?:1[56]|35)" free="116\\d{3}" />
+
+ <!-- Belarus: 4 digits -->
+ <shortcode country="by" pattern="\\d{4}" premium="3336|4161|444[4689]|501[34]|7781" />
+
+ <!-- Canada: 5-6 digits -->
+ <shortcode country="ca" pattern="\\d{5,6}" premium="60999|88188" />
+
+ <!-- Switzerland: 3-5 digits: http://www.swisscom.ch/fxres/kmu/thirdpartybusiness_code_of_conduct_en.pdf -->
+ <shortcode country="ch" pattern="[2-9]\\d{2,4}" premium="543|83111" />
+
+ <!-- China: premium shortcodes start with "1066", free shortcodes start with "1065":
+ http://clients.txtnation.com/entries/197192-china-premium-sms-short-code-requirements -->
+ <shortcode country="cn" premium="1066.*" free="1065.*" />
+
+ <!-- Cyprus: 4-6 digits (not confirmed), known premium codes listed, plus EU -->
+ <shortcode country="cy" pattern="\\d{4,6}" premium="7510" free="116\\d{3}" />
+
+ <!-- Czech Republic: 7-8 digits, starting with 9, plus EU:
+ http://www.o2.cz/osobni/en/services-by-alphabet/91670-premium_sms.html -->
+ <shortcode country="cz" premium="9\\d{6,7}" free="116\\d{3}" />
+
+ <!-- Germany: 4-5 digits plus 1232xxx (premium codes from http://www.vodafone.de/infofaxe/537.pdf and http://premiumdienste.eplus.de/pdf/kodex.pdf), plus EU. To keep the premium regex from being too large, it only includes payment processors that have been used by SMS malware, with the regular pattern matching the other premium short codes. -->
+ <shortcode country="de" pattern="\\d{4,5}|1232\\d{3}" premium="11(?:111|833)|1232(?:013|021|060|075|286|358)|118(?:44|80|86)|20[25]00|220(?:21|22|88|99)|221(?:14|21)|223(?:44|53|77)|224[13]0|225(?:20|59|90)|226(?:06|10|20|26|30|40|56|70)|227(?:07|33|39|66|76|78|79|88|99)|228(?:08|11|66|77)|23300|30030|3[12347]000|330(?:33|55|66)|33(?:233|331|366|533)|34(?:34|567)|37000|40(?:040|123|444|[3568]00)|41(?:010|414)|44(?:000|044|344|44[24]|544)|50005|50100|50123|50555|51000|52(?:255|783)|54(?:100|2542)|55(?:077|[24]00|222|333|55|[12369]55)|56(?:789|886)|60800|6[13]000|66(?:[12348]66|566|766|777|88|999)|68888|70(?:07|123|777)|76766|77(?:007|070|222|444|[567]77)|80(?:008|123|888)|82(?:002|[378]00|323|444|472|474|488|727)|83(?:005|[169]00|333|830)|84(?:141|300|32[34]|343|488|499|777|888)|85888|86(?:188|566|640|644|650|677|868|888)|870[24]9|871(?:23|[49]9)|872(?:1[0-8]|49|99)|87499|875(?:49|55|99)|876(?:0[1367]|1[1245678]|54|99)|877(?:00|99)|878(?:15|25|3[567]|8[12])|87999|880(?:08|44|55|77|99)|88688|888(?:03|10|8|89)|8899|90(?:009|999)|99999" free="116\\d{3}" />
+
+ <!-- Denmark: see http://iprs.webspacecommerce.com/Denmark-Premium-Rate-Numbers -->
+ <shortcode country="dk" pattern="\\d{4,5}" premium="1\\d{3}" free="116\\d{3}" />
+
+ <!-- Estonia: short codes 3-5 digits starting with 1, plus premium 7 digit numbers starting with 90, plus EU.
+ http://www.tja.ee/public/documents/Elektrooniline_side/Oigusaktid/ENG/Estonian_Numbering_Plan_annex_06_09_2010.mht -->
+ <shortcode country="ee" pattern="1\\d{2,4}" premium="90\\d{5}|15330|1701[0-3]" free="116\\d{3}" />
+
+ <!-- Spain: 5-6 digits: 25xxx, 27xxx, 280xx, 35xxx, 37xxx, 795xxx, 797xxx, 995xxx, 997xxx, plus EU.
+ http://www.legallink.es/?q=en/content/which-current-regulatory-status-premium-rate-services-spain -->
+ <shortcode country="es" premium="[23][57]\\d{3}|280\\d{2}|[79]9[57]\\d{3}" free="116\\d{3}" />
+
+ <!-- Finland: 5-6 digits, premium 0600, 0700: http://en.wikipedia.org/wiki/Telephone_numbers_in_Finland -->
+ <shortcode country="fi" pattern="\\d{5,6}" premium="0600.*|0700.*|171(?:59|63)" free="116\\d{3}" />
+
+ <!-- France: 5 digits, free: 3xxxx, premium [4-8]xxxx, plus EU:
+ http://clients.txtnation.com/entries/161972-france-premium-sms-short-code-requirements -->
+ <shortcode country="fr" premium="[4-8]\\d{4}" free="3\\d{4}|116\\d{3}" />
+
+ <!-- United Kingdom (Great Britain): 4-6 digits, common codes [5-8]xxxx, plus EU:
+ http://www.short-codes.com/media/Co-regulatoryCodeofPracticeforcommonshortcodes170206.pdf -->
+ <shortcode country="gb" pattern="\\d{4,6}" premium="[5-8]\\d{4}" free="116\\d{3}" />
+
+ <!-- Georgia: 4 digits, known premium codes listed -->
+ <shortcode country="ge" pattern="\\d{4}" premium="801[234]|888[239]" />
+
+ <!-- Greece: 5 digits (54xxx, 19yxx, x=0-9, y=0-5): http://www.cmtelecom.com/premium-sms/greece -->
+ <shortcode country="gr" pattern="\\d{5}" premium="54\\d{3}|19[0-5]\\d{2}" free="116\\d{3}" />
+
+ <!-- Hungary: 4 or 10 digits starting with 1 or 0, plus EU:
+ http://clients.txtnation.com/entries/209633-hungary-premium-sms-short-code-regulations -->
+ <shortcode country="hu" pattern="[01](?:\\d{3}|\\d{9})" premium="0691227910|1784" free="116\\d{3}" />
+
+ <!-- Ireland: 5 digits, 5xxxx (50xxx=free, 5[12]xxx=standard), plus EU:
+ http://www.comreg.ie/_fileupload/publications/ComReg1117.pdf -->
+ <shortcode country="ie" pattern="\\d{5}" premium="5[3-9]\\d{3}" free="50\\d{3}|116\\d{3}" standard="5[12]\\d{3}" />
+
+ <!-- Israel: 4 digits, known premium codes listed -->
+ <shortcode country="il" pattern="\\d{4}" premium="4422|4545" />
+
+ <!-- Italy: 5 digits (premium=4xxxx), plus EU:
+ http://clients.txtnation.com/attachments/token/di5kfblvubttvlw/?name=Italy_CASP_EN.pdf -->
+ <shortcode country="it" pattern="\\d{5}" premium="4\\d{4}" free="116\\d{3}" />
+
+ <!-- Kyrgyzstan: 4 digits, known premium codes listed -->
+ <shortcode country="kg" pattern="\\d{4}" premium="415[2367]|444[69]" />
+
+ <!-- Kazakhstan: 4 digits, known premium codes listed: http://smscoin.net/info/pricing-kazakhstan/ -->
+ <shortcode country="kz" pattern="\\d{4}" premium="335[02]|4161|444[469]|77[2359]0|8444|919[3-5]|968[2-5]" />
+
+ <!-- Lithuania: 3-5 digits, known premium codes listed, plus EU -->
+ <shortcode country="lt" pattern="\\d{3,5}" premium="13[89]1|1394|16[34]5" free="116\\d{3}" />
+
+ <!-- Luxembourg: 5 digits, 6xxxx, plus EU:
+ http://www.luxgsm.lu/assets/files/filepage/file_1253803400.pdf -->
+ <shortcode country="lu" premium="6\\d{4}" free="116\\d{3}" />
+
+ <!-- Latvia: 4 digits, known premium codes listed, plus EU -->
+ <shortcode country="lv" pattern="\\d{4}" premium="18(?:19|63|7[1-4])" free="116\\d{3}" />
+
+ <!-- Mexico: 4-5 digits (not confirmed), known premium codes listed -->
+ <shortcode country="mx" pattern="\\d{4,5}" premium="53035|7766" />
+
+ <!-- Malaysia: 5 digits: http://www.skmm.gov.my/attachment/Consumer_Regulation/Mobile_Content_Services_FAQs.pdf -->
+ <shortcode country="my" pattern="\\d{5}" premium="32298|33776" />
+
+ <!-- The Netherlands, 4 digits, known premium codes listed, plus EU -->
+ <shortcode country="nl" pattern="\\d{4}" premium="4466|5040" free="116\\d{3}" />
+
+ <!-- Norway: 4-5 digits (not confirmed), known premium codes listed -->
+ <shortcode country="no" pattern="\\d{4,5}" premium="2201|222[67]" />
+
+ <!-- New Zealand: 3-4 digits, known premium codes listed -->
+ <shortcode country="nz" pattern="\\d{3,4}" premium="3903|8995" />
+
+ <!-- Poland: 4-5 digits (not confirmed), known premium codes listed, plus EU -->
+ <shortcode country="pl" pattern="\\d{4,5}" premium="74240|79(?:10|866)|92525" free="116\\d{3}" />
+
+ <!-- Portugal: 5 digits, plus EU:
+ http://clients.txtnation.com/entries/158326-portugal-premium-sms-short-code-regulations -->
+ <shortcode country="pt" premium="6[1289]\\d{3}" free="116\\d{3}" />
+
+ <!-- Romania: 4 digits, plus EU: http://www.simplus.ro/en/resources/glossary-of-terms/ -->
+ <shortcode country="ro" pattern="\\d{4}" premium="12(?:63|66|88)|13(?:14|80)" free="116\\d{3}" />
+
+ <!-- Russia: 4 digits, known premium codes listed: http://smscoin.net/info/pricing-russia/ -->
+ <shortcode country="ru" pattern="\\d{4}" premium="1(?:1[56]1|899)|2(?:09[57]|322|47[46]|880|990)|3[589]33|4161|44(?:4[3-9]|81)|77(?:33|81)" />
+
+ <!-- Sweden: 5 digits (72xxx), plus EU: http://www.viatel.se/en/premium-sms/ -->
+ <shortcode country="se" premium="72\\d{3}" free="116\\d{3}" />
+
+ <!-- Singapore: 5 digits: http://clients.txtnation.com/entries/306442-singapore-premium-sms-short-code-requirements
+ Free government directory info at 74688: http://app.sgdi.gov.sg/sms_help.asp -->
+ <shortcode country="sg" pattern="7\\d{4}" premium="73800" standard="74688" />
+
+ <!-- Slovenia: 4 digits (premium=3xxx, 6xxx, 8xxx), plus EU: http://www.cmtelecom.com/premium-sms/slovenia -->
+ <shortcode country="si" pattern="\\d{4}" premium="[368]\\d{3}" free="116\\d{3}" />
+
+ <!-- Slovakia: 4 digits (premium), plus EU: http://www.cmtelecom.com/premium-sms/slovakia -->
+ <shortcode country="sk" premium="\\d{4}" free="116\\d{3}" />
+
+ <!-- Tajikistan: 4 digits, known premium codes listed -->
+ <shortcode country="tj" pattern="\\d{4}" premium="11[3-7]1|4161|4333|444[689]" />
+
+ <!-- Ukraine: 4 digits, known premium codes listed -->
+ <shortcode country="ua" pattern="\\d{4}" premium="444[3-9]|70[579]4|7540" />
+
+ <!-- USA: 5-6 digits (premium codes from https://www.premiumsmsrefunds.com/ShortCodes.htm) -->
+ <shortcode country="us" pattern="\\d{5,6}" premium="20433|21(?:344|472)|22715|23(?:333|847)|24(?:15|28)0|25209|27(?:449|606|663)|28498|305(?:00|83)|32(?:340|941)|33(?:166|786|849)|34746|35(?:182|564)|37975|38(?:135|146|254)|41(?:366|463)|42335|43(?:355|500)|44(?:578|711|811)|45814|46(?:157|173|327)|46666|47553|48(?:221|277|669)|50(?:844|920)|51(?:062|368)|52944|54(?:723|892)|55928|56483|57370|59(?:182|187|252|342)|60339|61(?:266|982)|62478|64(?:219|898)|65(?:108|500)|69(?:208|388)|70877|71851|72(?:078|087|465)|73(?:288|588|882|909|997)|74(?:034|332|815)|76426|79213|81946|83177|84(?:103|685)|85797|86(?:234|236|666)|89616|90(?:715|842|938)|91(?:362|958)|94719|95297|96(?:040|666|835|969)|97(?:142|294|688)|99(?:689|796|807)" />
+
+</shortcodes>