summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/java/android/app/ActivityManagerNative.java67
-rw-r--r--core/java/android/app/ActivityThread.java473
-rw-r--r--core/java/android/app/ApplicationThreadNative.java17
-rw-r--r--core/java/android/app/ContextImpl.java15
-rw-r--r--core/java/android/app/IActivityManager.java14
-rw-r--r--core/java/android/app/IApplicationThread.java2
-rw-r--r--core/java/android/app/Instrumentation.java7
-rw-r--r--core/java/android/app/backup/BackupManager.java10
-rw-r--r--core/java/android/content/ContentProviderClient.java133
-rw-r--r--core/java/android/content/ContentResolver.java242
-rw-r--r--core/java/android/view/AccessibilityIterators.java168
-rw-r--r--core/java/android/view/View.java192
-rw-r--r--core/java/android/webkit/WebViewInputDispatcher.java1
-rw-r--r--core/java/android/widget/AccessibilityIterators.java77
-rw-r--r--core/java/android/widget/TextView.java10
-rw-r--r--core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java178
-rw-r--r--core/java/com/android/internal/widget/multiwaveview/Tweener.java3
-rw-r--r--core/res/res/values-am/strings.xml18
-rw-r--r--core/res/res/values-ca/strings.xml18
-rw-r--r--core/res/res/values-cs/strings.xml4
-rw-r--r--core/res/res/values-el/strings.xml18
-rw-r--r--core/res/res/values-en-rGB/strings.xml18
-rw-r--r--core/res/res/values-es/strings.xml18
-rw-r--r--core/res/res/values-et/strings.xml2
-rw-r--r--core/res/res/values-in/strings.xml28
-rw-r--r--core/res/res/values-iw/strings.xml18
-rw-r--r--core/res/res/values-large/config.xml3
-rw-r--r--core/res/res/values-sl/strings.xml4
-rw-r--r--core/res/res/values-sw/strings.xml18
-rw-r--r--core/res/res/values-sw600dp/config.xml3
-rw-r--r--core/res/res/values-th/strings.xml18
-rw-r--r--core/res/res/values-zh-rCN/strings.xml14
-rwxr-xr-xcore/res/res/values/attrs.xml37
-rw-r--r--core/res/res/values/attrs_manifest.xml4
-rwxr-xr-xcore/res/res/values/config.xml8
-rw-r--r--core/res/res/values/public.xml7
36 files changed, 1182 insertions, 685 deletions
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 4506546..2ed93f4 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -580,7 +580,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
IBinder b = data.readStrongBinder();
IApplicationThread app = ApplicationThreadNative.asInterface(b);
String name = data.readString();
- ContentProviderHolder cph = getContentProvider(app, name);
+ boolean stable = data.readInt() != 0;
+ ContentProviderHolder cph = getContentProvider(app, name, stable);
reply.writeNoException();
if (cph != null) {
reply.writeInt(1);
@@ -617,12 +618,30 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true;
}
+ case REF_CONTENT_PROVIDER_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ IBinder b = data.readStrongBinder();
+ int stable = data.readInt();
+ int unstable = data.readInt();
+ boolean res = refContentProvider(b, stable, unstable);
+ reply.writeNoException();
+ reply.writeInt(res ? 1 : 0);
+ return true;
+ }
+
+ case UNSTABLE_PROVIDER_DIED_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ IBinder b = data.readStrongBinder();
+ unstableProviderDied(b);
+ reply.writeNoException();
+ return true;
+ }
+
case REMOVE_CONTENT_PROVIDER_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
- IApplicationThread app = ApplicationThreadNative.asInterface(b);
- String name = data.readString();
- removeContentProvider(app, name);
+ boolean stable = data.readInt() != 0;
+ removeContentProvider(b, stable);
reply.writeNoException();
return true;
}
@@ -2314,13 +2333,13 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
}
public ContentProviderHolder getContentProvider(IApplicationThread caller,
- String name) throws RemoteException
- {
+ String name, boolean stable) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeString(name);
+ data.writeInt(stable ? 1 : 0);
mRemote.transact(GET_CONTENT_PROVIDER_TRANSACTION, data, reply, 0);
reply.readException();
int res = reply.readInt();
@@ -2352,7 +2371,7 @@ class ActivityManagerProxy implements IActivityManager
return cph;
}
public void publishContentProviders(IApplicationThread caller,
- List<ContentProviderHolder> providers) throws RemoteException
+ List<ContentProviderHolder> providers) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -2364,14 +2383,38 @@ class ActivityManagerProxy implements IActivityManager
data.recycle();
reply.recycle();
}
-
- public void removeContentProvider(IApplicationThread caller,
- String name) throws RemoteException {
+ public boolean refContentProvider(IBinder connection, int stable, int unstable)
+ throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(caller != null ? caller.asBinder() : null);
- data.writeString(name);
+ data.writeStrongBinder(connection);
+ data.writeInt(stable);
+ data.writeInt(unstable);
+ mRemote.transact(REF_CONTENT_PROVIDER_TRANSACTION, data, reply, 0);
+ reply.readException();
+ boolean res = reply.readInt() != 0;
+ data.recycle();
+ reply.recycle();
+ return res;
+ }
+ public void unstableProviderDied(IBinder connection) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeStrongBinder(connection);
+ mRemote.transact(UNSTABLE_PROVIDER_DIED_TRANSACTION, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
+ public void removeContentProvider(IBinder connection, boolean stable) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeStrongBinder(connection);
+ data.writeInt(stable ? 1 : 0);
mRemote.transact(REMOVE_CONTENT_PROVIDER_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 33e639e..a457e3c 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -140,6 +140,7 @@ public final class ActivityThread {
private static final boolean DEBUG_CONFIGURATION = false;
private static final boolean DEBUG_SERVICE = false;
private static final boolean DEBUG_MEMORY_TRIM = false;
+ private static final boolean DEBUG_PROVIDER = false;
private static final long MIN_TIME_BETWEEN_GCS = 5*1000;
private static final Pattern PATTERN_SEMICOLON = Pattern.compile(";");
private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003;
@@ -210,6 +211,8 @@ public final class ActivityThread {
= new HashMap<IBinder, ProviderRefCount>();
final HashMap<IBinder, ProviderClientRecord> mLocalProviders
= new HashMap<IBinder, ProviderClientRecord>();
+ final HashMap<ComponentName, ProviderClientRecord> mLocalProvidersByName
+ = new HashMap<ComponentName, ProviderClientRecord>();
final HashMap<Activity, ArrayList<OnActivityPausedListener>> mOnPauseListeners
= new HashMap<Activity, ArrayList<OnActivityPausedListener>>();
@@ -284,20 +287,19 @@ public final class ActivityThread {
}
}
- final class ProviderClientRecord implements IBinder.DeathRecipient {
- final String mName;
+ final class ProviderClientRecord {
+ final String[] mNames;
final IContentProvider mProvider;
final ContentProvider mLocalProvider;
+ final IActivityManager.ContentProviderHolder mHolder;
- ProviderClientRecord(String name, IContentProvider provider,
- ContentProvider localProvider) {
- mName = name;
+ ProviderClientRecord(String[] names, IContentProvider provider,
+ ContentProvider localProvider,
+ IActivityManager.ContentProviderHolder holder) {
+ mNames = names;
mProvider = provider;
mLocalProvider = localProvider;
- }
-
- public void binderDied() {
- removeDeadProvider(mName, mProvider);
+ mHolder = holder;
}
}
@@ -1061,6 +1063,11 @@ public final class ActivityThread {
pw.flush();
}
+ @Override
+ public void unstableProviderDied(IBinder provider) {
+ queueOrSendMessage(H.UNSTABLE_PROVIDER_DIED, provider);
+ }
+
private void printRow(PrintWriter pw, String format, Object...objs) {
pw.println(String.format(format, objs));
}
@@ -1125,6 +1132,7 @@ public final class ActivityThread {
public static final int UPDATE_PACKAGE_COMPATIBILITY_INFO = 139;
public static final int TRIM_MEMORY = 140;
public static final int DUMP_PROVIDER = 141;
+ public static final int UNSTABLE_PROVIDER_DIED = 142;
String codeToString(int code) {
if (DEBUG_MESSAGES) {
switch (code) {
@@ -1170,6 +1178,7 @@ public final class ActivityThread {
case UPDATE_PACKAGE_COMPATIBILITY_INFO: return "UPDATE_PACKAGE_COMPATIBILITY_INFO";
case TRIM_MEMORY: return "TRIM_MEMORY";
case DUMP_PROVIDER: return "DUMP_PROVIDER";
+ case UNSTABLE_PROVIDER_DIED: return "UNSTABLE_PROVIDER_DIED";
}
}
return Integer.toString(code);
@@ -1337,7 +1346,7 @@ public final class ActivityThread {
break;
case REMOVE_PROVIDER:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "providerRemove");
- completeRemoveProvider((IContentProvider)msg.obj);
+ completeRemoveProvider((ProviderRefCount)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case ENABLE_JIT:
@@ -1377,6 +1386,9 @@ public final class ActivityThread {
handleTrimMemory(msg.arg1);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
+ case UNSTABLE_PROVIDER_DIED:
+ handleUnstableProviderDied((IBinder)msg.obj, false);
+ break;
}
if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
}
@@ -2867,10 +2879,24 @@ public final class ActivityThread {
}
private static final class ProviderRefCount {
- public int count;
+ public final IActivityManager.ContentProviderHolder holder;
+ public final ProviderClientRecord client;
+ public int stableCount;
+ public int unstableCount;
- ProviderRefCount(int pCount) {
- count = pCount;
+ // When this is set, the stable and unstable ref counts are 0 and
+ // we have a pending operation scheduled to remove the ref count
+ // from the activity manager. On the activity manager we are still
+ // holding an unstable ref, though it is not reflected in the counts
+ // here.
+ public boolean removePending;
+
+ ProviderRefCount(IActivityManager.ContentProviderHolder inHolder,
+ ProviderClientRecord inClient, int sCount, int uCount) {
+ holder = inHolder;
+ client = inClient;
+ stableCount = sCount;
+ unstableCount = uCount;
}
}
@@ -4080,15 +4106,6 @@ public final class ActivityThread {
Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
}
- try {
- mInstrumentation.onCreate(data.instrumentationArgs);
- }
- catch (Exception e) {
- throw new RuntimeException(
- "Exception thrown in onCreate() of "
- + data.instrumentationName + ": " + e.toString(), e);
- }
-
} else {
mInstrumentation = new Instrumentation();
}
@@ -4119,6 +4136,17 @@ public final class ActivityThread {
}
}
+ // Do this after providers, since instrumentation tests generally start their
+ // test thread at this point, and we don't want that racing.
+ try {
+ mInstrumentation.onCreate(data.instrumentationArgs);
+ }
+ catch (Exception e) {
+ throw new RuntimeException(
+ "Exception thrown in onCreate() of "
+ + data.instrumentationName + ": " + e.toString(), e);
+ }
+
try {
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
@@ -4159,12 +4187,9 @@ public final class ActivityThread {
buf.append(": ");
buf.append(cpi.name);
Log.i(TAG, buf.toString());
- IContentProvider cp = installProvider(context, null, cpi,
- false /*noisy*/, true /*noReleaseNeeded*/);
- if (cp != null) {
- IActivityManager.ContentProviderHolder cph =
- new IActivityManager.ContentProviderHolder(cpi);
- cph.provider = cp;
+ IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi,
+ false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
+ if (cph != null) {
cph.noReleaseNeeded = true;
results.add(cph);
}
@@ -4177,8 +4202,8 @@ public final class ActivityThread {
}
}
- public final IContentProvider acquireProvider(Context c, String name) {
- IContentProvider provider = acquireExistingProvider(c, name);
+ public final IContentProvider acquireProvider(Context c, String name, boolean stable) {
+ IContentProvider provider = acquireExistingProvider(c, name, stable);
if (provider != null) {
return provider;
}
@@ -4192,7 +4217,7 @@ public final class ActivityThread {
IActivityManager.ContentProviderHolder holder = null;
try {
holder = ActivityManagerNative.getDefault().getContentProvider(
- getApplicationThread(), name);
+ getApplicationThread(), name, stable);
} catch (RemoteException ex) {
}
if (holder == null) {
@@ -4202,23 +4227,79 @@ public final class ActivityThread {
// Install provider will increment the reference count for us, and break
// any ties in the race.
- provider = installProvider(c, holder.provider, holder.info,
- true /*noisy*/, holder.noReleaseNeeded);
- if (holder.provider != null && provider != holder.provider) {
- if (localLOGV) {
- Slog.v(TAG, "acquireProvider: lost the race, releasing extraneous "
- + "reference to the content provider");
+ holder = installProvider(c, holder, holder.info,
+ true /*noisy*/, holder.noReleaseNeeded, stable);
+ return holder.provider;
+ }
+
+ private final void incProviderRefLocked(ProviderRefCount prc, boolean stable) {
+ if (stable) {
+ prc.stableCount += 1;
+ if (prc.stableCount == 1) {
+ // We are acquiring a new stable reference on the provider.
+ int unstableDelta;
+ if (prc.removePending) {
+ // We have a pending remove operation, which is holding the
+ // last unstable reference. At this point we are converting
+ // that unstable reference to our new stable reference.
+ unstableDelta = -1;
+ // Cancel the removal of the provider.
+ if (DEBUG_PROVIDER) {
+ Slog.v(TAG, "incProviderRef: stable "
+ + "snatched provider from the jaws of death");
+ }
+ prc.removePending = false;
+ mH.removeMessages(H.REMOVE_PROVIDER, prc);
+ } else {
+ unstableDelta = 0;
+ }
+ try {
+ if (DEBUG_PROVIDER) {
+ Slog.v(TAG, "incProviderRef Now stable - "
+ + prc.holder.info.name + ": unstableDelta="
+ + unstableDelta);
+ }
+ ActivityManagerNative.getDefault().refContentProvider(
+ prc.holder.connection, 1, unstableDelta);
+ } catch (RemoteException e) {
+ //do nothing content provider object is dead any way
+ }
}
- try {
- ActivityManagerNative.getDefault().removeContentProvider(
- getApplicationThread(), name);
- } catch (RemoteException ex) {
+ } else {
+ prc.unstableCount += 1;
+ if (prc.unstableCount == 1) {
+ // We are acquiring a new unstable reference on the provider.
+ if (prc.removePending) {
+ // Oh look, we actually have a remove pending for the
+ // provider, which is still holding the last unstable
+ // reference. We just need to cancel that to take new
+ // ownership of the reference.
+ if (DEBUG_PROVIDER) {
+ Slog.v(TAG, "incProviderRef: unstable "
+ + "snatched provider from the jaws of death");
+ }
+ prc.removePending = false;
+ mH.removeMessages(H.REMOVE_PROVIDER, prc);
+ } else {
+ // First unstable ref, increment our count in the
+ // activity manager.
+ try {
+ if (DEBUG_PROVIDER) {
+ Slog.v(TAG, "incProviderRef: Now unstable - "
+ + prc.holder.info.name);
+ }
+ ActivityManagerNative.getDefault().refContentProvider(
+ prc.holder.connection, 0, 1);
+ } catch (RemoteException e) {
+ //do nothing content provider object is dead any way
+ }
+ }
}
}
- return provider;
}
- public final IContentProvider acquireExistingProvider(Context c, String name) {
+ public final IContentProvider acquireExistingProvider(Context c, String name,
+ boolean stable) {
synchronized (mProviderMap) {
ProviderClientRecord pr = mProviderMap.get(name);
if (pr == null) {
@@ -4232,23 +4313,14 @@ public final class ActivityThread {
// provider is not reference counted and never needs to be released.
ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
if (prc != null) {
- prc.count += 1;
- if (prc.count == 1) {
- if (localLOGV) {
- Slog.v(TAG, "acquireExistingProvider: "
- + "snatched provider from the jaws of death");
- }
- // Because the provider previously had a reference count of zero,
- // it was scheduled to be removed. Cancel that.
- mH.removeMessages(H.REMOVE_PROVIDER, provider);
- }
+ incProviderRefLocked(prc, stable);
}
return provider;
}
}
- public final boolean releaseProvider(IContentProvider provider) {
- if(provider == null) {
+ public final boolean releaseProvider(IContentProvider provider, boolean stable) {
+ if (provider == null) {
return false;
}
@@ -4260,55 +4332,98 @@ public final class ActivityThread {
return false;
}
- if (prc.count == 0) {
- if (localLOGV) Slog.v(TAG, "releaseProvider: ref count already 0, how?");
- return false;
+ boolean lastRef = false;
+ if (stable) {
+ if (prc.stableCount == 0) {
+ if (DEBUG_PROVIDER) Slog.v(TAG,
+ "releaseProvider: stable ref count already 0, how?");
+ return false;
+ }
+ prc.stableCount -= 1;
+ if (prc.stableCount == 0) {
+ // What we do at this point depends on whether there are
+ // any unstable refs left: if there are, we just tell the
+ // activity manager to decrement its stable count; if there
+ // aren't, we need to enqueue this provider to be removed,
+ // and convert to holding a single unstable ref while
+ // doing so.
+ lastRef = prc.unstableCount == 0;
+ try {
+ if (DEBUG_PROVIDER) {
+ Slog.v(TAG, "releaseProvider: No longer stable w/lastRef="
+ + lastRef + " - " + prc.holder.info.name);
+ }
+ ActivityManagerNative.getDefault().refContentProvider(
+ prc.holder.connection, -1, lastRef ? 1 : 0);
+ } catch (RemoteException e) {
+ //do nothing content provider object is dead any way
+ }
+ }
+ } else {
+ if (prc.unstableCount == 0) {
+ if (DEBUG_PROVIDER) Slog.v(TAG,
+ "releaseProvider: unstable ref count already 0, how?");
+ return false;
+ }
+ prc.unstableCount -= 1;
+ if (prc.unstableCount == 0) {
+ // If this is the last reference, we need to enqueue
+ // this provider to be removed instead of telling the
+ // activity manager to remove it at this point.
+ lastRef = prc.stableCount == 0;
+ if (!lastRef) {
+ try {
+ if (DEBUG_PROVIDER) {
+ Slog.v(TAG, "releaseProvider: No longer unstable - "
+ + prc.holder.info.name);
+ }
+ ActivityManagerNative.getDefault().refContentProvider(
+ prc.holder.connection, 0, -1);
+ } catch (RemoteException e) {
+ //do nothing content provider object is dead any way
+ }
+ }
+ }
}
- prc.count -= 1;
- if (prc.count == 0) {
- // Schedule the actual remove asynchronously, since we don't know the context
- // this will be called in.
- // TODO: it would be nice to post a delayed message, so
- // if we come back and need the same provider quickly
- // we will still have it available.
- Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, provider);
- mH.sendMessage(msg);
+ if (lastRef) {
+ if (!prc.removePending) {
+ // Schedule the actual remove asynchronously, since we don't know the context
+ // this will be called in.
+ // TODO: it would be nice to post a delayed message, so
+ // if we come back and need the same provider quickly
+ // we will still have it available.
+ if (DEBUG_PROVIDER) {
+ Slog.v(TAG, "releaseProvider: Enqueueing pending removal - "
+ + prc.holder.info.name);
+ }
+ prc.removePending = true;
+ Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, prc);
+ mH.sendMessage(msg);
+ } else {
+ Slog.w(TAG, "Duplicate remove pending of provider " + prc.holder.info.name);
+ }
}
return true;
}
}
- public final IContentProvider acquireUnstableProvider(Context c, String name) {
- return acquireProvider(c, name);
- }
-
- public final boolean releaseUnstableProvider(IContentProvider provider) {
- return releaseProvider(provider);
- }
-
- final void completeRemoveProvider(IContentProvider provider) {
- IBinder jBinder = provider.asBinder();
- String remoteProviderName = null;
- synchronized(mProviderMap) {
- ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
- if (prc == null) {
- // Either no release is needed (so we shouldn't be here) or the
- // provider was already released.
- if (localLOGV) Slog.v(TAG, "completeRemoveProvider: release not needed");
- return;
- }
-
- if (prc.count != 0) {
+ final void completeRemoveProvider(ProviderRefCount prc) {
+ synchronized (mProviderMap) {
+ if (!prc.removePending) {
// There was a race! Some other client managed to acquire
// the provider before the removal was completed.
// Abort the removal. We will do it later.
- if (localLOGV) Slog.v(TAG, "completeRemoveProvider: lost the race, "
+ if (DEBUG_PROVIDER) Slog.v(TAG, "completeRemoveProvider: lost the race, "
+ "provider still in use");
return;
}
- mProviderRefCountMap.remove(jBinder);
+ final IBinder jBinder = prc.holder.provider.asBinder();
+ ProviderRefCount existingPrc = mProviderRefCountMap.get(jBinder);
+ if (existingPrc == prc) {
+ mProviderRefCountMap.remove(jBinder);
+ }
Iterator<ProviderClientRecord> iter = mProviderMap.values().iterator();
while (iter.hasNext()) {
@@ -4316,43 +4431,72 @@ public final class ActivityThread {
IBinder myBinder = pr.mProvider.asBinder();
if (myBinder == jBinder) {
iter.remove();
- if (pr.mLocalProvider == null) {
- myBinder.unlinkToDeath(pr, 0);
- if (remoteProviderName == null) {
- remoteProviderName = pr.mName;
- }
- }
}
}
}
- if (remoteProviderName != null) {
- try {
- if (localLOGV) {
- Slog.v(TAG, "removeProvider: Invoking ActivityManagerNative."
- + "removeContentProvider(" + remoteProviderName + ")");
- }
- ActivityManagerNative.getDefault().removeContentProvider(
- getApplicationThread(), remoteProviderName);
- } catch (RemoteException e) {
- //do nothing content provider object is dead any way
+ try {
+ if (DEBUG_PROVIDER) {
+ Slog.v(TAG, "removeProvider: Invoking ActivityManagerNative."
+ + "removeContentProvider(" + prc.holder.info.name + ")");
}
+ ActivityManagerNative.getDefault().removeContentProvider(
+ prc.holder.connection, false);
+ } catch (RemoteException e) {
+ //do nothing content provider object is dead any way
}
}
- final void removeDeadProvider(String name, IContentProvider provider) {
+ final void handleUnstableProviderDied(IBinder provider, boolean fromClient) {
synchronized(mProviderMap) {
- ProviderClientRecord pr = mProviderMap.get(name);
- if (pr != null && pr.mProvider.asBinder() == provider.asBinder()) {
- Slog.i(TAG, "Removing dead content provider: " + name);
- ProviderClientRecord removed = mProviderMap.remove(name);
- if (removed != null) {
- removed.mProvider.asBinder().unlinkToDeath(removed, 0);
+ ProviderRefCount prc = mProviderRefCountMap.get(provider);
+ if (prc != null) {
+ if (DEBUG_PROVIDER) Slog.v(TAG, "Cleaning up dead provider "
+ + provider + " " + prc.holder.info.name);
+ mProviderRefCountMap.remove(provider);
+ if (prc.client != null && prc.client.mNames != null) {
+ for (String name : prc.client.mNames) {
+ ProviderClientRecord pr = mProviderMap.get(name);
+ if (pr != null && pr.mProvider.asBinder() == provider) {
+ Slog.i(TAG, "Removing dead content provider: " + name);
+ mProviderMap.remove(name);
+ }
+ }
+ }
+ if (fromClient) {
+ // We found out about this due to execution in our client
+ // code. Tell the activity manager about it now, to ensure
+ // that the next time we go to do anything with the provider
+ // it knows it is dead (so we don't race with its death
+ // notification).
+ try {
+ ActivityManagerNative.getDefault().unstableProviderDied(
+ prc.holder.connection);
+ } catch (RemoteException e) {
+ //do nothing content provider object is dead any way
+ }
}
}
}
}
+ private ProviderClientRecord installProviderAuthoritiesLocked(IContentProvider provider,
+ ContentProvider localProvider,IActivityManager.ContentProviderHolder holder) {
+ String names[] = PATTERN_SEMICOLON.split(holder.info.authority);
+ ProviderClientRecord pcr = new ProviderClientRecord(names, provider,
+ localProvider, holder);
+ for (int i = 0; i < names.length; i++) {
+ ProviderClientRecord existing = mProviderMap.get(names[i]);
+ if (existing != null) {
+ Slog.w(TAG, "Content provider " + pcr.mHolder.info.name
+ + " already published as " + names[i]);
+ } else {
+ mProviderMap.put(names[i], pcr);
+ }
+ }
+ return pcr;
+ }
+
/**
* Installs the provider.
*
@@ -4367,12 +4511,13 @@ public final class ActivityThread {
* and returns the existing provider. This can happen due to concurrent
* attempts to acquire the same provider.
*/
- private IContentProvider installProvider(Context context,
- IContentProvider provider, ProviderInfo info,
- boolean noisy, boolean noReleaseNeeded) {
+ private IActivityManager.ContentProviderHolder installProvider(Context context,
+ IActivityManager.ContentProviderHolder holder, ProviderInfo info,
+ boolean noisy, boolean noReleaseNeeded, boolean stable) {
ContentProvider localProvider = null;
- if (provider == null) {
- if (noisy) {
+ IContentProvider provider;
+ if (holder == null) {
+ if (DEBUG_PROVIDER || noisy) {
Slog.d(TAG, "Loading provider " + info.authority + ": "
+ info.name);
}
@@ -4409,7 +4554,7 @@ public final class ActivityThread {
info.applicationInfo.sourceDir);
return null;
}
- if (false) Slog.v(
+ if (DEBUG_PROVIDER) Slog.v(
TAG, "Instantiating local provider " + info.name);
// XXX Need to create the correct context for this provider.
localProvider.attachInfo(c, info);
@@ -4421,76 +4566,72 @@ public final class ActivityThread {
}
return null;
}
- } else if (localLOGV) {
- Slog.v(TAG, "Installing external provider " + info.authority + ": "
+ } else {
+ provider = holder.provider;
+ if (DEBUG_PROVIDER) Slog.v(TAG, "Installing external provider " + info.authority + ": "
+ info.name);
}
+ IActivityManager.ContentProviderHolder retHolder;
+
synchronized (mProviderMap) {
- // There is a possibility that this thread raced with another thread to
- // add the provider. If we find another thread got there first then we
- // just get out of the way and return the original provider.
+ if (DEBUG_PROVIDER) Slog.v(TAG, "Checking to add " + provider
+ + " / " + info.name);
IBinder jBinder = provider.asBinder();
- String names[] = PATTERN_SEMICOLON.split(info.authority);
- for (int i = 0; i < names.length; i++) {
- ProviderClientRecord pr = mProviderMap.get(names[i]);
- if (pr != null) {
- if (localLOGV) {
- Slog.v(TAG, "installProvider: lost the race, "
- + "using existing named provider");
- }
- provider = pr.mProvider;
- } else {
- pr = new ProviderClientRecord(names[i], provider, localProvider);
- if (localProvider == null) {
- try {
- jBinder.linkToDeath(pr, 0);
- } catch (RemoteException e) {
- // Provider already dead. Bail out of here without making
- // any changes to the provider map or other data structures.
- return null;
- }
- }
- mProviderMap.put(names[i], pr);
- }
- }
-
if (localProvider != null) {
- ProviderClientRecord pr = mLocalProviders.get(jBinder);
+ ComponentName cname = new ComponentName(info.packageName, info.name);
+ ProviderClientRecord pr = mLocalProvidersByName.get(cname);
if (pr != null) {
- if (localLOGV) {
+ if (DEBUG_PROVIDER) {
Slog.v(TAG, "installProvider: lost the race, "
+ "using existing local provider");
}
provider = pr.mProvider;
} else {
- pr = new ProviderClientRecord(null, provider, localProvider);
+ holder = new IActivityManager.ContentProviderHolder(info);
+ holder.provider = provider;
+ holder.noReleaseNeeded = true;
+ pr = installProviderAuthoritiesLocked(provider, localProvider, holder);
mLocalProviders.put(jBinder, pr);
+ mLocalProvidersByName.put(cname, pr);
}
- }
-
- if (!noReleaseNeeded) {
+ retHolder = pr.mHolder;
+ } else {
ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
if (prc != null) {
- if (localLOGV) {
- Slog.v(TAG, "installProvider: lost the race, incrementing ref count");
+ if (DEBUG_PROVIDER) {
+ Slog.v(TAG, "installProvider: lost the race, updating ref count");
}
- prc.count += 1;
- if (prc.count == 1) {
- if (localLOGV) {
- Slog.v(TAG, "installProvider: "
- + "snatched provider from the jaws of death");
+ // We need to transfer our new reference to the existing
+ // ref count, releasing the old one... but only if
+ // release is needed (that is, it is not running in the
+ // system process).
+ if (!noReleaseNeeded) {
+ incProviderRefLocked(prc, stable);
+ try {
+ ActivityManagerNative.getDefault().removeContentProvider(
+ holder.connection, stable);
+ } catch (RemoteException e) {
+ //do nothing content provider object is dead any way
}
- // Because the provider previously had a reference count of zero,
- // it was scheduled to be removed. Cancel that.
- mH.removeMessages(H.REMOVE_PROVIDER, provider);
}
} else {
- mProviderRefCountMap.put(jBinder, new ProviderRefCount(1));
+ ProviderClientRecord client = installProviderAuthoritiesLocked(
+ provider, localProvider, holder);
+ if (noReleaseNeeded) {
+ prc = new ProviderRefCount(holder, client, 1000, 1000);
+ } else {
+ prc = stable
+ ? new ProviderRefCount(holder, client, 1, 0)
+ : new ProviderRefCount(holder, client, 0, 1);
+ }
+ mProviderRefCountMap.put(jBinder, prc);
}
+ retHolder = prc.holder;
}
}
- return provider;
+
+ return retHolder;
}
private void attach(boolean system) {
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 437362b..3e726e0 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -575,6 +575,15 @@ public abstract class ApplicationThreadNative extends Binder
reply.writeNoException();
return true;
}
+
+ case UNSTABLE_PROVIDER_DIED_TRANSACTION:
+ {
+ data.enforceInterface(IApplicationThread.descriptor);
+ IBinder provider = data.readStrongBinder();
+ unstableProviderDied(provider);
+ reply.writeNoException();
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
@@ -1163,4 +1172,12 @@ class ApplicationThreadProxy implements IApplicationThread {
mRemote.transact(DUMP_DB_INFO_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
data.recycle();
}
+
+ public void unstableProviderDied(IBinder provider) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ data.writeInterfaceToken(IApplicationThread.descriptor);
+ data.writeStrongBinder(provider);
+ mRemote.transact(UNSTABLE_PROVIDER_DIED_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
+ data.recycle();
+ }
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 299e408..4c35a8c 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1679,27 +1679,32 @@ class ContextImpl extends Context {
@Override
protected IContentProvider acquireProvider(Context context, String name) {
- return mMainThread.acquireProvider(context, name);
+ return mMainThread.acquireProvider(context, name, true);
}
@Override
protected IContentProvider acquireExistingProvider(Context context, String name) {
- return mMainThread.acquireExistingProvider(context, name);
+ return mMainThread.acquireExistingProvider(context, name, true);
}
@Override
public boolean releaseProvider(IContentProvider provider) {
- return mMainThread.releaseProvider(provider);
+ return mMainThread.releaseProvider(provider, true);
}
@Override
protected IContentProvider acquireUnstableProvider(Context c, String name) {
- return mMainThread.acquireUnstableProvider(c, name);
+ return mMainThread.acquireProvider(c, name, false);
}
@Override
public boolean releaseUnstableProvider(IContentProvider icp) {
- return mMainThread.releaseUnstableProvider(icp);
+ return mMainThread.releaseProvider(icp, false);
+ }
+
+ @Override
+ public void unstableProviderDied(IContentProvider icp) {
+ mMainThread.handleUnstableProviderDied(icp.asBinder(), true);
}
private final ActivityThread mMainThread;
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index cf304df..609a047 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -116,14 +116,16 @@ public interface IActivityManager extends IInterface {
public void reportThumbnail(IBinder token,
Bitmap thumbnail, CharSequence description) throws RemoteException;
public ContentProviderHolder getContentProvider(IApplicationThread caller,
- String name) throws RemoteException;
+ String name, boolean stable) throws RemoteException;
public ContentProviderHolder getContentProviderExternal(String name, IBinder token)
throws RemoteException;
- public void removeContentProvider(IApplicationThread caller,
- String name) throws RemoteException;
+ public void removeContentProvider(IBinder connection, boolean stable) throws RemoteException;
public void removeContentProviderExternal(String name, IBinder token) throws RemoteException;
public void publishContentProviders(IApplicationThread caller,
List<ContentProviderHolder> providers) throws RemoteException;
+ public boolean refContentProvider(IBinder connection, int stableDelta, int unstableDelta)
+ throws RemoteException;
+ public void unstableProviderDied(IBinder connection) throws RemoteException;
public PendingIntent getRunningServiceControlPanel(ComponentName service)
throws RemoteException;
public ComponentName startService(IApplicationThread caller, Intent service,
@@ -363,6 +365,7 @@ public interface IActivityManager extends IInterface {
public static class ContentProviderHolder implements Parcelable {
public final ProviderInfo info;
public IContentProvider provider;
+ public IBinder connection;
public boolean noReleaseNeeded;
public ContentProviderHolder(ProviderInfo _info) {
@@ -380,6 +383,7 @@ public interface IActivityManager extends IInterface {
} else {
dest.writeStrongBinder(null);
}
+ dest.writeStrongBinder(connection);
dest.writeInt(noReleaseNeeded ? 1:0);
}
@@ -398,6 +402,7 @@ public interface IActivityManager extends IInterface {
info = ProviderInfo.CREATOR.createFromParcel(source);
provider = ContentProviderNative.asInterface(
source.readStrongBinder());
+ connection = source.readStrongBinder();
noReleaseNeeded = source.readInt() != 0;
}
}
@@ -476,7 +481,7 @@ public interface IActivityManager extends IInterface {
int REPORT_THUMBNAIL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+27;
int GET_CONTENT_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+28;
int PUBLISH_CONTENT_PROVIDERS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+29;
-
+ int REF_CONTENT_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+30;
int FINISH_SUB_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+31;
int GET_RUNNING_SERVICE_CONTROL_PANEL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+32;
int START_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+33;
@@ -597,4 +602,5 @@ public interface IActivityManager extends IInterface {
int SET_LOCK_SCREEN_SHOWN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+147;
int FINISH_ACTIVITY_AFFINITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+148;
int GET_LAUNCHED_FROM_UID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+149;
+ int UNSTABLE_PROVIDER_DIED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+150;
}
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 70029d2..f60cfd6 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -128,6 +128,7 @@ public interface IApplicationThread extends IInterface {
String[] args) throws RemoteException;
void dumpGfxInfo(FileDescriptor fd, String[] args) throws RemoteException;
void dumpDbInfo(FileDescriptor fd, String[] args) throws RemoteException;
+ void unstableProviderDied(IBinder provider) throws RemoteException;
String descriptor = "android.app.IApplicationThread";
@@ -176,4 +177,5 @@ public interface IApplicationThread extends IInterface {
int DUMP_GFX_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+43;
int DUMP_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+44;
int DUMP_DB_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+45;
+ int UNSTABLE_PROVIDER_DIED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+46;
}
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 75c6e11..cad4b01 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -987,7 +987,12 @@ public class Instrumentation {
/**
* Perform calling of the application's {@link Application#onCreate}
* method. The default implementation simply calls through to that method.
- *
+ *
+ * <p>Note: This method will be called immediately after {@link #onCreate(Bundle)}.
+ * Often instrumentation tests start their test thread in onCreate(); you
+ * need to be careful of races between these. (Well between it and
+ * everything else, but let's start here.)
+ *
* @param app The application being created.
*/
public void callApplicationOnCreate(Application app) {
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index 6eebed2..be8108c 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -145,8 +145,10 @@ public class BackupManager {
try {
IRestoreSession binder = sService.beginRestoreSession(mContext.getPackageName(),
null);
- session = new RestoreSession(mContext, binder);
- result = session.restorePackage(mContext.getPackageName(), observer);
+ if (binder != null) {
+ session = new RestoreSession(mContext, binder);
+ result = session.restorePackage(mContext.getPackageName(), observer);
+ }
} catch (RemoteException e) {
Log.w(TAG, "restoreSelf() unable to contact service");
} finally {
@@ -170,7 +172,9 @@ public class BackupManager {
try {
// All packages, current transport
IRestoreSession binder = sService.beginRestoreSession(null, null);
- session = new RestoreSession(mContext, binder);
+ if (binder != null) {
+ session = new RestoreSession(mContext, binder);
+ }
} catch (RemoteException e) {
Log.w(TAG, "beginRestoreSession() couldn't connect");
}
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index 423f1f6..5c315ce 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -20,6 +20,7 @@ import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.CancellationSignal;
+import android.os.DeadObjectException;
import android.os.ICancellationSignal;
import android.os.RemoteException;
import android.os.ParcelFileDescriptor;
@@ -33,11 +34,19 @@ import java.util.ArrayList;
* calling {@link ContentResolver#acquireContentProviderClient}. This object must be released
* using {@link #release} in order to indicate to the system that the {@link ContentProvider} is
* no longer needed and can be killed to free up resources.
+ *
+ * <p>Note that you should generally create a new ContentProviderClient instance
+ * for each thread that will be performing operations. Unlike
+ * {@link ContentResolver}, the methods here such as {@link #query} and
+ * {@link #openFile} are not thread safe -- you must not call
+ * {@link #release()} on the ContentProviderClient those calls are made from
+ * until you are finished with the data they have returned.
*/
public class ContentProviderClient {
private final IContentProvider mContentProvider;
private final ContentResolver mContentResolver;
private final boolean mStable;
+ private boolean mReleased;
/**
* @hide
@@ -52,7 +61,14 @@ public class ContentProviderClient {
/** See {@link ContentProvider#query ContentProvider.query} */
public Cursor query(Uri url, String[] projection, String selection,
String[] selectionArgs, String sortOrder) throws RemoteException {
- return query(url, projection, selection, selectionArgs, sortOrder, null);
+ try {
+ return query(url, projection, selection, selectionArgs, sortOrder, null);
+ } catch (DeadObjectException e) {
+ if (!mStable) {
+ mContentResolver.unstableProviderDied(mContentProvider);
+ }
+ throw e;
+ }
}
/** See {@link ContentProvider#query ContentProvider.query} */
@@ -64,41 +80,90 @@ public class ContentProviderClient {
remoteCancellationSignal = mContentProvider.createCancellationSignal();
cancellationSignal.setRemote(remoteCancellationSignal);
}
- return mContentProvider.query(url, projection, selection, selectionArgs, sortOrder,
- remoteCancellationSignal);
+ try {
+ return mContentProvider.query(url, projection, selection, selectionArgs, sortOrder,
+ remoteCancellationSignal);
+ } catch (DeadObjectException e) {
+ if (!mStable) {
+ mContentResolver.unstableProviderDied(mContentProvider);
+ }
+ throw e;
+ }
}
/** See {@link ContentProvider#getType ContentProvider.getType} */
public String getType(Uri url) throws RemoteException {
- return mContentProvider.getType(url);
+ try {
+ return mContentProvider.getType(url);
+ } catch (DeadObjectException e) {
+ if (!mStable) {
+ mContentResolver.unstableProviderDied(mContentProvider);
+ }
+ throw e;
+ }
}
/** See {@link ContentProvider#getStreamTypes ContentProvider.getStreamTypes} */
public String[] getStreamTypes(Uri url, String mimeTypeFilter) throws RemoteException {
- return mContentProvider.getStreamTypes(url, mimeTypeFilter);
+ try {
+ return mContentProvider.getStreamTypes(url, mimeTypeFilter);
+ } catch (DeadObjectException e) {
+ if (!mStable) {
+ mContentResolver.unstableProviderDied(mContentProvider);
+ }
+ throw e;
+ }
}
/** See {@link ContentProvider#insert ContentProvider.insert} */
public Uri insert(Uri url, ContentValues initialValues)
throws RemoteException {
- return mContentProvider.insert(url, initialValues);
+ try {
+ return mContentProvider.insert(url, initialValues);
+ } catch (DeadObjectException e) {
+ if (!mStable) {
+ mContentResolver.unstableProviderDied(mContentProvider);
+ }
+ throw e;
+ }
}
/** See {@link ContentProvider#bulkInsert ContentProvider.bulkInsert} */
public int bulkInsert(Uri url, ContentValues[] initialValues) throws RemoteException {
- return mContentProvider.bulkInsert(url, initialValues);
+ try {
+ return mContentProvider.bulkInsert(url, initialValues);
+ } catch (DeadObjectException e) {
+ if (!mStable) {
+ mContentResolver.unstableProviderDied(mContentProvider);
+ }
+ throw e;
+ }
}
/** See {@link ContentProvider#delete ContentProvider.delete} */
public int delete(Uri url, String selection, String[] selectionArgs)
throws RemoteException {
- return mContentProvider.delete(url, selection, selectionArgs);
+ try {
+ return mContentProvider.delete(url, selection, selectionArgs);
+ } catch (DeadObjectException e) {
+ if (!mStable) {
+ mContentResolver.unstableProviderDied(mContentProvider);
+ }
+ throw e;
+ }
}
/** See {@link ContentProvider#update ContentProvider.update} */
public int update(Uri url, ContentValues values, String selection,
String[] selectionArgs) throws RemoteException {
- return mContentProvider.update(url, values, selection, selectionArgs);
+ try {
+ return mContentProvider.update(url, values, selection, selectionArgs);
+ } catch (DeadObjectException e) {
+ if (!mStable) {
+ mContentResolver.unstableProviderDied(mContentProvider);
+ }
+ throw e;
+ }
}
/**
@@ -110,7 +175,14 @@ public class ContentProviderClient {
*/
public ParcelFileDescriptor openFile(Uri url, String mode)
throws RemoteException, FileNotFoundException {
- return mContentProvider.openFile(url, mode);
+ try {
+ return mContentProvider.openFile(url, mode);
+ } catch (DeadObjectException e) {
+ if (!mStable) {
+ mContentResolver.unstableProviderDied(mContentProvider);
+ }
+ throw e;
+ }
}
/**
@@ -122,20 +194,41 @@ public class ContentProviderClient {
*/
public AssetFileDescriptor openAssetFile(Uri url, String mode)
throws RemoteException, FileNotFoundException {
- return mContentProvider.openAssetFile(url, mode);
+ try {
+ return mContentProvider.openAssetFile(url, mode);
+ } catch (DeadObjectException e) {
+ if (!mStable) {
+ mContentResolver.unstableProviderDied(mContentProvider);
+ }
+ throw e;
+ }
}
/** See {@link ContentProvider#openTypedAssetFile ContentProvider.openTypedAssetFile} */
public final AssetFileDescriptor openTypedAssetFileDescriptor(Uri uri,
String mimeType, Bundle opts)
throws RemoteException, FileNotFoundException {
- return mContentProvider.openTypedAssetFile(uri, mimeType, opts);
+ try {
+ return mContentProvider.openTypedAssetFile(uri, mimeType, opts);
+ } catch (DeadObjectException e) {
+ if (!mStable) {
+ mContentResolver.unstableProviderDied(mContentProvider);
+ }
+ throw e;
+ }
}
/** See {@link ContentProvider#applyBatch ContentProvider.applyBatch} */
public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
throws RemoteException, OperationApplicationException {
- return mContentProvider.applyBatch(operations);
+ try {
+ return mContentProvider.applyBatch(operations);
+ } catch (DeadObjectException e) {
+ if (!mStable) {
+ mContentResolver.unstableProviderDied(mContentProvider);
+ }
+ throw e;
+ }
}
/**
@@ -144,10 +237,16 @@ public class ContentProviderClient {
* @return true if this was release, false if it was already released
*/
public boolean release() {
- if (mStable) {
- return mContentResolver.releaseProvider(mContentProvider);
- } else {
- return mContentResolver.releaseUnstableProvider(mContentProvider);
+ synchronized (this) {
+ if (mReleased) {
+ throw new IllegalStateException("Already released");
+ }
+ mReleased = true;
+ if (mStable) {
+ return mContentResolver.releaseProvider(mContentProvider);
+ } else {
+ return mContentResolver.releaseUnstableProvider(mContentProvider);
+ }
}
}
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index f509fd8..34b5a30 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -20,27 +20,24 @@ import dalvik.system.CloseGuard;
import android.accounts.Account;
import android.app.ActivityManagerNative;
-import android.app.ActivityThread;
import android.app.AppGlobals;
-import android.content.ContentProvider.Transport;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.database.CrossProcessCursorWrapper;
import android.database.Cursor;
-import android.database.CursorWrapper;
import android.database.IContentObserver;
import android.net.Uri;
import android.os.Bundle;
import android.os.CancellationSignal;
+import android.os.DeadObjectException;
import android.os.IBinder;
import android.os.ICancellationSignal;
import android.os.OperationCanceledException;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.StrictMode;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.EventLog;
@@ -202,6 +199,8 @@ public abstract class ContentResolver {
protected abstract IContentProvider acquireUnstableProvider(Context c, String name);
/** @hide */
public abstract boolean releaseUnstableProvider(IContentProvider icp);
+ /** @hide */
+ public abstract void unstableProviderDied(IContentProvider icp);
/**
* Return the MIME type of the given content URL.
@@ -211,6 +210,7 @@ public abstract class ContentResolver {
* @return A MIME type for the content, or null if the URL is invalid or the type is unknown
*/
public final String getType(Uri url) {
+ // XXX would like to have an acquireExistingUnstableProvider for this.
IContentProvider provider = acquireExistingProvider(url);
if (provider != null) {
try {
@@ -351,23 +351,37 @@ public abstract class ContentResolver {
public final Cursor query(final Uri uri, String[] projection,
String selection, String[] selectionArgs, String sortOrder,
CancellationSignal cancellationSignal) {
- IContentProvider provider = acquireProvider(uri);
- if (provider == null) {
+ IContentProvider unstableProvider = acquireUnstableProvider(uri);
+ if (unstableProvider == null) {
return null;
}
+ IContentProvider stableProvider = null;
try {
long startTime = SystemClock.uptimeMillis();
ICancellationSignal remoteCancellationSignal = null;
if (cancellationSignal != null) {
cancellationSignal.throwIfCanceled();
- remoteCancellationSignal = provider.createCancellationSignal();
+ remoteCancellationSignal = unstableProvider.createCancellationSignal();
cancellationSignal.setRemote(remoteCancellationSignal);
}
- Cursor qCursor = provider.query(uri, projection,
- selection, selectionArgs, sortOrder, remoteCancellationSignal);
+ Cursor qCursor;
+ try {
+ qCursor = unstableProvider.query(uri, projection,
+ selection, selectionArgs, sortOrder, remoteCancellationSignal);
+ } catch (DeadObjectException e) {
+ // The remote process has died... but we only hold an unstable
+ // reference though, so we might recover!!! Let's try!!!!
+ // This is exciting!!1!!1!!!!1
+ unstableProviderDied(unstableProvider);
+ stableProvider = acquireProvider(uri);
+ if (stableProvider == null) {
+ return null;
+ }
+ qCursor = stableProvider.query(uri, projection,
+ selection, selectionArgs, sortOrder, remoteCancellationSignal);
+ }
if (qCursor == null) {
- releaseProvider(provider);
return null;
}
// force query execution
@@ -375,16 +389,21 @@ public abstract class ContentResolver {
long durationMillis = SystemClock.uptimeMillis() - startTime;
maybeLogQueryToEventLog(durationMillis, uri, projection, selection, sortOrder);
// Wrap the cursor object into CursorWrapperInner object
- return new CursorWrapperInner(qCursor, provider);
+ CursorWrapperInner wrapper = new CursorWrapperInner(qCursor,
+ stableProvider != null ? stableProvider : acquireProvider(uri));
+ stableProvider = null;
+ return wrapper;
} catch (RemoteException e) {
- releaseProvider(provider);
-
// Arbitrary and not worth documenting, as Activity
// Manager will kill this process shortly anyway.
return null;
- } catch (RuntimeException e) {
- releaseProvider(provider);
- throw e;
+ } finally {
+ if (unstableProvider != null) {
+ releaseUnstableProvider(unstableProvider);
+ }
+ if (stableProvider != null) {
+ releaseProvider(stableProvider);
+ }
}
}
@@ -592,49 +611,63 @@ public abstract class ContentResolver {
if ("r".equals(mode)) {
return openTypedAssetFileDescriptor(uri, "*/*", null);
} else {
- int n = 0;
- while (true) {
- n++;
- IContentProvider provider = acquireUnstableProvider(uri);
- if (provider == null) {
- throw new FileNotFoundException("No content provider: " + uri);
- }
+ IContentProvider unstableProvider = acquireUnstableProvider(uri);
+ if (unstableProvider == null) {
+ throw new FileNotFoundException("No content provider: " + uri);
+ }
+ IContentProvider stableProvider = null;
+ AssetFileDescriptor fd = null;
+
+ try {
try {
- AssetFileDescriptor fd = provider.openAssetFile(uri, mode);
+ fd = unstableProvider.openAssetFile(uri, mode);
if (fd == null) {
// The provider will be released by the finally{} clause
return null;
}
- ParcelFileDescriptor pfd = new ParcelFileDescriptorInner(
- fd.getParcelFileDescriptor(), provider);
-
- // Success! Don't release the provider when exiting, let
- // ParcelFileDescriptorInner do that when it is closed.
- provider = null;
-
- return new AssetFileDescriptor(pfd, fd.getStartOffset(),
- fd.getDeclaredLength());
- } catch (RemoteException e) {
- // The provider died for some reason. Since we are
- // acquiring it unstable, its process could have gotten
- // killed and need to be restarted. We'll retry a couple
- // times and if still can't succeed then fail.
- if (n <= 2) {
- try {
- Thread.sleep(100);
- } catch (InterruptedException e1) {
- }
- continue;
+ } catch (DeadObjectException e) {
+ // The remote process has died... but we only hold an unstable
+ // reference though, so we might recover!!! Let's try!!!!
+ // This is exciting!!1!!1!!!!1
+ unstableProviderDied(unstableProvider);
+ stableProvider = acquireProvider(uri);
+ if (stableProvider == null) {
+ throw new FileNotFoundException("No content provider: " + uri);
}
- // Whatever, whatever, we'll go away.
- throw new FileNotFoundException("Dead content provider: " + uri);
- } catch (FileNotFoundException e) {
- throw e;
- } finally {
- if (provider != null) {
- releaseUnstableProvider(provider);
+ fd = stableProvider.openAssetFile(uri, mode);
+ if (fd == null) {
+ // The provider will be released by the finally{} clause
+ return null;
}
}
+
+ if (stableProvider == null) {
+ stableProvider = acquireProvider(uri);
+ }
+ releaseUnstableProvider(unstableProvider);
+ ParcelFileDescriptor pfd = new ParcelFileDescriptorInner(
+ fd.getParcelFileDescriptor(), stableProvider);
+
+ // Success! Don't release the provider when exiting, let
+ // ParcelFileDescriptorInner do that when it is closed.
+ stableProvider = null;
+
+ return new AssetFileDescriptor(pfd, fd.getStartOffset(),
+ fd.getDeclaredLength());
+
+ } catch (RemoteException e) {
+ // Whatever, whatever, we'll go away.
+ throw new FileNotFoundException(
+ "Failed opening content provider: " + uri);
+ } catch (FileNotFoundException e) {
+ throw e;
+ } finally {
+ if (stableProvider != null) {
+ releaseProvider(stableProvider);
+ }
+ if (unstableProvider != null) {
+ releaseUnstableProvider(unstableProvider);
+ }
}
}
}
@@ -670,49 +703,63 @@ public abstract class ContentResolver {
*/
public final AssetFileDescriptor openTypedAssetFileDescriptor(Uri uri,
String mimeType, Bundle opts) throws FileNotFoundException {
- int n = 0;
- while (true) {
- n++;
- IContentProvider provider = acquireUnstableProvider(uri);
- if (provider == null) {
- throw new FileNotFoundException("No content provider: " + uri);
- }
+ IContentProvider unstableProvider = acquireUnstableProvider(uri);
+ if (unstableProvider == null) {
+ throw new FileNotFoundException("No content provider: " + uri);
+ }
+ IContentProvider stableProvider = null;
+ AssetFileDescriptor fd = null;
+
+ try {
try {
- AssetFileDescriptor fd = provider.openTypedAssetFile(uri, mimeType, opts);
+ fd = unstableProvider.openTypedAssetFile(uri, mimeType, opts);
if (fd == null) {
// The provider will be released by the finally{} clause
return null;
}
- ParcelFileDescriptor pfd = new ParcelFileDescriptorInner(
- fd.getParcelFileDescriptor(), provider);
-
- // Success! Don't release the provider when exiting, let
- // ParcelFileDescriptorInner do that when it is closed.
- provider = null;
-
- return new AssetFileDescriptor(pfd, fd.getStartOffset(),
- fd.getDeclaredLength());
- } catch (RemoteException e) {
- // The provider died for some reason. Since we are
- // acquiring it unstable, its process could have gotten
- // killed and need to be restarted. We'll retry a couple
- // times and if still can't succeed then fail.
- if (n <= 2) {
- try {
- Thread.sleep(100);
- } catch (InterruptedException e1) {
- }
- continue;
+ } catch (DeadObjectException e) {
+ // The remote process has died... but we only hold an unstable
+ // reference though, so we might recover!!! Let's try!!!!
+ // This is exciting!!1!!1!!!!1
+ unstableProviderDied(unstableProvider);
+ stableProvider = acquireProvider(uri);
+ if (stableProvider == null) {
+ throw new FileNotFoundException("No content provider: " + uri);
}
- // Whatever, whatever, we'll go away.
- throw new FileNotFoundException("Dead content provider: " + uri);
- } catch (FileNotFoundException e) {
- throw e;
- } finally {
- if (provider != null) {
- releaseUnstableProvider(provider);
+ fd = stableProvider.openTypedAssetFile(uri, mimeType, opts);
+ if (fd == null) {
+ // The provider will be released by the finally{} clause
+ return null;
}
}
+
+ if (stableProvider == null) {
+ stableProvider = acquireProvider(uri);
+ }
+ releaseUnstableProvider(unstableProvider);
+ ParcelFileDescriptor pfd = new ParcelFileDescriptorInner(
+ fd.getParcelFileDescriptor(), stableProvider);
+
+ // Success! Don't release the provider when exiting, let
+ // ParcelFileDescriptorInner do that when it is closed.
+ stableProvider = null;
+
+ return new AssetFileDescriptor(pfd, fd.getStartOffset(),
+ fd.getDeclaredLength());
+
+ } catch (RemoteException e) {
+ // Whatever, whatever, we'll go away.
+ throw new FileNotFoundException(
+ "Failed opening content provider: " + uri);
+ } catch (FileNotFoundException e) {
+ throw e;
+ } finally {
+ if (stableProvider != null) {
+ releaseProvider(stableProvider);
+ }
+ if (unstableProvider != null) {
+ releaseUnstableProvider(unstableProvider);
+ }
}
}
@@ -1061,7 +1108,7 @@ public abstract class ContentResolver {
if (name == null) {
return null;
}
- return acquireProvider(mContext, name);
+ return acquireUnstableProvider(mContext, name);
}
/**
@@ -1113,10 +1160,15 @@ public abstract class ContentResolver {
* use it as needed and it won't disappear, even if your process is in the
* background. If using this method, you need to take care to deal with any
* failures when communicating with the provider, and be sure to close it
- * so that it can be re-opened later.
+ * so that it can be re-opened later. In particular, catching a
+ * {@link android.os.DeadObjectException} from the calls there will let you
+ * know that the content provider has gone away; at that point the current
+ * ContentProviderClient object is invalid, and you should release it. You
+ * can acquire a new one if you would like to try to restart the provider
+ * and perform new operations on it.
*/
public final ContentProviderClient acquireUnstableContentProviderClient(Uri uri) {
- IContentProvider provider = acquireProvider(uri);
+ IContentProvider provider = acquireUnstableProvider(uri);
if (provider != null) {
return new ContentProviderClient(this, provider, false);
}
@@ -1133,10 +1185,15 @@ public abstract class ContentResolver {
* use it as needed and it won't disappear, even if your process is in the
* background. If using this method, you need to take care to deal with any
* failures when communicating with the provider, and be sure to close it
- * so that it can be re-opened later.
+ * so that it can be re-opened later. In particular, catching a
+ * {@link android.os.DeadObjectException} from the calls there will let you
+ * know that the content provider has gone away; at that point the current
+ * ContentProviderClient object is invalid, and you should release it. You
+ * can acquire a new one if you would like to try to restart the provider
+ * and perform new operations on it.
*/
public final ContentProviderClient acquireUnstableContentProviderClient(String name) {
- IContentProvider provider = acquireProvider(name);
+ IContentProvider provider = acquireUnstableProvider(name);
if (provider != null) {
return new ContentProviderClient(this, provider, false);
}
@@ -1780,7 +1837,6 @@ public abstract class ContentResolver {
private final class ParcelFileDescriptorInner extends ParcelFileDescriptor {
private final IContentProvider mContentProvider;
- public static final String TAG="ParcelFileDescriptorInner";
private boolean mReleaseProviderFlag = false;
ParcelFileDescriptorInner(ParcelFileDescriptor pfd, IContentProvider icp) {
@@ -1792,7 +1848,7 @@ public abstract class ContentResolver {
public void close() throws IOException {
if(!mReleaseProviderFlag) {
super.close();
- ContentResolver.this.releaseUnstableProvider(mContentProvider);
+ ContentResolver.this.releaseProvider(mContentProvider);
mReleaseProviderFlag = true;
}
}
diff --git a/core/java/android/view/AccessibilityIterators.java b/core/java/android/view/AccessibilityIterators.java
index cd54f24..2a7dc18 100644
--- a/core/java/android/view/AccessibilityIterators.java
+++ b/core/java/android/view/AccessibilityIterators.java
@@ -47,7 +47,6 @@ public final class AccessibilityIterators {
* @hide
*/
public static abstract class AbstractTextSegmentIterator implements TextSegmentIterator {
- protected static final int DONE = -1;
protected String mText;
@@ -104,20 +103,20 @@ public final class AccessibilityIterators {
if (offset >= textLegth) {
return null;
}
- int start = -1;
- if (offset < 0) {
- offset = 0;
- if (mImpl.isBoundary(offset)) {
- start = offset;
- }
- }
+ int start = offset;
if (start < 0) {
- start = mImpl.following(offset);
+ start = 0;
}
- if (start < 0) {
- return null;
+ while (!mImpl.isBoundary(start)) {
+ start = mImpl.following(start);
+ if (start == BreakIterator.DONE) {
+ return null;
+ }
}
final int end = mImpl.following(start);
+ if (end == BreakIterator.DONE) {
+ return null;
+ }
return getRange(start, end);
}
@@ -130,20 +129,20 @@ public final class AccessibilityIterators {
if (offset <= 0) {
return null;
}
- int end = -1;
- if (offset > mText.length()) {
- offset = mText.length();
- if (mImpl.isBoundary(offset)) {
- end = offset;
- }
+ int end = offset;
+ if (end > textLegth) {
+ end = textLegth;
}
- if (end < 0) {
- end = mImpl.preceding(offset);
+ while (!mImpl.isBoundary(end)) {
+ end = mImpl.preceding(end);
+ if (end == BreakIterator.DONE) {
+ return null;
+ }
}
- if (end < 0) {
+ final int start = mImpl.preceding(end);
+ if (start == BreakIterator.DONE) {
return null;
}
- final int start = mImpl.preceding(end);
return getRange(start, end);
}
@@ -195,25 +194,20 @@ public final class AccessibilityIterators {
if (offset >= mText.length()) {
return null;
}
- int start = -1;
- if (offset < 0) {
- offset = 0;
- if (mImpl.isBoundary(offset) && isLetterOrDigit(offset)) {
- start = offset;
- }
- }
+ int start = offset;
if (start < 0) {
- while ((offset = mImpl.following(offset)) != DONE) {
- if (isLetterOrDigit(offset)) {
- start = offset;
- break;
- }
+ start = 0;
+ }
+ while (!isLetterOrDigit(start) && !isStartBoundary(start)) {
+ start = mImpl.following(start);
+ if (start == BreakIterator.DONE) {
+ return null;
}
}
- if (start < 0) {
+ final int end = mImpl.following(start);
+ if (end == BreakIterator.DONE || !isEndBoundary(end)) {
return null;
}
- final int end = mImpl.following(start);
return getRange(start, end);
}
@@ -226,28 +220,33 @@ public final class AccessibilityIterators {
if (offset <= 0) {
return null;
}
- int end = -1;
- if (offset > mText.length()) {
- offset = mText.length();
- if (mImpl.isBoundary(offset) && offset > 0 && isLetterOrDigit(offset - 1)) {
- end = offset;
- }
+ int end = offset;
+ if (end > textLegth) {
+ end = textLegth;
}
- if (end < 0) {
- while ((offset = mImpl.preceding(offset)) != DONE) {
- if (offset > 0 && isLetterOrDigit(offset - 1)) {
- end = offset;
- break;
- }
+ while (end > 0 && !isLetterOrDigit(end - 1) && !isEndBoundary(end)) {
+ end = mImpl.preceding(end);
+ if (end == BreakIterator.DONE) {
+ return null;
}
}
- if (end < 0) {
+ final int start = mImpl.preceding(end);
+ if (start == BreakIterator.DONE || !isStartBoundary(start)) {
return null;
}
- final int start = mImpl.preceding(end);
return getRange(start, end);
}
+ private boolean isStartBoundary(int index) {
+ return isLetterOrDigit(index)
+ && (index == 0 || !isLetterOrDigit(index - 1));
+ }
+
+ private boolean isEndBoundary(int index) {
+ return (index > 0 && isLetterOrDigit(index - 1))
+ && (index == mText.length() || !isLetterOrDigit(index));
+ }
+
private boolean isLetterOrDigit(int index) {
if (index >= 0 && index < mText.length()) {
final int codePoint = mText.codePointAt(index);
@@ -276,31 +275,19 @@ public final class AccessibilityIterators {
if (offset >= textLength) {
return null;
}
- int start = -1;
- if (offset < 0) {
- start = 0;
- } else {
- for (int i = offset + 1; i < textLength; i++) {
- if (mText.charAt(i) == '\n') {
- start = i;
- break;
- }
- }
- }
+ int start = offset;
if (start < 0) {
- return null;
+ start = 0;
}
- while (start < textLength && mText.charAt(start) == '\n') {
+ while (start < textLength && mText.charAt(start) == '\n'
+ && !isStartBoundary(start)) {
start++;
}
- int end = start;
- for (int i = end + 1; i < textLength; i++) {
- end = i;
- if (mText.charAt(i) == '\n') {
- break;
- }
+ if (start >= textLength) {
+ return null;
}
- while (end < textLength && mText.charAt(end) == '\n') {
+ int end = start + 1;
+ while (end < textLength && !isEndBoundary(end)) {
end++;
}
return getRange(start, end);
@@ -315,38 +302,31 @@ public final class AccessibilityIterators {
if (offset <= 0) {
return null;
}
- int end = -1;
- if (offset > mText.length()) {
- end = mText.length();
- } else {
- if (offset > 0 && mText.charAt(offset - 1) == '\n') {
- offset--;
- }
- for (int i = offset - 1; i >= 0; i--) {
- if (i > 0 && mText.charAt(i - 1) == '\n') {
- end = i;
- break;
- }
- }
+ int end = offset;
+ if (end > textLength) {
+ end = textLength;
+ }
+ while(end > 0 && mText.charAt(end - 1) == '\n' && !isEndBoundary(end)) {
+ end--;
}
if (end <= 0) {
return null;
}
- int start = end;
- while (start > 0 && mText.charAt(start - 1) == '\n') {
+ int start = end - 1;
+ while (start > 0 && !isStartBoundary(start)) {
start--;
}
- if (start == 0 && mText.charAt(start) == '\n') {
- return null;
- }
- for (int i = start - 1; i >= 0; i--) {
- start = i;
- if (start > 0 && mText.charAt(i - 1) == '\n') {
- break;
- }
- }
- start = Math.max(0, start);
return getRange(start, end);
}
+
+ private boolean isStartBoundary(int index) {
+ return (mText.charAt(index) != '\n'
+ && (index == 0 || mText.charAt(index - 1) == '\n'));
+ }
+
+ private boolean isEndBoundary(int index) {
+ return (index > 0 && mText.charAt(index - 1) != '\n'
+ && (index == mText.length() || mText.charAt(index) == '\n'));
+ }
}
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 35b6aa6..9613149 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1596,7 +1596,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
/**
* @hide
*/
- private int mAccessibilityCursorPosition = -1;
+ private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
/**
* The view's tag.
@@ -2086,7 +2086,8 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
// Accessiblity constants for mPrivateFlags2
/**
- * Shift for accessibility related bits in {@link #mPrivateFlags2}.
+ * Shift for the bits in {@link #mPrivateFlags2} related to the
+ * "importantForAccessibility" attribute.
*/
static final int IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
@@ -2142,6 +2143,72 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
*/
static final int VIEW_QUICK_REJECTED = 0x20000000;
+ // Accessiblity constants for mPrivateFlags2
+
+ /**
+ * Shift for the bits in {@link #mPrivateFlags2} related to the
+ * "accessibilityFocusable" attribute.
+ */
+ static final int ACCESSIBILITY_FOCUSABLE_SHIFT = 30;
+
+ /**
+ * The system determines whether the view can take accessibility focus - default (recommended).
+ * <p>
+ * Such a view is consideted by the focus search if it is:
+ * <ul>
+ * <li>
+ * Important for accessibility and actionable (clickable, long clickable, focusable)
+ * </li>
+ * <li>
+ * Important for accessibility, not actionable (clickable, long clickable, focusable),
+ * and does not have an actionable predecessor.
+ * </li>
+ * </ul>
+ * An accessibility srvice can request putting accessibility focus on such a view.
+ * </p>
+ *
+ * @hide
+ */
+ public static final int ACCESSIBILITY_FOCUSABLE_AUTO = 0x00000000;
+
+ /**
+ * The view can take accessibility focus.
+ * <p>
+ * A view that can take accessibility focus is always considered during focus
+ * search and an accessibility service can request putting accessibility focus
+ * on it.
+ * </p>
+ *
+ * @hide
+ */
+ public static final int ACCESSIBILITY_FOCUSABLE_YES = 0x00000001;
+
+ /**
+ * The view can not take accessibility focus.
+ * <p>
+ * A view that can not take accessibility focus is never considered during focus
+ * search and an accessibility service can not request putting accessibility focus
+ * on it.
+ * </p>
+ *
+ * @hide
+ */
+ public static final int ACCESSIBILITY_FOCUSABLE_NO = 0x00000002;
+
+ /**
+ * The default whether the view is accessiblity focusable.
+ */
+ static final int ACCESSIBILITY_FOCUSABLE_DEFAULT = ACCESSIBILITY_FOCUSABLE_AUTO;
+
+ /**
+ * Mask for obtainig the bits which specifies how to determine
+ * whether a view is accessibility focusable.
+ */
+ static final int ACCESSIBILITY_FOCUSABLE_MASK = (ACCESSIBILITY_FOCUSABLE_AUTO
+ | ACCESSIBILITY_FOCUSABLE_YES | ACCESSIBILITY_FOCUSABLE_NO)
+ << ACCESSIBILITY_FOCUSABLE_SHIFT;
+
+
/* End of masks for mPrivateFlags2 */
static final int DRAG_MASK = DRAG_CAN_ACCEPT | DRAG_HOVERED;
@@ -2468,6 +2535,11 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
/**
+ * The undefined cursor position.
+ */
+ private static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
+
+ /**
* Indicates that the screen has changed state and is now off.
*
* @see #onScreenStateChanged(int)
@@ -3132,7 +3204,8 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
mPrivateFlags2 = (LAYOUT_DIRECTION_DEFAULT << LAYOUT_DIRECTION_MASK_SHIFT) |
(TEXT_DIRECTION_DEFAULT << TEXT_DIRECTION_MASK_SHIFT) |
(TEXT_ALIGNMENT_DEFAULT << TEXT_ALIGNMENT_MASK_SHIFT) |
- (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
+ (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << IMPORTANT_FOR_ACCESSIBILITY_SHIFT) |
+ (ACCESSIBILITY_FOCUSABLE_DEFAULT << ACCESSIBILITY_FOCUSABLE_SHIFT);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
mUserPaddingStart = -1;
@@ -4790,7 +4863,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
}
if (!isAccessibilityFocused()) {
- info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
+ final int mode = getAccessibilityFocusable();
+ if (mode == ACCESSIBILITY_FOCUSABLE_YES || mode == ACCESSIBILITY_FOCUSABLE_AUTO) {
+ info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
+ }
} else {
info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
}
@@ -6071,7 +6147,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
return;
}
if ((focusableMode & FOCUSABLES_ACCESSIBILITY) == FOCUSABLES_ACCESSIBILITY) {
- if (canTakeAccessibilityFocusFromHover() || getAccessibilityNodeProvider() != null) {
+ if (isAccessibilityFocusable()) {
views.add(this);
return;
}
@@ -6204,7 +6280,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
notifyAccessibilityStateChanged();
// Clear the text navigation state.
- setAccessibilityCursorPosition(-1);
+ setAccessibilityCursorPosition(ACCESSIBILITY_CURSOR_POSITION_UNDEFINED);
}
// Clear the global reference of accessibility focus if this
// view or any of its descendants had accessibility focus.
@@ -6254,6 +6330,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
void clearAccessibilityFocusNoCallbacks() {
if ((mPrivateFlags2 & ACCESSIBILITY_FOCUSED) != 0) {
mPrivateFlags2 &= ~ACCESSIBILITY_FOCUSED;
+ setAccessibilityCursorPosition(ACCESSIBILITY_CURSOR_POSITION_UNDEFINED);
invalidate();
}
}
@@ -6405,12 +6482,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
*/
@ViewDebug.ExportedProperty(category = "accessibility", mapping = {
- @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO,
- to = "IMPORTANT_FOR_ACCESSIBILITY_AUTO"),
- @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES,
- to = "IMPORTANT_FOR_ACCESSIBILITY_YES"),
- @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO,
- to = "IMPORTANT_FOR_ACCESSIBILITY_NO")
+ @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
+ @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
+ @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no")
})
public int getImportantForAccessibility() {
return (mPrivateFlags2 & IMPORTANT_FOR_ACCESSIBILITY_MASK)
@@ -6463,6 +6537,73 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
}
/**
+ * Gets the mode for determining whether this View can take accessibility focus.
+ *
+ * @return The mode for determining whether a View can take accessibility focus.
+ *
+ * @attr ref android.R.styleable#View_accessibilityFocusable
+ *
+ * @see #ACCESSIBILITY_FOCUSABLE_YES
+ * @see #ACCESSIBILITY_FOCUSABLE_NO
+ * @see #ACCESSIBILITY_FOCUSABLE_AUTO
+ *
+ * @hide
+ */
+ @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
+ @ViewDebug.IntToString(from = ACCESSIBILITY_FOCUSABLE_AUTO, to = "auto"),
+ @ViewDebug.IntToString(from = ACCESSIBILITY_FOCUSABLE_YES, to = "yes"),
+ @ViewDebug.IntToString(from = ACCESSIBILITY_FOCUSABLE_NO, to = "no")
+ })
+ public int getAccessibilityFocusable() {
+ return (mPrivateFlags2 & ACCESSIBILITY_FOCUSABLE_MASK) >>> ACCESSIBILITY_FOCUSABLE_SHIFT;
+ }
+
+ /**
+ * Sets how to determine whether this view can take accessibility focus.
+ *
+ * @param mode How to determine whether this view can take accessibility focus.
+ *
+ * @attr ref android.R.styleable#View_accessibilityFocusable
+ *
+ * @see #ACCESSIBILITY_FOCUSABLE_YES
+ * @see #ACCESSIBILITY_FOCUSABLE_NO
+ * @see #ACCESSIBILITY_FOCUSABLE_AUTO
+ *
+ * @hide
+ */
+ public void setAccessibilityFocusable(int mode) {
+ if (mode != getAccessibilityFocusable()) {
+ mPrivateFlags2 &= ~ACCESSIBILITY_FOCUSABLE_MASK;
+ mPrivateFlags2 |= (mode << ACCESSIBILITY_FOCUSABLE_SHIFT)
+ & ACCESSIBILITY_FOCUSABLE_MASK;
+ notifyAccessibilityStateChanged();
+ }
+ }
+
+ /**
+ * Gets whether this view can take accessibility focus.
+ *
+ * @return Whether the view can take accessibility focus.
+ *
+ * @hide
+ */
+ public boolean isAccessibilityFocusable() {
+ final int mode = (mPrivateFlags2 & ACCESSIBILITY_FOCUSABLE_MASK)
+ >>> ACCESSIBILITY_FOCUSABLE_SHIFT;
+ switch (mode) {
+ case ACCESSIBILITY_FOCUSABLE_YES:
+ return true;
+ case ACCESSIBILITY_FOCUSABLE_NO:
+ return false;
+ case ACCESSIBILITY_FOCUSABLE_AUTO:
+ return canTakeAccessibilityFocusFromHover()
+ || getAccessibilityNodeProvider() != null;
+ default:
+ throw new IllegalArgumentException("Unknow accessibility focusable mode: " + mode);
+ }
+ }
+
+ /**
* Gets the parent for accessibility purposes. Note that the parent for
* accessibility is not necessary the immediate parent. It is the first
* predecessor that is important for accessibility.
@@ -6643,7 +6784,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
}
} break;
case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
- if (!isAccessibilityFocused()) {
+ final int mode = getAccessibilityFocusable();
+ if (!isAccessibilityFocused()
+ && (mode == ACCESSIBILITY_FOCUSABLE_YES
+ || mode == ACCESSIBILITY_FOCUSABLE_AUTO)) {
return requestAccessibilityFocus();
}
} break;
@@ -6683,12 +6827,11 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
final int current = getAccessibilityCursorPosition();
final int[] range = iterator.following(current);
if (range == null) {
- setAccessibilityCursorPosition(-1);
return false;
}
final int start = range[0];
final int end = range[1];
- setAccessibilityCursorPosition(start);
+ setAccessibilityCursorPosition(end);
sendViewTextTraversedAtGranularityEvent(
AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY,
granularity, start, end);
@@ -6704,16 +6847,26 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
if (iterator == null) {
return false;
}
- final int selectionStart = getAccessibilityCursorPosition();
- final int current = selectionStart >= 0 ? selectionStart : text.length() + 1;
+ int current = getAccessibilityCursorPosition();
+ if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
+ current = text.length();
+ } else if (granularity == AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER) {
+ // When traversing by character we always put the cursor after the character
+ // to ease edit and have to compensate before asking the for previous segment.
+ current--;
+ }
final int[] range = iterator.preceding(current);
if (range == null) {
- setAccessibilityCursorPosition(-1);
return false;
}
final int start = range[0];
final int end = range[1];
- setAccessibilityCursorPosition(end);
+ // Always put the cursor after the character to ease edit.
+ if (granularity == AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER) {
+ setAccessibilityCursorPosition(end);
+ } else {
+ setAccessibilityCursorPosition(start);
+ }
sendViewTextTraversedAtGranularityEvent(
AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
granularity, start, end);
@@ -8038,6 +8191,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
private void removeSendViewScrolledAccessibilityEventCallback() {
if (mSendViewScrolledAccessibilityEvent != null) {
removeCallbacks(mSendViewScrolledAccessibilityEvent);
+ mSendViewScrolledAccessibilityEvent.mIsPending = false;
}
}
diff --git a/core/java/android/webkit/WebViewInputDispatcher.java b/core/java/android/webkit/WebViewInputDispatcher.java
index d8065e9..f64547f 100644
--- a/core/java/android/webkit/WebViewInputDispatcher.java
+++ b/core/java/android/webkit/WebViewInputDispatcher.java
@@ -661,6 +661,7 @@ final class WebViewInputDispatcher {
// Web kit has decided to consume the event!
if (d.mEventType == EVENT_TYPE_TOUCH) {
enqueueUiCancelTouchEventIfNeededLocked();
+ unscheduleLongPressLocked();
}
} else {
// Web kit is being friendly. Pass the event to the UI.
diff --git a/core/java/android/widget/AccessibilityIterators.java b/core/java/android/widget/AccessibilityIterators.java
index e800e8d..a3d58a4 100644
--- a/core/java/android/widget/AccessibilityIterators.java
+++ b/core/java/android/widget/AccessibilityIterators.java
@@ -56,16 +56,18 @@ final class AccessibilityIterators {
if (offset >= mText.length()) {
return null;
}
- int nextLine = -1;
+ int nextLine;
if (offset < 0) {
nextLine = mLayout.getLineForOffset(0);
} else {
final int currentLine = mLayout.getLineForOffset(offset);
- if (currentLine < mLayout.getLineCount() - 1) {
+ if (getLineEdgeIndex(currentLine, DIRECTION_START) == offset) {
+ nextLine = currentLine;
+ } else {
nextLine = currentLine + 1;
}
}
- if (nextLine < 0) {
+ if (nextLine >= mLayout.getLineCount()) {
return null;
}
final int start = getLineEdgeIndex(nextLine, DIRECTION_START);
@@ -82,12 +84,14 @@ final class AccessibilityIterators {
if (offset <= 0) {
return null;
}
- int previousLine = -1;
+ int previousLine;
if (offset > mText.length()) {
previousLine = mLayout.getLineForOffset(mText.length());
} else {
- final int currentLine = mLayout.getLineForOffset(offset - 1);
- if (currentLine > 0) {
+ final int currentLine = mLayout.getLineForOffset(offset);
+ if (getLineEdgeIndex(currentLine, DIRECTION_END) + 1 == offset) {
+ previousLine = currentLine;
+ } else {
previousLine = currentLine - 1;
}
}
@@ -141,29 +145,18 @@ final class AccessibilityIterators {
return null;
}
- final int currentLine = mLayout.getLineForOffset(offset);
+ final int start = Math.max(0, offset);
+
+ final int currentLine = mLayout.getLineForOffset(start);
final int currentLineTop = mLayout.getLineTop(currentLine);
final int pageHeight = mTempRect.height() - mView.getTotalPaddingTop()
- mView.getTotalPaddingBottom();
+ final int nextPageStartY = currentLineTop + pageHeight;
+ final int lastLineTop = mLayout.getLineTop(mLayout.getLineCount() - 1);
+ final int currentPageEndLine = (nextPageStartY < lastLineTop)
+ ? mLayout.getLineForVertical(nextPageStartY) - 1 : mLayout.getLineCount() - 1;
- final int nextPageStartLine;
- final int nextPageEndLine;
- if (offset < 0) {
- nextPageStartLine = currentLine;
- final int nextPageEndY = currentLineTop + pageHeight;
- nextPageEndLine = mLayout.getLineForVertical(nextPageEndY);
- } else {
- final int nextPageStartY = currentLineTop + pageHeight;
- nextPageStartLine = mLayout.getLineForVertical(nextPageStartY) + 1;
- if (mLayout.getLineTop(nextPageStartLine) <= nextPageStartY) {
- return null;
- }
- final int nextPageEndY = nextPageStartY + pageHeight;
- nextPageEndLine = mLayout.getLineForVertical(nextPageEndY);
- }
-
- final int start = getLineEdgeIndex(nextPageStartLine, DIRECTION_START);
- final int end = getLineEdgeIndex(nextPageEndLine, DIRECTION_END) + 1;
+ final int end = getLineEdgeIndex(currentPageEndLine, DIRECTION_END) + 1;
return getRange(start, end);
}
@@ -181,37 +174,17 @@ final class AccessibilityIterators {
return null;
}
- final int currentLine = mLayout.getLineForOffset(offset);
+ final int end = Math.min(mText.length(), offset);
+
+ final int currentLine = mLayout.getLineForOffset(end);
final int currentLineTop = mLayout.getLineTop(currentLine);
final int pageHeight = mTempRect.height() - mView.getTotalPaddingTop()
- mView.getTotalPaddingBottom();
+ final int previousPageEndY = currentLineTop - pageHeight;
+ final int currentPageStartLine = (previousPageEndY > 0) ?
+ mLayout.getLineForVertical(previousPageEndY) + 1 : 0;
- final int previousPageStartLine;
- final int previousPageEndLine;
- if (offset > mText.length()) {
- final int prevousPageStartY = mLayout.getHeight() - pageHeight;
- if (prevousPageStartY < 0) {
- return null;
- }
- previousPageStartLine = mLayout.getLineForVertical(prevousPageStartY);
- previousPageEndLine = mLayout.getLineCount() - 1;
- } else {
- final int prevousPageStartY;
- if (offset == mText.length()) {
- prevousPageStartY = mLayout.getHeight() - 2 * pageHeight;
- } else {
- prevousPageStartY = currentLineTop - 2 * pageHeight;
- }
- if (prevousPageStartY < 0) {
- return null;
- }
- previousPageStartLine = mLayout.getLineForVertical(prevousPageStartY);
- final int previousPageEndY = prevousPageStartY + pageHeight;
- previousPageEndLine = mLayout.getLineForVertical(previousPageEndY) - 1;
- }
-
- final int start = getLineEdgeIndex(previousPageStartLine, DIRECTION_START);
- final int end = getLineEdgeIndex(previousPageEndLine, DIRECTION_END) + 1;
+ final int start = getLineEdgeIndex(currentPageStartLine, DIRECTION_START);
return getRange(start, end);
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index bd19f00..3e2d43a 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -8376,10 +8376,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@Override
public int getAccessibilityCursorPosition() {
if (TextUtils.isEmpty(getContentDescription())) {
- return getSelectionEnd();
- } else {
- return super.getAccessibilityCursorPosition();
+ final int selectionEnd = getSelectionEnd();
+ if (selectionEnd >= 0) {
+ return selectionEnd;
+ }
}
+ return super.getAccessibilityCursorPosition();
}
/**
@@ -8391,7 +8393,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return;
}
if (TextUtils.isEmpty(getContentDescription())) {
- if (index >= 0) {
+ if (index >= 0 && index <= mText.length()) {
Selection.setSelection((Spannable) mText, index);
} else {
Selection.removeSelection((Spannable) mText);
diff --git a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
index 8cd63ef..f9ef3c5 100644
--- a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
+++ b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
@@ -19,6 +19,7 @@ package com.android.internal.widget.multiwaveview;
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
@@ -27,6 +28,7 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
import android.os.Vibrator;
import android.text.TextUtils;
import android.util.AttributeSet;
@@ -52,10 +54,11 @@ public class MultiWaveView extends View {
// Wave state machine
private static final int STATE_IDLE = 0;
- private static final int STATE_FIRST_TOUCH = 1;
- private static final int STATE_TRACKING = 2;
- private static final int STATE_SNAP = 3;
- private static final int STATE_FINISH = 4;
+ private static final int STATE_START = 1;
+ private static final int STATE_FIRST_TOUCH = 2;
+ private static final int STATE_TRACKING = 3;
+ private static final int STATE_SNAP = 4;
+ private static final int STATE_FINISH = 5;
// Animation properties.
private static final float SNAP_MARGIN_DEFAULT = 20.0f; // distance to ring before we snap to it
@@ -74,17 +77,18 @@ public class MultiWaveView extends View {
private static final int CHEVRON_INCREMENTAL_DELAY = 160;
private static final int CHEVRON_ANIMATION_DURATION = 850;
private static final int RETURN_TO_HOME_DELAY = 1200;
- private static final int RETURN_TO_HOME_DURATION = 300;
+ private static final int RETURN_TO_HOME_DURATION = 200;
private static final int HIDE_ANIMATION_DELAY = 200;
private static final int HIDE_ANIMATION_DURATION = 200;
private static final int SHOW_ANIMATION_DURATION = 200;
private static final int SHOW_ANIMATION_DELAY = 50;
+ private static final int INITIAL_SHOW_HANDLE_DURATION = 200;
+
private static final float TAP_RADIUS_SCALE_ACCESSIBILITY_ENABLED = 1.3f;
- private static final float TARGET_SCALE_SELECTED = 0.8f;
- private static final long INITIAL_SHOW_HANDLE_DURATION = 200;
- private static final float TARGET_SCALE_UNSELECTED = 1.0f;
- private static final float RING_SCALE_UNSELECTED = 0.5f;
- private static final float RING_SCALE_SELECTED = 1.5f;
+ private static final float TARGET_SCALE_EXPANDED = 1.0f;
+ private static final float TARGET_SCALE_COLLAPSED = 0.8f;
+ private static final float RING_SCALE_EXPANDED = 1.0f;
+ private static final float RING_SCALE_COLLAPSED = 0.5f;
private TimeInterpolator mChevronAnimationInterpolator = Ease.Quad.easeOut;
@@ -182,7 +186,7 @@ public class MultiWaveView extends View {
if (mNewTargetResources != 0) {
internalSetTargetResources(mNewTargetResources);
mNewTargetResources = 0;
- hideTargets(false);
+ hideTargets(false, false);
}
mAnimatingTargets = false;
}
@@ -195,6 +199,7 @@ public class MultiWaveView extends View {
private int mVerticalInset;
private int mGravity = Gravity.TOP;
private boolean mInitialLayout = true;
+ private Tweener mBackgroundAnimator;
public MultiWaveView(Context context) {
this(context, null);
@@ -358,14 +363,21 @@ public class MultiWaveView extends View {
switch (state) {
case STATE_IDLE:
deactivateTargets();
+ hideTargets(true, false);
+ startBackgroundAnimation(0, 0.0f);
mHandleDrawable.setState(TargetDrawable.STATE_INACTIVE);
break;
+ case STATE_START:
+ deactivateHandle(0, 0, 1.0f, null);
+ startBackgroundAnimation(0, 0.0f);
+ break;
+
case STATE_FIRST_TOUCH:
- stopHandleAnimation();
deactivateTargets();
showTargets(true);
- activateHandle();
+ mHandleDrawable.setState(TargetDrawable.STATE_ACTIVE);
+ startBackgroundAnimation(INITIAL_SHOW_HANDLE_DURATION, 1.0f);
setGrabbedState(OnTriggerListener.CENTER_HANDLE);
if (AccessibilityManager.getInstance(mContext).isEnabled()) {
announceTargets();
@@ -384,17 +396,29 @@ public class MultiWaveView extends View {
}
}
- private void activateHandle() {
- mHandleDrawable.setState(TargetDrawable.STATE_ACTIVE);
- if (mAlwaysTrackFinger) {
- mHandleAnimations.stop();
- mHandleDrawable.setAlpha(0.0f);
- mHandleAnimations.add(Tweener.to(mHandleDrawable, INITIAL_SHOW_HANDLE_DURATION,
- "ease", Ease.Cubic.easeIn,
- "alpha", 1.0f,
- "onUpdate", mUpdateListener));
- mHandleAnimations.start();
- }
+ private void activateHandle(int duration, int delay, float finalAlpha,
+ AnimatorListener finishListener) {
+ mHandleAnimations.cancel();
+ mHandleAnimations.add(Tweener.to(mHandleDrawable, duration,
+ "ease", Ease.Cubic.easeIn,
+ "delay", delay,
+ "alpha", finalAlpha,
+ "onUpdate", mUpdateListener,
+ "onComplete", finishListener));
+ mHandleAnimations.start();
+ }
+
+ private void deactivateHandle(int duration, int delay, float finalAlpha,
+ AnimatorListener finishListener) {
+ mHandleAnimations.cancel();
+ mHandleAnimations.add(Tweener.to(mHandleDrawable, duration,
+ "ease", Ease.Quart.easeOut,
+ "delay", delay,
+ "alpha", finalAlpha,
+ "x", 0,
+ "y", 0,
+ "onUpdate", mUpdateListener,
+ "onComplete", finishListener));
}
/**
@@ -441,14 +465,6 @@ public class MultiWaveView extends View {
mChevronAnimations.start();
}
- private void stopChevronAnimation() {
- mChevronAnimations.stop();
- }
-
- private void stopHandleAnimation() {
- mHandleAnimations.stop();
- }
-
private void deactivateTargets() {
final int count = mTargetDrawables.size();
for (int i = 0; i < count; i++) {
@@ -493,39 +509,33 @@ public class MultiWaveView extends View {
private void doFinish() {
final int activeTarget = mActiveTarget;
- boolean targetHit = activeTarget != -1;
-
- // Hide unselected targets
- hideTargets(true);
+ final boolean targetHit = activeTarget != -1;
- // Highlight the selected one
- mHandleAnimations.cancel();
if (targetHit) {
- mHandleDrawable.setAlpha(0.0f);
- mTargetDrawables.get(activeTarget).setState(TargetDrawable.STATE_ACTIVE);
- hideUnselected(activeTarget);
+ if (DEBUG) Log.v(TAG, "Finish with target hit = " + targetHit);
+
+ highlightSelected(activeTarget);
// Inform listener of any active targets. Typically only one will be active.
- if (DEBUG) Log.v(TAG, "Finish with target hit = " + targetHit);
+ deactivateHandle(RETURN_TO_HOME_DURATION, RETURN_TO_HOME_DELAY, 0.0f, mResetListener);
dispatchTriggerEvent(activeTarget);
+ } else {
+ // Animate handle back to the center based on current state.
+ deactivateHandle(HIDE_ANIMATION_DURATION, HIDE_ANIMATION_DELAY, 1.0f,
+ mResetListenerWithPing);
+ hideTargets(true, false);
+ mHandleAnimations.start();
}
- // Animate handle back to the center based on current state.
- int delay = targetHit ? RETURN_TO_HOME_DELAY : 0;
- int duration = RETURN_TO_HOME_DURATION;
- mHandleAnimations.add(Tweener.to(mHandleDrawable, duration,
- "ease", Ease.Quart.easeOut,
- "delay", delay,
- "alpha", mAlwaysTrackFinger ? 0.0f : 1.0f,
- "x", 0,
- "y", 0,
- "onUpdate", mUpdateListener,
- "onComplete", (mDragging && !targetHit) ? mResetListenerWithPing : mResetListener));
- mHandleAnimations.start();
-
setGrabbedState(OnTriggerListener.NO_HANDLE);
}
+ private void highlightSelected(int activeTarget) {
+ // Highlight the given target and fade others
+ mTargetDrawables.get(activeTarget).setState(TargetDrawable.STATE_ACTIVE);
+ hideUnselected(activeTarget);
+ }
+
private void hideUnselected(int active) {
for (int i = 0; i < mTargetDrawables.size(); i++) {
if (i != active) {
@@ -535,16 +545,15 @@ public class MultiWaveView extends View {
mOuterRing.setAlpha(0.0f);
}
- private void hideTargets(boolean animate) {
+ private void hideTargets(boolean animate, boolean expanded) {
mTargetAnimations.cancel();
// Note: these animations should complete at the same time so that we can swap out
// the target assets asynchronously from the setTargetResources() call.
mAnimatingTargets = animate;
final int duration = animate ? HIDE_ANIMATION_DURATION : 0;
final int delay = animate ? HIDE_ANIMATION_DELAY : 0;
- final boolean targetSelected = mActiveTarget != -1;
- final float targetScale = targetSelected ? TARGET_SCALE_SELECTED : TARGET_SCALE_UNSELECTED;
+ final float targetScale = expanded ? TARGET_SCALE_EXPANDED : TARGET_SCALE_COLLAPSED;
final int length = mTargetDrawables.size();
for (int i = 0; i < length; i++) {
TargetDrawable target = mTargetDrawables.get(i);
@@ -558,7 +567,7 @@ public class MultiWaveView extends View {
"onUpdate", mUpdateListener));
}
- final float ringScaleTarget = targetSelected ? RING_SCALE_SELECTED : RING_SCALE_UNSELECTED;
+ final float ringScaleTarget = expanded ? RING_SCALE_EXPANDED : RING_SCALE_COLLAPSED;
mTargetAnimations.add(Tweener.to(mOuterRing, duration,
"ease", Ease.Cubic.easeOut,
"alpha", 0.0f,
@@ -580,8 +589,6 @@ public class MultiWaveView extends View {
for (int i = 0; i < length; i++) {
TargetDrawable target = mTargetDrawables.get(i);
target.setState(TargetDrawable.STATE_INACTIVE);
- target.setScaleX(TARGET_SCALE_SELECTED);
- target.setScaleY(TARGET_SCALE_SELECTED);
mTargetAnimations.add(Tweener.to(target, duration,
"ease", Ease.Cubic.easeOut,
"alpha", 1.0f,
@@ -732,17 +739,30 @@ public class MultiWaveView extends View {
* @param animate
*/
public void reset(boolean animate) {
- stopChevronAnimation();
- stopHandleAnimation();
+ mChevronAnimations.stop();
+ mHandleAnimations.stop();
mTargetAnimations.stop();
+ startBackgroundAnimation(0, 0.0f);
hideChevrons();
- hideTargets(animate);
- mHandleDrawable.setX(0);
- mHandleDrawable.setY(0);
- mHandleDrawable.setState(TargetDrawable.STATE_INACTIVE);
+ hideTargets(animate, false);
+ deactivateHandle(0, 0, 1.0f, null);
Tweener.reset();
}
+ private void startBackgroundAnimation(int duration, float alpha) {
+ Drawable background = getBackground();
+ if (mAlwaysTrackFinger && background != null) {
+ if (mBackgroundAnimator != null) {
+ mBackgroundAnimator.animator.end();
+ }
+ mBackgroundAnimator = Tweener.to(background, duration,
+ "ease", Ease.Cubic.easeIn,
+ "alpha", new int[] {0, (int)(255.0f * alpha)},
+ "delay", SHOW_ANIMATION_DELAY);
+ mBackgroundAnimator.animator.start();
+ }
+ }
+
@Override
public boolean onTouchEvent(MotionEvent event) {
final int action = event.getAction();
@@ -784,7 +804,10 @@ public class MultiWaveView extends View {
}
private void handleDown(MotionEvent event) {
- if (!trySwitchToFirstTouchState(event.getX(), event.getY())) {
+ float eventX = event.getX();
+ float eventY = event.getY();
+ switchToState(STATE_START, eventX, eventY);
+ if (!trySwitchToFirstTouchState(eventX, eventY)) {
mDragging = false;
mTargetAnimations.cancel();
ping();
@@ -830,7 +853,9 @@ public class MultiWaveView extends View {
if (!mDragging) {
trySwitchToFirstTouchState(eventX, eventY);
- } else {
+ }
+
+ if (mDragging) {
if (singleTarget) {
// Snap to outer ring if there's only one target
float snapRadius = mOuterRadius - mSnapMargin;
@@ -865,17 +890,11 @@ public class MultiWaveView extends View {
if (activeTarget != -1) {
switchToState(STATE_SNAP, x,y);
TargetDrawable target = targets.get(activeTarget);
- float newX = singleTarget ? x : target.getX();
- float newY = singleTarget ? y : target.getY();
+ final float newX = singleTarget ? x : target.getX();
+ final float newY = singleTarget ? y : target.getY();
moveHandleTo(newX, newY, false);
- mHandleAnimations.cancel();
- mHandleDrawable.setAlpha(0.0f);
} else {
switchToState(STATE_TRACKING, x, y);
- if (mActiveTarget != -1) {
- mHandleAnimations.cancel();
- mHandleDrawable.setAlpha(1.0f);
- }
moveHandleTo(x, y, false);
}
@@ -900,6 +919,9 @@ public class MultiWaveView extends View {
String targetContentDescription = getTargetDescription(activeTarget);
announceText(targetContentDescription);
}
+ activateHandle(0, 0, 0.0f, null);
+ } else {
+ activateHandle(0, 0, 1.0f, null);
}
}
mActiveTarget = activeTarget;
@@ -1021,7 +1043,7 @@ public class MultiWaveView extends View {
if (mInitialLayout) {
hideChevrons();
- hideTargets(false);
+ hideTargets(false, false);
moveHandleTo(0, 0, false);
mInitialLayout = false;
}
diff --git a/core/java/com/android/internal/widget/multiwaveview/Tweener.java b/core/java/com/android/internal/widget/multiwaveview/Tweener.java
index 1d502ba..d559d9d 100644
--- a/core/java/com/android/internal/widget/multiwaveview/Tweener.java
+++ b/core/java/com/android/internal/widget/multiwaveview/Tweener.java
@@ -83,6 +83,9 @@ class Tweener {
} else if (value instanceof float[]) {
props.add(PropertyValuesHolder.ofFloat(key,
((float[])value)[0], ((float[])value)[1]));
+ } else if (value instanceof int[]) {
+ props.add(PropertyValuesHolder.ofInt(key,
+ ((int[])value)[0], ((int[])value)[1]));
} else if (value instanceof Number) {
float floatValue = ((Number)value).floatValue();
props.add(PropertyValuesHolder.ofFloat(key, floatValue));
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index c8bb77e..fb11af3 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -855,12 +855,9 @@
<string name="searchview_description_clear" msgid="1330281990951833033">"ጥያቄ አጥራ"</string>
<string name="searchview_description_submit" msgid="2688450133297983542">"ጥያቄ አስረክብ"</string>
<string name="searchview_description_voice" msgid="2453203695674994440">"የድምፅ ፍለጋ"</string>
- <!-- no translation found for enable_explore_by_touch_warning_title (7460694070309730149) -->
- <skip />
- <!-- no translation found for enable_explore_by_touch_warning_message (8655887539089910577) -->
- <skip />
- <!-- no translation found for enable_explore_by_touch_warning_message (2708199672852373195) -->
- <skip />
+ <string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"በመንካት አስስ ይንቃ?"</string>
+ <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> ማሰስን በንኪ ማንቃት ይፈልጋል። አስስ በንኪ በሚበራበት ጊዜ፣ ከጡባዊ ተኮው ጋር ለመግባባት ምን በጣትህ ስር ወይም ምልክቶችን ማከናወን እንዳለብህ ማብራሪያ ልታይ ወይም ልትሰማ ትችላለህ።"</string>
+ <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> ማሰስን በንኪ ማንቃት ይፈልጋል። አስስ በንኪ በሚበራበት ጊዜ፣ ከስልኩ ጋር ለመግባባት ምን በጣትህ ስር ወይም ምልክቶችን ማከናወን እንዳለብህ ማብራሪያ ልታይ ወይም ልትሰማ ትችላለህ።"</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"ከ1 ወር በፊት"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"ከ1 ወር በፊት"</string>
<plurals name="num_seconds_ago">
@@ -1127,10 +1124,8 @@
<string name="configure_input_methods" msgid="9091652157722495116">"የግቤት ስልቶችን አዘጋጅ"</string>
<string name="use_physical_keyboard" msgid="6203112478095117625">"የሚዳሰስ የቁልፍ ሰሌዳ"</string>
<string name="hardware" msgid="7517821086888990278">"ሃርድዌር"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (1407367017263030773) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (4465907700449257063) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"የቁልፍ ሰሌዳ አቀማመጥ ምረጥ"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"የቁልፍ ሰሌዳ አቀማመጥ ለመምረጥ ንካ።"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"ዕጩዎች"</u></string>
@@ -1324,6 +1319,5 @@
<string name="launchBrowserDefault" msgid="2057951947297614725">"ማሰሺያን አስነሳ?"</string>
<string name="SetupCallDefault" msgid="5834948469253758575">"ጥሪ ተቀበል?"</string>
<string name="activity_resolver_use_always" msgid="8017770747801494933">"ዘወትር"</string>
- <!-- no translation found for activity_resolver_use_once (2404644797149173758) -->
- <skip />
+ <string name="activity_resolver_use_once" msgid="2404644797149173758">"አንዴ ብቻ"</string>
</resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 97876f6..4190bdb 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -855,12 +855,9 @@
<string name="searchview_description_clear" msgid="1330281990951833033">"Neteja la consulta"</string>
<string name="searchview_description_submit" msgid="2688450133297983542">"Envia la consulta"</string>
<string name="searchview_description_voice" msgid="2453203695674994440">"Cerca per veu"</string>
- <!-- no translation found for enable_explore_by_touch_warning_title (7460694070309730149) -->
- <skip />
- <!-- no translation found for enable_explore_by_touch_warning_message (8655887539089910577) -->
- <skip />
- <!-- no translation found for enable_explore_by_touch_warning_message (2708199672852373195) -->
- <skip />
+ <string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"Vols activar l\'Exploració per tacte?"</string>
+ <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> vol activar l\'Exploració per tacte. Quan l\'Exploració per tacte està activada, pots escoltar o veure les descripcions del que hi ha sota el dit o fer gestos per interactuar amb la tauleta."</string>
+ <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> vol activar l\'Exploració per tacte. Quan l\'Exploració per tacte està activada, pots escoltar o veure les descripcions del que hi ha sota el dit o fer gestos per interactuar amb el telèfon."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"Fa 1 mes"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Fa menys d\'1 mes"</string>
<plurals name="num_seconds_ago">
@@ -1127,10 +1124,8 @@
<string name="configure_input_methods" msgid="9091652157722495116">"Configura els mètodes d\'entrada"</string>
<string name="use_physical_keyboard" msgid="6203112478095117625">"Teclat físic"</string>
<string name="hardware" msgid="7517821086888990278">"Maquinari"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (1407367017263030773) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (4465907700449257063) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Selecciona una disposició de teclat"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Toca per seleccionar una disposició de teclat."</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"candidats"</u></string>
@@ -1324,6 +1319,5 @@
<string name="launchBrowserDefault" msgid="2057951947297614725">"Vols iniciar el navegador?"</string>
<string name="SetupCallDefault" msgid="5834948469253758575">"Vols acceptar la trucada?"</string>
<string name="activity_resolver_use_always" msgid="8017770747801494933">"Sempre"</string>
- <!-- no translation found for activity_resolver_use_once (2404644797149173758) -->
- <skip />
+ <string name="activity_resolver_use_once" msgid="2404644797149173758">"Només una"</string>
</resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index acd4bba..ad25a3e 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -145,7 +145,7 @@
<string name="shutdown_progress" msgid="2281079257329981203">"Vypínání..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Tablet se vypne."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Váš telefon bude vypnut."</string>
- <string name="shutdown_confirm_question" msgid="2906544768881136183">"Chcete vypnout telefon?"</string>
+ <string name="shutdown_confirm_question" msgid="2906544768881136183">"Chcete zařízení vypnout?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Restart v nouzovém režimu"</string>
<string name="reboot_safemode_confirm" msgid="55293944502784668">"Chcete zařízení restartovat v nouzovém režimu? Deaktivujete tak veškeré nainstalované aplikace třetích stran. Po dalším restartu budou obnoveny."</string>
<string name="recent_tasks_title" msgid="3691764623638127888">"Nejnovější"</string>
@@ -1205,7 +1205,7 @@
<string name="throttled_notification_title" msgid="6269541897729781332">"Byl překročen limit mobilních dat"</string>
<string name="throttled_notification_message" msgid="5443457321354907181">"Dotykem zobrazíte další informace o využití mobilních dat."</string>
<string name="no_matches" msgid="8129421908915840737">"Žádné shody"</string>
- <string name="find_on_page" msgid="1946799233822820384">"Vyhledat na stránce"</string>
+ <string name="find_on_page" msgid="1946799233822820384">"Hledat na stránce"</string>
<plurals name="matches_found">
<item quantity="one" msgid="8167147081136579439">"1 shoda"</item>
<item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> z <xliff:g id="TOTAL">%d</xliff:g>"</item>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index c44f789..8cde21f 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -855,12 +855,9 @@
<string name="searchview_description_clear" msgid="1330281990951833033">"Απαλοιφή ερωτήματος"</string>
<string name="searchview_description_submit" msgid="2688450133297983542">"Υποβολή ερωτήματος"</string>
<string name="searchview_description_voice" msgid="2453203695674994440">"Φωνητική αναζήτηση"</string>
- <!-- no translation found for enable_explore_by_touch_warning_title (7460694070309730149) -->
- <skip />
- <!-- no translation found for enable_explore_by_touch_warning_message (8655887539089910577) -->
- <skip />
- <!-- no translation found for enable_explore_by_touch_warning_message (2708199672852373195) -->
- <skip />
+ <string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"Ενεργοποίηση Αναζήτησης μέσω αφής;"</string>
+ <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"Η υπηρεσία <xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> απαιτεί ενεργοποίηση της Εξερεύνησης μέσω αφής. Όταν είναι ενεργοποιημένη η Εξερεύνηση μέσω αφής, μπορείτε να δείτε ή να ακούσετε περιγραφές για τις επιλογές που βρίσκονται κάτω από το δάχτυλό σας ή να κάνετε κινήσεις αλληλεπίδρασης με το tablet σας."</string>
+ <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"Η υπηρεσία <xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> απαιτεί ενεργοποίηση της Εξερεύνησης μέσω αφής. Όταν είναι ενεργοποιημένη η Εξερεύνηση μέσω αφής, μπορείτε να δείτε ή να ακούσετε περιγραφές για τις επιλογές που βρίσκονται κάτω από το δάχτυλό σας ή να κάνετε κινήσεις αλληλεπίδρασης με το τηλέφωνό σας."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"πριν από 1 μήνα"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Παλαιότερα από 1 μήνα"</string>
<plurals name="num_seconds_ago">
@@ -1127,10 +1124,8 @@
<string name="configure_input_methods" msgid="9091652157722495116">"Ρύθμιση μεθόδων εισαγωγής"</string>
<string name="use_physical_keyboard" msgid="6203112478095117625">"Φυσικό πληκτρολόγιο"</string>
<string name="hardware" msgid="7517821086888990278">"Υλικό"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (1407367017263030773) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (4465907700449257063) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Επιλογή διάταξης πληκτρολογίου"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Αγγίξτε για να επιλέξετε διάταξη πληκτρολογίου."</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"υποψήφιοι"</u></string>
@@ -1324,6 +1319,5 @@
<string name="launchBrowserDefault" msgid="2057951947297614725">"Εκκίνηση προγράμματος περιήγησης;"</string>
<string name="SetupCallDefault" msgid="5834948469253758575">"Αποδοχή κλήσης;"</string>
<string name="activity_resolver_use_always" msgid="8017770747801494933">"Πάντα"</string>
- <!-- no translation found for activity_resolver_use_once (2404644797149173758) -->
- <skip />
+ <string name="activity_resolver_use_once" msgid="2404644797149173758">"Μόνο μία φορά"</string>
</resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index a54c479..4ad7daf 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -855,12 +855,9 @@
<string name="searchview_description_clear" msgid="1330281990951833033">"Clear query"</string>
<string name="searchview_description_submit" msgid="2688450133297983542">"Submit query"</string>
<string name="searchview_description_voice" msgid="2453203695674994440">"Voice search"</string>
- <!-- no translation found for enable_explore_by_touch_warning_title (7460694070309730149) -->
- <skip />
- <!-- no translation found for enable_explore_by_touch_warning_message (8655887539089910577) -->
- <skip />
- <!-- no translation found for enable_explore_by_touch_warning_message (2708199672852373195) -->
- <skip />
+ <string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"Enable Explore by Touch?"</string>
+ <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> wants to enable Explore by Touch. When Explore by Touch is turned on, you can hear or see descriptions of what\'s under your finger or perform gestures to interact with the tablet."</string>
+ <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> wants to enable Explore by Touch. When Explore by Touch is turned on, you can hear or see descriptions of what\'s under your finger or perform gestures to interact with the phone."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"1 month ago"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Before 1 month ago"</string>
<plurals name="num_seconds_ago">
@@ -1127,10 +1124,8 @@
<string name="configure_input_methods" msgid="9091652157722495116">"Set up input methods"</string>
<string name="use_physical_keyboard" msgid="6203112478095117625">"Physical keyboard"</string>
<string name="hardware" msgid="7517821086888990278">"Hardware"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (1407367017263030773) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (4465907700449257063) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Select keyboard layout"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Touch to select a keyboard layout."</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"candidates"</u></string>
@@ -1324,6 +1319,5 @@
<string name="launchBrowserDefault" msgid="2057951947297614725">"Launch Browser?"</string>
<string name="SetupCallDefault" msgid="5834948469253758575">"Accept call?"</string>
<string name="activity_resolver_use_always" msgid="8017770747801494933">"Always"</string>
- <!-- no translation found for activity_resolver_use_once (2404644797149173758) -->
- <skip />
+ <string name="activity_resolver_use_once" msgid="2404644797149173758">"Just once"</string>
</resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index f5ffece..f5d8795 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -855,12 +855,9 @@
<string name="searchview_description_clear" msgid="1330281990951833033">"Borrar consulta"</string>
<string name="searchview_description_submit" msgid="2688450133297983542">"Enviar consulta"</string>
<string name="searchview_description_voice" msgid="2453203695674994440">"Búsqueda por voz"</string>
- <!-- no translation found for enable_explore_by_touch_warning_title (7460694070309730149) -->
- <skip />
- <!-- no translation found for enable_explore_by_touch_warning_message (8655887539089910577) -->
- <skip />
- <!-- no translation found for enable_explore_by_touch_warning_message (2708199672852373195) -->
- <skip />
+ <string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"¿Habilitar exploración táctil?"</string>
+ <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> quiere habilitar la exploración táctil. Cuando esta función esté activada, podrás escuchar o ver descripciones del contenido seleccionado o usar gestos para interactuar con el tablet."</string>
+ <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> quiere habilitar la exploración táctil. Cuando esta función esté activada, podrás escuchar o ver descripciones del contenido seleccionado o usar gestos para interactuar con el teléfono."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"Hace un mes"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Hace más de un mes"</string>
<plurals name="num_seconds_ago">
@@ -1127,10 +1124,8 @@
<string name="configure_input_methods" msgid="9091652157722495116">"Configurar métodos de introducción"</string>
<string name="use_physical_keyboard" msgid="6203112478095117625">"Teclado físico"</string>
<string name="hardware" msgid="7517821086888990278">"Hardware"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (1407367017263030773) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (4465907700449257063) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Selecciona un diseño de teclado"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Toca para seleccionar un diseño de teclado."</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"candidatos"</u></string>
@@ -1324,6 +1319,5 @@
<string name="launchBrowserDefault" msgid="2057951947297614725">"¿Iniciar el navegador?"</string>
<string name="SetupCallDefault" msgid="5834948469253758575">"¿Aceptar la llamada?"</string>
<string name="activity_resolver_use_always" msgid="8017770747801494933">"Siempre"</string>
- <!-- no translation found for activity_resolver_use_once (2404644797149173758) -->
- <skip />
+ <string name="activity_resolver_use_once" msgid="2404644797149173758">"Solo una vez"</string>
</resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index ea57cf5..eaa7c94 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -318,7 +318,7 @@
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"seo sisestusmeetodiga"</string>
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Lubab omanikul siduda sisestusmeetodi ülataseme liidesega. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"sidumine juurdepääsuteenusega"</string>
- <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Lubab omanikul luua sideme juurdepääsuteenuseteenuse ülataseme liidesega. Tavarakenduste puhul ei tohiks seda kunagi vaja minna."</string>
+ <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Lubab omanikul luua sideme juurdepääsuteenuse ülataseme liidesega. Tavarakenduste puhul ei tohiks seda kunagi vaja minna."</string>
<string name="permlab_bindTextService" msgid="7358378401915287938">"tekstiteenusega sidumine"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Võimaldab omanikul siduda tekstiteenuse (nt SpellCheckerService) ülataseme liidesega. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"seo VPN-teenusega"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index f249c2c..f0187ec 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -606,30 +606,30 @@
<item msgid="1735177144948329370">"Faks Rumah"</item>
<item msgid="603878674477207394">"Pager"</item>
<item msgid="1650824275177931637">"Lainnya"</item>
- <item msgid="9192514806975898961">"Ubahsuaian"</item>
+ <item msgid="9192514806975898961">"Khusus"</item>
</string-array>
<string-array name="emailAddressTypes">
<item msgid="8073994352956129127">"Rumah"</item>
<item msgid="7084237356602625604">"Kantor"</item>
<item msgid="1112044410659011023">"Lainnya"</item>
- <item msgid="2374913952870110618">"Ubahsuaian"</item>
+ <item msgid="2374913952870110618">"Khusus"</item>
</string-array>
<string-array name="postalAddressTypes">
<item msgid="6880257626740047286">"Rumah"</item>
<item msgid="5629153956045109251">"Kantor"</item>
<item msgid="4966604264500343469">"Lainnya"</item>
- <item msgid="4932682847595299369">"Ubahsuaian"</item>
+ <item msgid="4932682847595299369">"Khusus"</item>
</string-array>
<string-array name="imAddressTypes">
<item msgid="1738585194601476694">"Rumah"</item>
<item msgid="1359644565647383708">"Kantor"</item>
<item msgid="7868549401053615677">"Lainnya"</item>
- <item msgid="3145118944639869809">"Ubahsuaian"</item>
+ <item msgid="3145118944639869809">"Khusus"</item>
</string-array>
<string-array name="organizationTypes">
<item msgid="7546335612189115615">"Kantor"</item>
<item msgid="4378074129049520373">"Lainnya"</item>
- <item msgid="3455047468583965104">"Ubahsuaian"</item>
+ <item msgid="3455047468583965104">"Khusus"</item>
</string-array>
<string-array name="imProtocols">
<item msgid="8595261363518459565">"AIM"</item>
@@ -641,7 +641,7 @@
<item msgid="2506857312718630823">"ICQ"</item>
<item msgid="1648797903785279353">"Jabber"</item>
</string-array>
- <string name="phoneTypeCustom" msgid="1644738059053355820">"Ubahsuaian"</string>
+ <string name="phoneTypeCustom" msgid="1644738059053355820">"Khusus"</string>
<string name="phoneTypeHome" msgid="2570923463033985887">"Rumah"</string>
<string name="phoneTypeMobile" msgid="6501463557754751037">"Seluler"</string>
<string name="phoneTypeWork" msgid="8863939667059911633">"Kantor"</string>
@@ -662,24 +662,24 @@
<string name="phoneTypeWorkPager" msgid="649938731231157056">"Pager Kantor"</string>
<string name="phoneTypeAssistant" msgid="5596772636128562884">"Asisten"</string>
<string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
- <string name="eventTypeCustom" msgid="7837586198458073404">"Ubahsuaian"</string>
+ <string name="eventTypeCustom" msgid="7837586198458073404">"Khusus"</string>
<string name="eventTypeBirthday" msgid="2813379844211390740">"Hari Ulang Tahun"</string>
<string name="eventTypeAnniversary" msgid="3876779744518284000">"Hari Peringatan"</string>
<string name="eventTypeOther" msgid="7388178939010143077">"Lainnya"</string>
- <string name="emailTypeCustom" msgid="8525960257804213846">"Ubahsuaian"</string>
+ <string name="emailTypeCustom" msgid="8525960257804213846">"Khusus"</string>
<string name="emailTypeHome" msgid="449227236140433919">"Rumah"</string>
<string name="emailTypeWork" msgid="3548058059601149973">"Kantor"</string>
<string name="emailTypeOther" msgid="2923008695272639549">"Lainnya"</string>
<string name="emailTypeMobile" msgid="119919005321166205">"Seluler"</string>
- <string name="postalTypeCustom" msgid="8903206903060479902">"Ubahsuaian"</string>
+ <string name="postalTypeCustom" msgid="8903206903060479902">"Khusus"</string>
<string name="postalTypeHome" msgid="8165756977184483097">"Rumah"</string>
<string name="postalTypeWork" msgid="5268172772387694495">"Kantor"</string>
<string name="postalTypeOther" msgid="2726111966623584341">"Lainnya"</string>
- <string name="imTypeCustom" msgid="2074028755527826046">"Ubahsuaian"</string>
+ <string name="imTypeCustom" msgid="2074028755527826046">"Khusus"</string>
<string name="imTypeHome" msgid="6241181032954263892">"Rumah"</string>
<string name="imTypeWork" msgid="1371489290242433090">"Kantor"</string>
<string name="imTypeOther" msgid="5377007495735915478">"Lainnya"</string>
- <string name="imProtocolCustom" msgid="6919453836618749992">"Ubahsuaian"</string>
+ <string name="imProtocolCustom" msgid="6919453836618749992">"Khusus"</string>
<string name="imProtocolAim" msgid="7050360612368383417">"AIM"</string>
<string name="imProtocolMsn" msgid="144556545420769442">"Windows Live"</string>
<string name="imProtocolYahoo" msgid="8271439408469021273">"Yahoo"</string>
@@ -691,8 +691,8 @@
<string name="imProtocolNetMeeting" msgid="8287625655986827971">"NetMeeting"</string>
<string name="orgTypeWork" msgid="29268870505363872">"Kantor"</string>
<string name="orgTypeOther" msgid="3951781131570124082">"Lainnya"</string>
- <string name="orgTypeCustom" msgid="225523415372088322">"Ubahsuaian"</string>
- <string name="relationTypeCustom" msgid="3542403679827297300">"Ubahsuaian"</string>
+ <string name="orgTypeCustom" msgid="225523415372088322">"Khusus"</string>
+ <string name="relationTypeCustom" msgid="3542403679827297300">"Khusus"</string>
<string name="relationTypeAssistant" msgid="6274334825195379076">"Asisten"</string>
<string name="relationTypeBrother" msgid="8757913506784067713">"Saudara laki-laki"</string>
<string name="relationTypeChild" msgid="1890746277276881626">"Anak"</string>
@@ -707,7 +707,7 @@
<string name="relationTypeRelative" msgid="1799819930085610271">"Sanak saudara"</string>
<string name="relationTypeSister" msgid="1735983554479076481">"Saudara perempuan"</string>
<string name="relationTypeSpouse" msgid="394136939428698117">"Pasangan"</string>
- <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Ubahsuaian"</string>
+ <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Khusus"</string>
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Beranda"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Kerjaan"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Lainnya"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 65cb688..265da95 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -855,12 +855,9 @@
<string name="searchview_description_clear" msgid="1330281990951833033">"נקה שאילתה"</string>
<string name="searchview_description_submit" msgid="2688450133297983542">"שלח שאילתה"</string>
<string name="searchview_description_voice" msgid="2453203695674994440">"חיפוש קולי"</string>
- <!-- no translation found for enable_explore_by_touch_warning_title (7460694070309730149) -->
- <skip />
- <!-- no translation found for enable_explore_by_touch_warning_message (8655887539089910577) -->
- <skip />
- <!-- no translation found for enable_explore_by_touch_warning_message (2708199672852373195) -->
- <skip />
+ <string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"האם להפעיל את התכונה \'חקור על ידי מגע\'?"</string>
+ <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> רוצה להפעיל את התכונה \'חקור על ידי מגע\'. כאשר התכונה \'חקור על ידי מגע\' מופעלת, אתה יכול לשמוע או לראות תיאורים של הפריטים שעליהם אצבעך מונחת או לקיים אינטראקציה עם הטאבלט באמצעות מחוות."</string>
+ <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> רוצה להפעיל את התכונה \'חקור על ידי מגע\'. כאשר התכונה \'חקור על ידי מגע\' מופעלת, אתה יכול לשמוע או לראות תיאורים של הפריטים שעליהם אצבעך מונחת או לקיים אינטראקציה עם הטלפון באמצעות מחוות."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"לפני חודש אחד"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"לפני חודש אחד"</string>
<plurals name="num_seconds_ago">
@@ -1127,10 +1124,8 @@
<string name="configure_input_methods" msgid="9091652157722495116">"הגדר שיטות קלט"</string>
<string name="use_physical_keyboard" msgid="6203112478095117625">"מקלדת פיזית"</string>
<string name="hardware" msgid="7517821086888990278">"חומרה"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (1407367017263030773) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (4465907700449257063) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"בחירת פריסת מקלדת"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"גע כדי לבחור פריסת מקלדת."</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"מועמדים"</u></string>
@@ -1324,6 +1319,5 @@
<string name="launchBrowserDefault" msgid="2057951947297614725">"להפעיל את הדפדפן?"</string>
<string name="SetupCallDefault" msgid="5834948469253758575">"האם לקבל את השיחה?"</string>
<string name="activity_resolver_use_always" msgid="8017770747801494933">"תמיד"</string>
- <!-- no translation found for activity_resolver_use_once (2404644797149173758) -->
- <skip />
+ <string name="activity_resolver_use_once" msgid="2404644797149173758">"רק פעם אחת"</string>
</resources>
diff --git a/core/res/res/values-large/config.xml b/core/res/res/values-large/config.xml
index 9327200..d1ec4ef 100644
--- a/core/res/res/values-large/config.xml
+++ b/core/res/res/values-large/config.xml
@@ -24,9 +24,6 @@
<dimen name="config_prefDialogWidth">440dp</dimen>
<!-- see comment in values/config.xml -->
- <integer name="config_longPressOnPowerBehavior">2</integer>
-
- <!-- see comment in values/config.xml -->
<integer name="config_longPressOnHomeBehavior">0</integer>
</resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 90398a3..2e019d4 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -317,8 +317,8 @@
<string name="permdesc_readInputState" msgid="8387754901688728043">"Programu omogoča spremljanje tipk, ki jih pritisnete med interakcijo z drugim programom (na primer vnos gesla). Navadni programi tega nikoli ne potrebujejo."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"povezovanje z načinom vnosa"</string>
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Lastniku omogoča, da se poveže z vmesnikom načina vnosa najvišje ravni. Tega nikoli ni treba uporabiti za navadne programe."</string>
- <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"vezano na storitev za ljudi s posebnimi potrebami"</string>
- <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Lastniku omogoča povezovanje z vmesnikom storitve za ljudi s posebnimi potrebami najvišje ravni. Tega nikoli ni treba uporabiti za navadne aplikacije."</string>
+ <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"povezovanje s storitvijo za ljudi s posebnimi potrebami"</string>
+ <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Lastniku omogoča povezovanje z vmesnikom najvišje ravni storitve za ljudi s posebnimi potrebami. Tega nikoli ni treba uporabiti za navadne aplikacije."</string>
<string name="permlab_bindTextService" msgid="7358378401915287938">"poveži z besedilno storitvijo"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Dovoljuje, da se lastnik poveže z vmesnikom besedilne storitve najvišje ravni (npr. SpellCheckerService). Tega nikoli ni treba uporabiti za navadne programe."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"povezava s storitvijo navideznega zasebnega omrežja"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 40345d1..35079c5 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -855,12 +855,9 @@
<string name="searchview_description_clear" msgid="1330281990951833033">"Futa swali"</string>
<string name="searchview_description_submit" msgid="2688450133297983542">"Wasilisha hoja"</string>
<string name="searchview_description_voice" msgid="2453203695674994440">"Utafutaji wa sauti"</string>
- <!-- no translation found for enable_explore_by_touch_warning_title (7460694070309730149) -->
- <skip />
- <!-- no translation found for enable_explore_by_touch_warning_message (8655887539089910577) -->
- <skip />
- <!-- no translation found for enable_explore_by_touch_warning_message (2708199672852373195) -->
- <skip />
+ <string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"Wezesha Kuchunguza kwa Kugusa?"</string>
+ <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> inataka kuwezesha Kuchunguza kwa Kugusa. Wakati Kuchunguza kwa Kugusa kumewezeshwa, unaweza kusikia au kuona maelezo ya ni nini kilichochini ya kidole chako au kufanya ishara za kuingiliana na kumpyuta ndogo."</string>
+ <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> inataka kuwezesha Kuchunguza kwa Kugusa. Wakati Kuchunguza kwa Kugusa kumewezeshwa, unaweza kusikia au kuona maelezo ya ni nini kilichochini ya kidole chako au kufanya ishara za kuingiliana na simu."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"Mwezi 1 uliopita"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Kabla ya mwezi 1 uliopita"</string>
<plurals name="num_seconds_ago">
@@ -1127,10 +1124,8 @@
<string name="configure_input_methods" msgid="9091652157722495116">"Weka mbinu za ingizo"</string>
<string name="use_physical_keyboard" msgid="6203112478095117625">"Kibodi halisi"</string>
<string name="hardware" msgid="7517821086888990278">"Maunzi"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (1407367017263030773) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (4465907700449257063) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Teua mpangilio wa kibodi"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Gusa kuchagua mpangilio wa kibodi."</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"wagombeaji"</u></string>
@@ -1324,6 +1319,5 @@
<string name="launchBrowserDefault" msgid="2057951947297614725">"Zindua Kivinjari?"</string>
<string name="SetupCallDefault" msgid="5834948469253758575">"Kubali simu?"</string>
<string name="activity_resolver_use_always" msgid="8017770747801494933">"Kila mara"</string>
- <!-- no translation found for activity_resolver_use_once (2404644797149173758) -->
- <skip />
+ <string name="activity_resolver_use_once" msgid="2404644797149173758">"Mara moja tu"</string>
</resources>
diff --git a/core/res/res/values-sw600dp/config.xml b/core/res/res/values-sw600dp/config.xml
index b54e9d1..1486d9c 100644
--- a/core/res/res/values-sw600dp/config.xml
+++ b/core/res/res/values-sw600dp/config.xml
@@ -20,9 +20,6 @@
<!-- These resources are around just to allow their values to be customized
for different hardware and product builds. -->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- see comment in values/config.xml -->
- <integer name="config_longPressOnPowerBehavior">2</integer>
-
<!-- Enable lockscreen rotation -->
<bool name="config_enableLockScreenRotation">true</bool>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 8de8e5e..34e4433 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -855,12 +855,9 @@
<string name="searchview_description_clear" msgid="1330281990951833033">"ล้างข้อความค้นหา"</string>
<string name="searchview_description_submit" msgid="2688450133297983542">"ส่งข้อความค้นหา"</string>
<string name="searchview_description_voice" msgid="2453203695674994440">"ค้นหาด้วยเสียง"</string>
- <!-- no translation found for enable_explore_by_touch_warning_title (7460694070309730149) -->
- <skip />
- <!-- no translation found for enable_explore_by_touch_warning_message (8655887539089910577) -->
- <skip />
- <!-- no translation found for enable_explore_by_touch_warning_message (2708199672852373195) -->
- <skip />
+ <string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"เปิดใช้งาน \"สำรวจโดยการแตะ\" หรือไม่"</string>
+ <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> ต้องการเปิดใช้งาน \"สำรวจโดยการแตะ\" เมื่อเปิดใช้งานแล้ว คุณสามารถฟังหรือดูคำอธิบายของสิ่งที่อยู่ใต้นิ้วข​​องคุณ หรือใช้ท่าทางสัมผัสต่างๆ เพื่อโต้ตอบกับแท็บเล็ตได้"</string>
+ <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> ต้องการเปิดใช้งาน \"สำรวจโดยการแตะ\" เมื่อเปิดใช้งานแล้ว คุณสามารถฟังหรือดูคำอธิบายของสิ่งที่อยู่ใต้นิ้วข​​องคุณ หรือใช้ท่าทางสัมผัสต่างๆ เพื่อโต้ตอบกับโทรศัพท์ได้"</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"1 เดือนที่ผ่านมา"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"ก่อน 1 เดือนที่แล้ว"</string>
<plurals name="num_seconds_ago">
@@ -1127,10 +1124,8 @@
<string name="configure_input_methods" msgid="9091652157722495116">"ตั้งค่าวิธีการป้อนข้อมูล"</string>
<string name="use_physical_keyboard" msgid="6203112478095117625">"แป้นพิมพ์บนเครื่อง"</string>
<string name="hardware" msgid="7517821086888990278">"ฮาร์ดแวร์"</string>
- <!-- no translation found for select_keyboard_layout_notification_title (1407367017263030773) -->
- <skip />
- <!-- no translation found for select_keyboard_layout_notification_message (4465907700449257063) -->
- <skip />
+ <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"เลือกรูปแบบแป้นพิมพ์"</string>
+ <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"แตะเพื่อเลือกรูปแบบแป้นพิมพ์"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรลวศษสหฬอฮ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรลวศษสหฬอฮ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"ตัวเลือก"</u></string>
@@ -1324,6 +1319,5 @@
<string name="launchBrowserDefault" msgid="2057951947297614725">"เปิดเบราว์เซอร์หรือไม่"</string>
<string name="SetupCallDefault" msgid="5834948469253758575">"รับสายหรือไม่"</string>
<string name="activity_resolver_use_always" msgid="8017770747801494933">"ทุกครั้ง"</string>
- <!-- no translation found for activity_resolver_use_once (2404644797149173758) -->
- <skip />
+ <string name="activity_resolver_use_once" msgid="2404644797149173758">"เฉพาะครั้งนี้"</string>
</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 7cd2d9d..865761b 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -185,10 +185,10 @@
<string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"使用耗电量较大的功能。"</string>
<string name="permgrouplab_calendar" msgid="5863508437783683902">"日历"</string>
<string name="permgroupdesc_calendar" msgid="5777534316982184416">"直接访问日历和活动。"</string>
- <string name="permgrouplab_dictionary" msgid="4148597128843641379">"读取用户字典"</string>
- <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"读取用户字典中的字词。"</string>
- <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"写入用户字典"</string>
- <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"将字词添加到用户字典。"</string>
+ <string name="permgrouplab_dictionary" msgid="4148597128843641379">"读取用户词典"</string>
+ <string name="permgroupdesc_dictionary" msgid="7921166355964764490">"读取用户词典中的字词。"</string>
+ <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"写入用户词典"</string>
+ <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"将字词添加到用户词典。"</string>
<string name="permgrouplab_bookmarks" msgid="1949519673103968229">"书签和历史记录"</string>
<string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"直接访问书签和浏览器历史记录。"</string>
<string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"闹钟"</string>
@@ -211,7 +211,7 @@
<string name="permgroupdesc_syncSettings" msgid="7603195265129031797">"访问同步设置。"</string>
<string name="permgrouplab_accounts" msgid="3359646291125325519">"您的帐户"</string>
<string name="permgroupdesc_accounts" msgid="4948732641827091312">"访问可用的帐户。"</string>
- <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"硬件控件"</string>
+ <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"硬件控制"</string>
<string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"直接访问手机上的硬件。"</string>
<string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"手机通话"</string>
<string name="permgroupdesc_phoneCalls" msgid="7489701620446183770">"监管、记录和处理电话呼叫。"</string>
@@ -554,7 +554,7 @@
<string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"允许应用获取有关当前同步的 Feed 的详情。"</string>
<string name="permlab_subscribedFeedsWrite" msgid="9015246325408209296">"写入订阅的供稿"</string>
<string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"允许应用修改您当前同步的 Feed。恶意应用可能会更改您的同步 Feed。"</string>
- <string name="permlab_readDictionary" msgid="4107101525746035718">"读取您添加到字典的字词"</string>
+ <string name="permlab_readDictionary" msgid="4107101525746035718">"读取您添加到词典的字词"</string>
<string name="permdesc_readDictionary" msgid="8977815988329283705">"允许应用读取用户可能在用户词典中已存储的任意私有字词、名称和短语。"</string>
<string name="permlab_writeDictionary" msgid="2296383164914812772">"写入用户定义的词典"</string>
<string name="permdesc_writeDictionary" msgid="8185385716255065291">"允许应用向用户词典中写入新词。"</string>
@@ -1111,7 +1111,7 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="5100428757107469454">"如果您打开 USB 存储设备,您正在使用的某些应用将会停止,并且在您关闭 USB 存储设备前都将无法使用。"</string>
<string name="dlg_error_title" msgid="7323658469626514207">"USB 操作失败"</string>
<string name="dlg_ok" msgid="7376953167039865701">"确定"</string>
- <string name="usb_mtp_notification_title" msgid="3699913097391550394">"作为媒体设备连接"</string>
+ <string name="usb_mtp_notification_title" msgid="3699913097391550394">"已作为媒体设备连接"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"作为相机连接"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"作为安装程序连接"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"已连接到 USB 配件"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 2f540a5..e9a3385 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2136,7 +2136,8 @@
query the screen. Note: While not recommended, an accessibility service may
decide to ignore this attribute and operate on all views in the view tree. -->
<attr name="importantForAccessibility" format="integer">
- <!-- The system determines whether the view is important for accessibility (recommended). -->
+ <!-- The system determines whether the view is important for accessibility - default
+ (recommended). -->
<enum name="auto" value="0" />
<!-- The view is important for accessibility. -->
<enum name="yes" value="1" />
@@ -2144,6 +2145,40 @@
<enum name="no" value="2" />
</attr>
+ <!-- @hide Controls whether this view can take accessibility focus. -->
+ <attr name="accessibilityFocusable" format="integer">
+ <!-- The system determines whether the view can take accessibility focus - default
+ (recommended).
+ <p>
+ Such a view is consideted by the focus search if it is:
+ <ul>
+ <li>
+ Important for accessibility and actionable (clickable, long clickable, focusable)
+ </li>
+ <li>
+ Important for accessibility, not actionable (clickable, long clickable, focusable),
+ and does not have an actionable predecessor.
+ </li>
+ </ul>
+ An accessibility srvice can request putting accessibility focus on such a view.
+ </p> -->
+ <enum name="auto" value="0" />
+ <!-- The view can take accessibility focus.
+ <p>
+ A view that can take accessibility focus is always considered during focus
+ search and an accessibility service can request putting accessibility focus
+ on it.
+ </p> -->
+ <enum name="yes" value="1" />
+ <!-- The view can not take accessibility focus.
+ <p>
+ A view that can not take accessibility focus is never considered during focus
+ search and an accessibility service can not request putting accessibility focus
+ on it.
+ </p> -->
+ <enum name="no" value="2" />
+ </attr>
+
</declare-styleable>
<!-- Attributes that can be used with a {@link android.view.ViewGroup} or any
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index b677513..f24733c 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -551,13 +551,13 @@
<enum name="sensorLandscape" value="6" />
<!-- Would like to have the screen in portrait orientation, but can
use the sensor to change which direction the screen is facing. -->
- <enum name="sensorPortait" value="7" />
+ <enum name="sensorPortrait" value="7" />
<!-- Would like to have the screen in landscape orientation, turned in
the opposite direction from normal landscape. -->
<enum name="reverseLandscape" value="8" />
<!-- Would like to have the screen in portrait orientation, turned in
the opposite direction from normal portrait. -->
- <enum name="reversePortait" value="9" />
+ <enum name="reversePortrait" value="9" />
<!-- Orientation is determined by a physical orientation sensor:
the display will rotate based on how the user moves the device.
This allows any of the 4 possible rotations, regardless of what
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 98e7769..09e3fbb 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -577,11 +577,11 @@
<!-- True if WallpaperService is enabled -->
<bool name="config_enableWallpaperService">true</bool>
- <!-- Component name of the service providing network location support. -->
- <string name="config_networkLocationProvider" translatable="false">@null</string>
+ <!-- Package name providing network location support. -->
+ <string name="config_networkLocationProviderPackageName" translatable="false">@null</string>
- <!-- Component name of the service providing geocoder API support. -->
- <string name="config_geocodeProvider" translatable="false">@null</string>
+ <!-- Package name providing geocoder API support. -->
+ <string name="config_geocodeProviderPackageName" translatable="false">@null</string>
<!-- Boolean indicating if current platform supports bluetooth SCO for off call
use cases -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index a143feb..4cfbff5 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1303,6 +1303,9 @@
<java-symbol type="string" name="global_actions_airplane_mode_off_status" />
<java-symbol type="string" name="global_actions_airplane_mode_on_status" />
<java-symbol type="string" name="global_actions_toggle_airplane_mode" />
+ <java-symbol type="string" name="global_action_silent_mode_off_status" />
+ <java-symbol type="string" name="global_action_silent_mode_on_status" />
+ <java-symbol type="string" name="global_action_toggle_silent_mode" />
<java-symbol type="string" name="invalidPuk" />
<java-symbol type="string" name="keyguard_password_enter_pin_code" />
<java-symbol type="string" name="keyguard_password_enter_puk_code" />
@@ -1457,8 +1460,8 @@
<java-symbol type="string" name="car_mode_disable_notification_title" />
<java-symbol type="string" name="chooser_wallpaper" />
<java-symbol type="string" name="config_datause_iface" />
- <java-symbol type="string" name="config_geocodeProvider" />
- <java-symbol type="string" name="config_networkLocationProvider" />
+ <java-symbol type="string" name="config_geocodeProviderPackageName" />
+ <java-symbol type="string" name="config_networkLocationProviderPackageName" />
<java-symbol type="string" name="config_wimaxManagerClassname" />
<java-symbol type="string" name="config_wimaxNativeLibLocation" />
<java-symbol type="string" name="config_wimaxServiceClassname" />