Merge "Make isHostRoute match only host routes" into jb-mr2-dev
diff --git a/Android.mk b/Android.mk
index 8090448..2ad7a72 100644
--- a/Android.mk
+++ b/Android.mk
@@ -195,7 +195,6 @@
core/java/com/android/internal/view/IInputContext.aidl \
core/java/com/android/internal/view/IInputContextCallback.aidl \
core/java/com/android/internal/view/IInputMethod.aidl \
- core/java/com/android/internal/view/IInputMethodCallback.aidl \
core/java/com/android/internal/view/IInputMethodClient.aidl \
core/java/com/android/internal/view/IInputMethodManager.aidl \
core/java/com/android/internal/view/IInputMethodSession.aidl \
@@ -307,7 +306,6 @@
frameworks/base/core/java/com/android/internal/textservice/ITextServicesSessionListener.aidl \
frameworks/base/core/java/com/android/internal/view/IInputContext.aidl \
frameworks/base/core/java/com/android/internal/view/IInputMethod.aidl \
- frameworks/base/core/java/com/android/internal/view/IInputMethodCallback.aidl \
frameworks/base/core/java/com/android/internal/view/IInputMethodClient.aidl \
frameworks/base/core/java/com/android/internal/view/IInputMethodManager.aidl \
frameworks/base/core/java/com/android/internal/view/IInputMethodSession.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index e715a9f..fc63866 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -157,6 +157,8 @@
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/telephony/java/com/android/internal/telephony/SmsRawData.*)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/com/android/internal/view/IInputMethodCallback.*)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/com/android/internal/view/IInputMethodSession.*)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/com/android/internal/view/IInputMethodCallback.*)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************
diff --git a/api/current.txt b/api/current.txt
index cfaa1bb..d1a904a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -12246,6 +12246,14 @@
field public static final int CONTENT_TYPE_VOICE = 3; // 0x3
field public static final java.lang.String EFFECT_AUXILIARY = "Auxiliary";
field public static final java.lang.String EFFECT_INSERT = "Insert";
+ field public static final java.util.UUID EFFECT_TYPE_AEC;
+ field public static final java.util.UUID EFFECT_TYPE_AGC;
+ field public static final java.util.UUID EFFECT_TYPE_BASS_BOOST;
+ field public static final java.util.UUID EFFECT_TYPE_ENV_REVERB;
+ field public static final java.util.UUID EFFECT_TYPE_EQUALIZER;
+ field public static final java.util.UUID EFFECT_TYPE_NS;
+ field public static final java.util.UUID EFFECT_TYPE_PRESET_REVERB;
+ field public static final java.util.UUID EFFECT_TYPE_VIRTUALIZER;
field public static final int ERROR = -1; // 0xffffffff
field public static final int ERROR_BAD_VALUE = -4; // 0xfffffffc
field public static final int ERROR_DEAD_OBJECT = -7; // 0xfffffff9
@@ -17935,6 +17943,13 @@
field public static final java.lang.String TYPE = "data2";
}
+ public static final class ContactsContract.CommonDataKinds.Contactables implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
+ ctor public ContactsContract.CommonDataKinds.Contactables();
+ field public static final android.net.Uri CONTENT_FILTER_URI;
+ field public static final android.net.Uri CONTENT_URI;
+ field public static final java.lang.String VISIBLE_CONTACTS_ONLY = "visible_contacts_only";
+ }
+
public static final class ContactsContract.CommonDataKinds.Email implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
method public static final int getTypeLabelResource(int);
@@ -18228,6 +18243,7 @@
method public static android.net.Uri getContactLookupUri(android.content.ContentResolver, android.net.Uri);
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/data";
field public static final android.net.Uri CONTENT_URI;
+ field public static final java.lang.String VISIBLE_CONTACTS_ONLY = "visible_contacts_only";
}
protected static abstract interface ContactsContract.DataColumns {
@@ -18258,7 +18274,7 @@
field public static final java.lang.String SYNC4 = "data_sync4";
}
- protected static abstract interface ContactsContract.DataColumnsWithJoins implements android.provider.BaseColumns android.provider.ContactsContract.ContactNameColumns android.provider.ContactsContract.ContactOptionsColumns android.provider.ContactsContract.ContactStatusColumns android.provider.ContactsContract.ContactsColumns android.provider.ContactsContract.DataColumns android.provider.ContactsContract.RawContactsColumns android.provider.ContactsContract.StatusColumns {
+ protected static abstract interface ContactsContract.DataColumnsWithJoins implements android.provider.BaseColumns android.provider.ContactsContract.ContactNameColumns android.provider.ContactsContract.ContactOptionsColumns android.provider.ContactsContract.ContactStatusColumns android.provider.ContactsContract.ContactsColumns android.provider.ContactsContract.DataColumns android.provider.ContactsContract.DataUsageStatColumns android.provider.ContactsContract.RawContactsColumns android.provider.ContactsContract.StatusColumns {
}
public static final class ContactsContract.DataUsageFeedback {
@@ -18271,6 +18287,15 @@
field public static final java.lang.String USAGE_TYPE_SHORT_TEXT = "short_text";
}
+ protected static abstract interface ContactsContract.DataUsageStatColumns {
+ field public static final java.lang.String LAST_TIME_USED = "last_time_used";
+ field public static final java.lang.String TIMES_USED = "times_used";
+ field public static final java.lang.String USAGE_TYPE = "usage_type";
+ field public static final int USAGE_TYPE_CALL = 0; // 0x0
+ field public static final int USAGE_TYPE_LONG_TEXT = 1; // 0x1
+ field public static final int USAGE_TYPE_SHORT_TEXT = 2; // 0x2
+ }
+
public static final class ContactsContract.Directory implements android.provider.BaseColumns {
method public static void notifyDirectoryChange(android.content.ContentResolver);
field public static final java.lang.String ACCOUNT_NAME = "accountName";
diff --git a/cmds/wm/src/com/android/commands/wm/Wm.java b/cmds/wm/src/com/android/commands/wm/Wm.java
index f48764f..31eba96 100644
--- a/cmds/wm/src/com/android/commands/wm/Wm.java
+++ b/cmds/wm/src/com/android/commands/wm/Wm.java
@@ -19,6 +19,7 @@
package com.android.commands.wm;
import android.content.Context;
+import android.graphics.Point;
import android.graphics.Rect;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -87,9 +88,22 @@
}
private void runDisplaySize() throws Exception {
- String size = nextArgRequired();
+ String size = nextArg();
int w, h;
- if ("reset".equals(size)) {
+ if (size == null) {
+ Point initialSize = new Point();
+ Point baseSize = new Point();
+ try {
+ mWm.getInitialDisplaySize(Display.DEFAULT_DISPLAY, initialSize);
+ mWm.getBaseDisplaySize(Display.DEFAULT_DISPLAY, baseSize);
+ System.out.println("Physical size: " + initialSize.x + "x" + initialSize.y);
+ if (!initialSize.equals(baseSize)) {
+ System.out.println("Override size: " + baseSize.x + "x" + baseSize.y);
+ }
+ } catch (RemoteException e) {
+ }
+ return;
+ } else if ("reset".equals(size)) {
w = h = -1;
} else {
int div = size.indexOf('x');
@@ -120,9 +134,20 @@
}
private void runDisplayDensity() throws Exception {
- String densityStr = nextArgRequired();
+ String densityStr = nextArg();
int density;
- if ("reset".equals(densityStr)) {
+ if (densityStr == null) {
+ try {
+ int initialDensity = mWm.getInitialDisplayDensity(Display.DEFAULT_DISPLAY);
+ int baseDensity = mWm.getBaseDisplayDensity(Display.DEFAULT_DISPLAY);
+ System.out.println("Physical density: " + initialDensity);
+ if (initialDensity != baseDensity) {
+ System.out.println("Override density: " + baseDensity);
+ }
+ } catch (RemoteException e) {
+ }
+ return;
+ } else if ("reset".equals(densityStr)) {
density = -1;
} else {
try {
@@ -231,7 +256,7 @@
" wm density [reset|DENSITY]\n" +
" wm overscan [reset|LEFT,TOP,RIGHT,BOTTOM]\n" +
"\n" +
- "wm size: override display size.\n" +
+ "wm size: return or override display size.\n" +
"\n" +
"wm density: override display density.\n" +
"\n" +
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index bb73cf4..ae0671b 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4533,6 +4533,8 @@
+ "snatched provider from the jaws of death");
}
prc.removePending = false;
+ // There is a race! It fails to remove the message, which
+ // will be handled in completeRemoveProvider().
mH.removeMessages(H.REMOVE_PROVIDER, prc);
} else {
unstableDelta = 0;
@@ -4712,6 +4714,11 @@
return;
}
+ // More complicated race!! Some client managed to acquire the
+ // provider and release it before the removal was completed.
+ // Continue the removal, and abort the next remove message.
+ prc.removePending = false;
+
final IBinder jBinder = prc.holder.provider.asBinder();
ProviderRefCount existingPrc = mProviderRefCountMap.get(jBinder);
if (existingPrc == prc) {
diff --git a/core/java/android/app/NativeActivity.java b/core/java/android/app/NativeActivity.java
index 396f910..51867bc 100644
--- a/core/java/android/app/NativeActivity.java
+++ b/core/java/android/app/NativeActivity.java
@@ -353,8 +353,7 @@
}
void preDispatchKeyEvent(KeyEvent event, int seq) {
- mIMM.dispatchKeyEvent(this, seq, event,
- mInputMethodCallback);
+ mIMM.dispatchInputEvent(this, seq, event, mInputMethodCallback);
}
void setWindowFlags(int flags, int mask) {
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index e68d23a..1166e4b 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -49,8 +49,8 @@
static final String TAG = "AppWidgetManager";
/**
- * Send this from your {@link AppWidgetHost} activity when you want to pick an AppWidget to display.
- * The AppWidget picker activity will be launched.
+ * Activity action to launch from your {@link AppWidgetHost} activity when you want to
+ * pick an AppWidget to display. The AppWidget picker activity will be launched.
* <p>
* You must supply the following extras:
* <table>
@@ -89,8 +89,8 @@
ACTION_KEYGUARD_APPWIDGET_PICK = "android.appwidget.action.KEYGUARD_APPWIDGET_PICK";
/**
- * Send this from your {@link AppWidgetHost} activity when you want to bind an AppWidget to
- * display and bindAppWidgetIdIfAllowed returns false.
+ * Activity action to launch from your {@link AppWidgetHost} activity when you want to bind
+ * an AppWidget to display and bindAppWidgetIdIfAllowed returns false.
* <p>
* You must supply the following extras:
* <table>
@@ -269,6 +269,9 @@
/**
* Sent when the custom extras for an AppWidget change.
*
+ * <p class="note">This is a protected intent that can only be sent
+ * by the system.
+ *
* @see AppWidgetProvider#onAppWidgetOptionsChanged
* AppWidgetProvider.onAppWidgetOptionsChanged(Context context,
* AppWidgetManager appWidgetManager, int appWidgetId, Bundle newExtras)
@@ -278,6 +281,9 @@
/**
* Sent when an instance of an AppWidget is deleted from its host.
*
+ * <p class="note">This is a protected intent that can only be sent
+ * by the system.
+ *
* @see AppWidgetProvider#onDeleted AppWidgetProvider.onDeleted(Context context, int[] appWidgetIds)
*/
public static final String ACTION_APPWIDGET_DELETED = "android.appwidget.action.APPWIDGET_DELETED";
@@ -285,6 +291,9 @@
/**
* Sent when an instance of an AppWidget is removed from the last host.
*
+ * <p class="note">This is a protected intent that can only be sent
+ * by the system.
+ *
* @see AppWidgetProvider#onEnabled AppWidgetProvider.onEnabled(Context context)
*/
public static final String ACTION_APPWIDGET_DISABLED = "android.appwidget.action.APPWIDGET_DISABLED";
@@ -294,6 +303,9 @@
* This broadcast is sent at boot time if there is a AppWidgetHost installed with
* an instance for this provider.
*
+ * <p class="note">This is a protected intent that can only be sent
+ * by the system.
+ *
* @see AppWidgetProvider#onEnabled AppWidgetProvider.onEnabled(Context context)
*/
public static final String ACTION_APPWIDGET_ENABLED = "android.appwidget.action.APPWIDGET_ENABLED";
diff --git a/core/java/android/content/UriMatcher.java b/core/java/android/content/UriMatcher.java
index 841c8f4..1a8ea47 100644
--- a/core/java/android/content/UriMatcher.java
+++ b/core/java/android/content/UriMatcher.java
@@ -69,6 +69,11 @@
sURIMatcher.addURI("call_log", "calls/#", CALLS_ID);
}
</pre>
+<p>Starting from API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, paths can start
+ with a leading slash. For example:
+<pre>
+ sURIMatcher.addURI("contacts", "/people", PEOPLE);
+</pre>
<p>Then when you need to match against a URI, call {@link #match}, providing
the URL that you have been given. You can use the result to build a query,
return a type, insert or delete a row, or whatever you need, without duplicating
@@ -143,6 +148,9 @@
* matched. URI nodes may be exact match string, the token "*"
* that matches any text, or the token "#" that matches only
* numbers.
+ * <p>
+ * Starting from API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
+ * this method will accept leading slash in the path.
*
* @param authority the authority to match
* @param path the path to match. * may be used as a wild card for
@@ -155,7 +163,17 @@
if (code < 0) {
throw new IllegalArgumentException("code " + code + " is invalid: it must be positive");
}
- String[] tokens = path != null ? PATH_SPLIT_PATTERN.split(path) : null;
+
+ String[] tokens = null;
+ if (path != null) {
+ String newPath = path;
+ // Strip leading slash if present.
+ if (path.length() > 0 && path.charAt(0) == '/') {
+ newPath = path.substring(1);
+ }
+ tokens = PATH_SPLIT_PATTERN.split(newPath);
+ }
+
int numTokens = tokens != null ? tokens.length : 0;
UriMatcher node = this;
for (int i = -1; i < numTokens; i++) {
diff --git a/core/java/android/inputmethodservice/AbstractInputMethodService.java b/core/java/android/inputmethodservice/AbstractInputMethodService.java
index 3c3182a..3531926 100644
--- a/core/java/android/inputmethodservice/AbstractInputMethodService.java
+++ b/core/java/android/inputmethodservice/AbstractInputMethodService.java
@@ -126,11 +126,12 @@
mRevoked = true;
mEnabled = false;
}
-
+
/**
* Take care of dispatching incoming key events to the appropriate
* callbacks on the service, and tell the client when this is done.
*/
+ @Override
public void dispatchKeyEvent(int seq, KeyEvent event, EventCallback callback) {
boolean handled = event.dispatch(AbstractInputMethodService.this,
mDispatcherState, this);
@@ -143,6 +144,7 @@
* Take care of dispatching incoming trackball events to the appropriate
* callbacks on the service, and tell the client when this is done.
*/
+ @Override
public void dispatchTrackballEvent(int seq, MotionEvent event, EventCallback callback) {
boolean handled = onTrackballEvent(event);
if (callback != null) {
@@ -154,6 +156,7 @@
* Take care of dispatching incoming generic motion events to the appropriate
* callbacks on the service, and tell the client when this is done.
*/
+ @Override
public void dispatchGenericMotionEvent(int seq, MotionEvent event, EventCallback callback) {
boolean handled = onGenericMotionEvent(event);
if (callback != null) {
diff --git a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
index d78262b..726dcec 100644
--- a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
@@ -18,15 +18,20 @@
import com.android.internal.os.HandlerCaller;
import com.android.internal.os.SomeArgs;
-import com.android.internal.view.IInputMethodCallback;
import com.android.internal.view.IInputMethodSession;
import android.content.Context;
import android.graphics.Rect;
import android.os.Bundle;
+import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
+import android.util.SparseArray;
+import android.view.InputChannel;
+import android.view.InputDevice;
+import android.view.InputEvent;
+import android.view.InputEventReceiver;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.inputmethod.CompletionInfo;
@@ -36,14 +41,10 @@
class IInputMethodSessionWrapper extends IInputMethodSession.Stub
implements HandlerCaller.Callback {
private static final String TAG = "InputMethodWrapper";
- private static final boolean DEBUG = false;
private static final int DO_FINISH_INPUT = 60;
private static final int DO_DISPLAY_COMPLETIONS = 65;
private static final int DO_UPDATE_EXTRACTED_TEXT = 67;
- private static final int DO_DISPATCH_KEY_EVENT = 70;
- private static final int DO_DISPATCH_TRACKBALL_EVENT = 80;
- private static final int DO_DISPATCH_GENERIC_MOTION_EVENT = 85;
private static final int DO_UPDATE_SELECTION = 90;
private static final int DO_UPDATE_CURSOR = 95;
private static final int DO_APP_PRIVATE_COMMAND = 100;
@@ -53,34 +54,30 @@
HandlerCaller mCaller;
InputMethodSession mInputMethodSession;
-
- // NOTE: we should have a cache of these.
- static class InputMethodEventCallbackWrapper implements InputMethodSession.EventCallback {
- final IInputMethodCallback mCb;
- InputMethodEventCallbackWrapper(IInputMethodCallback cb) {
- mCb = cb;
- }
- public void finishedEvent(int seq, boolean handled) {
- try {
- mCb.finishedEvent(seq, handled);
- } catch (RemoteException e) {
- }
- }
- }
-
+ InputChannel mChannel;
+ ImeInputEventReceiver mReceiver;
+
public IInputMethodSessionWrapper(Context context,
- InputMethodSession inputMethodSession) {
+ InputMethodSession inputMethodSession, InputChannel channel) {
mCaller = new HandlerCaller(context, null,
this, true /*asyncHandler*/);
mInputMethodSession = inputMethodSession;
+ mChannel = channel;
+ if (channel != null) {
+ mReceiver = new ImeInputEventReceiver(channel, context.getMainLooper());
+ }
}
public InputMethodSession getInternalInputMethodSession() {
return mInputMethodSession;
}
+ @Override
public void executeMessage(Message msg) {
- if (mInputMethodSession == null) return;
+ if (mInputMethodSession == null) {
+ // The session has been finished.
+ return;
+ }
switch (msg.what) {
case DO_FINISH_INPUT:
@@ -93,33 +90,6 @@
mInputMethodSession.updateExtractedText(msg.arg1,
(ExtractedText)msg.obj);
return;
- case DO_DISPATCH_KEY_EVENT: {
- SomeArgs args = (SomeArgs)msg.obj;
- mInputMethodSession.dispatchKeyEvent(msg.arg1,
- (KeyEvent)args.arg1,
- new InputMethodEventCallbackWrapper(
- (IInputMethodCallback)args.arg2));
- args.recycle();
- return;
- }
- case DO_DISPATCH_TRACKBALL_EVENT: {
- SomeArgs args = (SomeArgs)msg.obj;
- mInputMethodSession.dispatchTrackballEvent(msg.arg1,
- (MotionEvent)args.arg1,
- new InputMethodEventCallbackWrapper(
- (IInputMethodCallback)args.arg2));
- args.recycle();
- return;
- }
- case DO_DISPATCH_GENERIC_MOTION_EVENT: {
- SomeArgs args = (SomeArgs)msg.obj;
- mInputMethodSession.dispatchGenericMotionEvent(msg.arg1,
- (MotionEvent)args.arg1,
- new InputMethodEventCallbackWrapper(
- (IInputMethodCallback)args.arg2));
- args.recycle();
- return;
- }
case DO_UPDATE_SELECTION: {
SomeArgs args = (SomeArgs)msg.obj;
mInputMethodSession.updateSelection(args.argi1, args.argi2,
@@ -143,7 +113,7 @@
return;
}
case DO_FINISH_SESSION: {
- mInputMethodSession = null;
+ doFinishSession();
return;
}
case DO_VIEW_CLICKED: {
@@ -153,37 +123,37 @@
}
Log.w(TAG, "Unhandled message code: " + msg.what);
}
-
+
+ private void doFinishSession() {
+ mInputMethodSession = null;
+ if (mReceiver != null) {
+ mReceiver.dispose();
+ mReceiver = null;
+ }
+ if (mChannel != null) {
+ mChannel.dispose();
+ mChannel = null;
+ }
+ }
+
+ @Override
public void finishInput() {
mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_FINISH_INPUT));
}
+ @Override
public void displayCompletions(CompletionInfo[] completions) {
mCaller.executeOrSendMessage(mCaller.obtainMessageO(
DO_DISPLAY_COMPLETIONS, completions));
}
-
+
+ @Override
public void updateExtractedText(int token, ExtractedText text) {
mCaller.executeOrSendMessage(mCaller.obtainMessageIO(
DO_UPDATE_EXTRACTED_TEXT, token, text));
}
-
- public void dispatchKeyEvent(int seq, KeyEvent event, IInputMethodCallback callback) {
- mCaller.executeOrSendMessage(mCaller.obtainMessageIOO(DO_DISPATCH_KEY_EVENT, seq,
- event, callback));
- }
- public void dispatchTrackballEvent(int seq, MotionEvent event, IInputMethodCallback callback) {
- mCaller.executeOrSendMessage(mCaller.obtainMessageIOO(DO_DISPATCH_TRACKBALL_EVENT, seq,
- event, callback));
- }
-
- public void dispatchGenericMotionEvent(int seq, MotionEvent event,
- IInputMethodCallback callback) {
- mCaller.executeOrSendMessage(mCaller.obtainMessageIOO(DO_DISPATCH_GENERIC_MOTION_EVENT, seq,
- event, callback));
- }
-
+ @Override
public void updateSelection(int oldSelStart, int oldSelEnd,
int newSelStart, int newSelEnd, int candidatesStart, int candidatesEnd) {
mCaller.executeOrSendMessage(mCaller.obtainMessageIIIIII(DO_UPDATE_SELECTION,
@@ -191,24 +161,74 @@
candidatesStart, candidatesEnd));
}
+ @Override
public void viewClicked(boolean focusChanged) {
- mCaller.executeOrSendMessage(mCaller.obtainMessageI(DO_VIEW_CLICKED, focusChanged ? 1 : 0));
+ mCaller.executeOrSendMessage(
+ mCaller.obtainMessageI(DO_VIEW_CLICKED, focusChanged ? 1 : 0));
}
+ @Override
public void updateCursor(Rect newCursor) {
- mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_UPDATE_CURSOR,
- newCursor));
- }
-
- public void appPrivateCommand(String action, Bundle data) {
- mCaller.executeOrSendMessage(mCaller.obtainMessageOO(DO_APP_PRIVATE_COMMAND, action, data));
- }
-
- public void toggleSoftInput(int showFlags, int hideFlags) {
- mCaller.executeOrSendMessage(mCaller.obtainMessageII(DO_TOGGLE_SOFT_INPUT, showFlags, hideFlags));
+ mCaller.executeOrSendMessage(
+ mCaller.obtainMessageO(DO_UPDATE_CURSOR, newCursor));
}
+ @Override
+ public void appPrivateCommand(String action, Bundle data) {
+ mCaller.executeOrSendMessage(
+ mCaller.obtainMessageOO(DO_APP_PRIVATE_COMMAND, action, data));
+ }
+
+ @Override
+ public void toggleSoftInput(int showFlags, int hideFlags) {
+ mCaller.executeOrSendMessage(
+ mCaller.obtainMessageII(DO_TOGGLE_SOFT_INPUT, showFlags, hideFlags));
+ }
+
+ @Override
public void finishSession() {
mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_FINISH_SESSION));
}
+
+ private final class ImeInputEventReceiver extends InputEventReceiver
+ implements InputMethodSession.EventCallback {
+ private final SparseArray<InputEvent> mPendingEvents = new SparseArray<InputEvent>();
+
+ public ImeInputEventReceiver(InputChannel inputChannel, Looper looper) {
+ super(inputChannel, looper);
+ }
+
+ @Override
+ public void onInputEvent(InputEvent event) {
+ if (mInputMethodSession == null) {
+ // The session has been finished.
+ finishInputEvent(event, false);
+ return;
+ }
+
+ final int seq = event.getSequenceNumber();
+ mPendingEvents.put(seq, event);
+ if (event instanceof KeyEvent) {
+ KeyEvent keyEvent = (KeyEvent)event;
+ mInputMethodSession.dispatchKeyEvent(seq, keyEvent, this);
+ } else {
+ MotionEvent motionEvent = (MotionEvent)event;
+ if (motionEvent.isFromSource(InputDevice.SOURCE_CLASS_TRACKBALL)) {
+ mInputMethodSession.dispatchTrackballEvent(seq, motionEvent, this);
+ } else {
+ mInputMethodSession.dispatchGenericMotionEvent(seq, motionEvent, this);
+ }
+ }
+ }
+
+ @Override
+ public void finishedEvent(int seq, boolean handled) {
+ int index = mPendingEvents.indexOfKey(seq);
+ if (index >= 0) {
+ InputEvent event = mPendingEvents.valueAt(index);
+ mPendingEvents.removeAt(index);
+ finishInputEvent(event, handled);
+ }
+ }
+ }
}
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index 0d981be..9306373 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -32,6 +32,7 @@
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.util.Log;
+import android.view.InputChannel;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputBinding;
import android.view.inputmethod.InputConnection;
@@ -53,7 +54,6 @@
class IInputMethodWrapper extends IInputMethod.Stub
implements HandlerCaller.Callback {
private static final String TAG = "InputMethodWrapper";
- private static final boolean DEBUG = false;
private static final int DO_DUMP = 1;
private static final int DO_ATTACH_TOKEN = 10;
@@ -78,20 +78,29 @@
}
// NOTE: we should have a cache of these.
- static class InputMethodSessionCallbackWrapper implements InputMethod.SessionCallback {
+ static final class InputMethodSessionCallbackWrapper implements InputMethod.SessionCallback {
final Context mContext;
+ final InputChannel mChannel;
final IInputSessionCallback mCb;
- InputMethodSessionCallbackWrapper(Context context, IInputSessionCallback cb) {
+
+ InputMethodSessionCallbackWrapper(Context context, InputChannel channel,
+ IInputSessionCallback cb) {
mContext = context;
+ mChannel = channel;
mCb = cb;
}
+
+ @Override
public void sessionCreated(InputMethodSession session) {
try {
if (session != null) {
IInputMethodSessionWrapper wrap =
- new IInputMethodSessionWrapper(mContext, session);
+ new IInputMethodSessionWrapper(mContext, session, mChannel);
mCb.sessionCreated(wrap);
} else {
+ if (mChannel != null) {
+ mChannel.dispose();
+ }
mCb.sessionCreated(null);
}
} catch (RemoteException e) {
@@ -112,6 +121,7 @@
return mInputMethod.get();
}
+ @Override
public void executeMessage(Message msg) {
InputMethod inputMethod = mInputMethod.get();
// Need a valid reference to the inputMethod for everything except a dump.
@@ -174,8 +184,11 @@
return;
}
case DO_CREATE_SESSION: {
+ SomeArgs args = (SomeArgs)msg.obj;
inputMethod.createSession(new InputMethodSessionCallbackWrapper(
- mCaller.mContext, (IInputSessionCallback)msg.obj));
+ mCaller.mContext, (InputChannel)args.arg1,
+ (IInputSessionCallback)args.arg2));
+ args.recycle();
return;
}
case DO_SET_SESSION_ENABLED:
@@ -197,8 +210,9 @@
}
Log.w(TAG, "Unhandled message code: " + msg.what);
}
-
- @Override protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
AbstractInputMethodService target = mTarget.get();
if (target == null) {
return;
@@ -224,10 +238,12 @@
}
}
+ @Override
public void attachToken(IBinder token) {
mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_ATTACH_TOKEN, token));
}
-
+
+ @Override
public void bindInput(InputBinding binding) {
InputConnection ic = new InputConnectionWrapper(
IInputContext.Stub.asInterface(binding.getConnectionToken()));
@@ -235,24 +251,30 @@
mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_SET_INPUT_CONTEXT, nu));
}
+ @Override
public void unbindInput() {
mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_UNSET_INPUT_CONTEXT));
}
+ @Override
public void startInput(IInputContext inputContext, EditorInfo attribute) {
mCaller.executeOrSendMessage(mCaller.obtainMessageOO(DO_START_INPUT,
inputContext, attribute));
}
+ @Override
public void restartInput(IInputContext inputContext, EditorInfo attribute) {
mCaller.executeOrSendMessage(mCaller.obtainMessageOO(DO_RESTART_INPUT,
inputContext, attribute));
}
- public void createSession(IInputSessionCallback callback) {
- mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_CREATE_SESSION, callback));
+ @Override
+ public void createSession(InputChannel channel, IInputSessionCallback callback) {
+ mCaller.executeOrSendMessage(mCaller.obtainMessageOO(DO_CREATE_SESSION,
+ channel, callback));
}
+ @Override
public void setSessionEnabled(IInputMethodSession session, boolean enabled) {
try {
InputMethodSession ls = ((IInputMethodSessionWrapper)
@@ -263,7 +285,8 @@
Log.w(TAG, "Incoming session not of correct type: " + session, e);
}
}
-
+
+ @Override
public void revokeSession(IInputMethodSession session) {
try {
InputMethodSession ls = ((IInputMethodSessionWrapper)
@@ -273,17 +296,20 @@
Log.w(TAG, "Incoming session not of correct type: " + session, e);
}
}
-
+
+ @Override
public void showSoftInput(int flags, ResultReceiver resultReceiver) {
mCaller.executeOrSendMessage(mCaller.obtainMessageIO(DO_SHOW_SOFT_INPUT,
flags, resultReceiver));
}
-
+
+ @Override
public void hideSoftInput(int flags, ResultReceiver resultReceiver) {
mCaller.executeOrSendMessage(mCaller.obtainMessageIO(DO_HIDE_SOFT_INPUT,
flags, resultReceiver));
}
+ @Override
public void changeInputMethodSubtype(InputMethodSubtype subtype) {
mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_CHANGE_INPUTMETHOD_SUBTYPE,
subtype));
diff --git a/core/java/com/android/internal/view/IInputMethodCallback.aidl b/core/java/android/nfc/BeamShareData.aidl
similarity index 62%
rename from core/java/com/android/internal/view/IInputMethodCallback.aidl
rename to core/java/android/nfc/BeamShareData.aidl
index 717a82d..a47e240 100644
--- a/core/java/com/android/internal/view/IInputMethodCallback.aidl
+++ b/core/java/android/nfc/BeamShareData.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,13 +14,6 @@
* limitations under the License.
*/
-package com.android.internal.view;
+package android.nfc;
-/**
- * Helper interface for IInputMethod to allow the input method to call back
- * to its client with results from incoming calls.
- * {@hide}
- */
-oneway interface IInputMethodCallback {
- void finishedEvent(int seq, boolean handled);
-}
+parcelable BeamShareData;
diff --git a/core/java/android/nfc/BeamShareData.java b/core/java/android/nfc/BeamShareData.java
new file mode 100644
index 0000000..c30ba14
--- /dev/null
+++ b/core/java/android/nfc/BeamShareData.java
@@ -0,0 +1,62 @@
+package android.nfc;
+
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Class to IPC data to be shared over Android Beam.
+ * Allows bundling NdefMessage, Uris and flags in a single
+ * IPC call. This is important as we want to reduce the
+ * amount of IPC calls at "touch time".
+ * @hide
+ */
+public final class BeamShareData implements Parcelable {
+ public final NdefMessage ndefMessage;
+ public final Uri[] uris;
+ public final int flags;
+
+ public BeamShareData(NdefMessage msg, Uri[] uris, int flags) {
+ this.ndefMessage = msg;
+ this.uris = uris;
+ this.flags = flags;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ int urisLength = (uris != null) ? uris.length : 0;
+ dest.writeParcelable(ndefMessage, 0);
+ dest.writeInt(urisLength);
+ if (urisLength > 0) {
+ dest.writeTypedArray(uris, 0);
+ }
+ dest.writeInt(this.flags);
+ }
+
+ public static final Parcelable.Creator<BeamShareData> CREATOR =
+ new Parcelable.Creator<BeamShareData>() {
+ @Override
+ public BeamShareData createFromParcel(Parcel source) {
+ Uri[] uris = null;
+ NdefMessage msg = source.readParcelable(NdefMessage.class.getClassLoader());
+ int numUris = source.readInt();
+ if (numUris > 0) {
+ uris = new Uri[numUris];
+ source.readTypedArray(uris, Uri.CREATOR);
+ }
+ int flags = source.readInt();
+
+ return new BeamShareData(msg, uris, flags);
+ }
+
+ @Override
+ public BeamShareData[] newArray(int size) {
+ return new BeamShareData[size];
+ }
+ };
+}
diff --git a/core/java/android/nfc/INdefPushCallback.aidl b/core/java/android/nfc/INdefPushCallback.aidl
index 1c6d5d0..16771dc 100644
--- a/core/java/android/nfc/INdefPushCallback.aidl
+++ b/core/java/android/nfc/INdefPushCallback.aidl
@@ -16,15 +16,13 @@
package android.nfc;
-import android.nfc.NdefMessage;
-import android.net.Uri;
+import android.nfc.BeamShareData;
/**
* @hide
*/
interface INdefPushCallback
{
- NdefMessage createMessage();
- Uri[] getUris();
+ BeamShareData createBeamShareData();
void onNdefPushComplete();
}
diff --git a/core/java/android/nfc/NfcActivityManager.java b/core/java/android/nfc/NfcActivityManager.java
index 7c3123f..10183c0 100644
--- a/core/java/android/nfc/NfcActivityManager.java
+++ b/core/java/android/nfc/NfcActivityManager.java
@@ -110,6 +110,7 @@
NfcAdapter.OnNdefPushCompleteCallback onNdefPushCompleteCallback = null;
NfcAdapter.CreateBeamUrisCallback uriCallback = null;
Uri[] uris = null;
+ int flags = 0;
public NfcActivityState(Activity activity) {
if (activity.getWindow().isDestroyed()) {
throw new IllegalStateException("activity is already destroyed");
@@ -215,11 +216,12 @@
}
}
- public void setNdefPushMessage(Activity activity, NdefMessage message) {
+ public void setNdefPushMessage(Activity activity, NdefMessage message, int flags) {
boolean isResumed;
synchronized (NfcActivityManager.this) {
NfcActivityState state = getActivityState(activity);
state.ndefMessage = message;
+ state.flags = flags;
isResumed = state.resumed;
}
if (isResumed) {
@@ -228,11 +230,12 @@
}
public void setNdefPushMessageCallback(Activity activity,
- NfcAdapter.CreateNdefMessageCallback callback) {
+ NfcAdapter.CreateNdefMessageCallback callback, int flags) {
boolean isResumed;
synchronized (NfcActivityManager.this) {
NfcActivityState state = getActivityState(activity);
state.ndefMessageCallback = callback;
+ state.flags = flags;
isResumed = state.resumed;
}
if (isResumed) {
@@ -267,38 +270,29 @@
/** Callback from NFC service, usually on binder thread */
@Override
- public NdefMessage createMessage() {
- NfcAdapter.CreateNdefMessageCallback callback;
+ public BeamShareData createBeamShareData() {
+ NfcAdapter.CreateNdefMessageCallback ndefCallback;
+ NfcAdapter.CreateBeamUrisCallback urisCallback;
NdefMessage message;
- synchronized (NfcActivityManager.this) {
- NfcActivityState state = findResumedActivityState();
- if (state == null) return null;
-
- callback = state.ndefMessageCallback;
- message = state.ndefMessage;
- }
-
- // Make callback without lock
- if (callback != null) {
- return callback.createNdefMessage(mDefaultEvent);
- } else {
- return message;
- }
- }
-
- /** Callback from NFC service, usually on binder thread */
- @Override
- public Uri[] getUris() {
Uri[] uris;
- NfcAdapter.CreateBeamUrisCallback callback;
+ int flags;
synchronized (NfcActivityManager.this) {
NfcActivityState state = findResumedActivityState();
if (state == null) return null;
+
+ ndefCallback = state.ndefMessageCallback;
+ urisCallback = state.uriCallback;
+ message = state.ndefMessage;
uris = state.uris;
- callback = state.uriCallback;
+ flags = state.flags;
}
- if (callback != null) {
- uris = callback.createBeamUris(mDefaultEvent);
+
+ // Make callbacks without lock
+ if (ndefCallback != null) {
+ message = ndefCallback.createNdefMessage(mDefaultEvent);
+ }
+ if (urisCallback != null) {
+ uris = urisCallback.createBeamUris(mDefaultEvent);
if (uris != null) {
for (Uri uri : uris) {
if (uri == null) {
@@ -314,10 +308,9 @@
}
}
}
- return uris;
- } else {
- return uris;
}
+
+ return new BeamShareData(message, uris, flags);
}
/** Callback from NFC service, usually on binder thread */
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 6ad382b..ca4a7d6 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -196,6 +196,9 @@
public static final int STATE_TURNING_OFF = 4;
/** @hide */
+ public static final int FLAG_NDEF_PUSH_NO_CONFIRM = 0x1;
+
+ /** @hide */
public static final String ACTION_HANDOVER_TRANSFER_STARTED =
"android.nfc.action.HANDOVER_TRANSFER_STARTED";
@@ -796,12 +799,12 @@
if (activity == null) {
throw new NullPointerException("activity cannot be null");
}
- mNfcActivityManager.setNdefPushMessage(activity, message);
+ mNfcActivityManager.setNdefPushMessage(activity, message, 0);
for (Activity a : activities) {
if (a == null) {
throw new NullPointerException("activities cannot contain null");
}
- mNfcActivityManager.setNdefPushMessage(a, message);
+ mNfcActivityManager.setNdefPushMessage(a, message, 0);
}
} catch (IllegalStateException e) {
if (targetSdkVersion < android.os.Build.VERSION_CODES.JELLY_BEAN) {
@@ -816,6 +819,16 @@
}
/**
+ * @hide
+ */
+ public void setNdefPushMessage(NdefMessage message, Activity activity, int flags) {
+ if (activity == null) {
+ throw new NullPointerException("activity cannot be null");
+ }
+ mNfcActivityManager.setNdefPushMessage(activity, message, flags);
+ }
+
+ /**
* Set a callback that dynamically generates NDEF messages to send using Android Beam (TM).
*
* <p>This method may be called at any time before {@link Activity#onDestroy},
@@ -887,12 +900,12 @@
if (activity == null) {
throw new NullPointerException("activity cannot be null");
}
- mNfcActivityManager.setNdefPushMessageCallback(activity, callback);
+ mNfcActivityManager.setNdefPushMessageCallback(activity, callback, 0);
for (Activity a : activities) {
if (a == null) {
throw new NullPointerException("activities cannot contain null");
}
- mNfcActivityManager.setNdefPushMessageCallback(a, callback);
+ mNfcActivityManager.setNdefPushMessageCallback(a, callback, 0);
}
} catch (IllegalStateException e) {
if (targetSdkVersion < android.os.Build.VERSION_CODES.JELLY_BEAN) {
@@ -907,6 +920,17 @@
}
/**
+ * @hide
+ */
+ public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity,
+ int flags) {
+ if (activity == null) {
+ throw new NullPointerException("activity cannot be null");
+ }
+ mNfcActivityManager.setNdefPushMessageCallback(activity, callback, flags);
+ }
+
+ /**
* Set a callback on successful Android Beam (TM).
*
* <p>This method may be called at any time before {@link Activity#onDestroy},
@@ -1095,7 +1119,7 @@
throw new NullPointerException();
}
enforceResumed(activity);
- mNfcActivityManager.setNdefPushMessage(activity, message);
+ mNfcActivityManager.setNdefPushMessage(activity, message, 0);
}
/**
@@ -1123,8 +1147,8 @@
throw new NullPointerException();
}
enforceResumed(activity);
- mNfcActivityManager.setNdefPushMessage(activity, null);
- mNfcActivityManager.setNdefPushMessageCallback(activity, null);
+ mNfcActivityManager.setNdefPushMessage(activity, null, 0);
+ mNfcActivityManager.setNdefPushMessageCallback(activity, null, 0);
mNfcActivityManager.setOnNdefPushCompleteCallback(activity, null);
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 3f666c1..622308f 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -224,7 +224,7 @@
/**
* Sets all the user-wide restrictions for this user.
- * Requires the {@link android.Manifest.permission#MANAGE_USERS} permission.
+ * Requires the MANAGE_USERS permission.
* @param restrictions the Bundle containing all the restrictions.
*/
public void setUserRestrictions(Bundle restrictions) {
@@ -233,7 +233,7 @@
/**
* Sets all the user-wide restrictions for the specified user.
- * Requires the {@link android.Manifest.permission#MANAGE_USERS} permission.
+ * Requires the MANAGE_USERS permission.
* @param restrictions the Bundle containing all the restrictions.
* @param userHandle the UserHandle of the user for whom to set the restrictions.
*/
@@ -247,10 +247,9 @@
/**
* Sets the value of a specific restriction.
- * Requires the {@link android.Manifest.permission#MANAGE_USERS} permission.
+ * Requires the MANAGE_USERS permission.
* @param key the key of the restriction
* @param value the value for the restriction
- * @param userHandle the user whose restriction is to be changed.
*/
public void setUserRestriction(String key, boolean value) {
Bundle bundle = getUserRestrictions();
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 8f54a38..90bcf1c 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -3793,13 +3793,63 @@
}
/**
+ * Columns in the Data_Usage_Stat table
+ */
+ protected interface DataUsageStatColumns {
+ /** What the referenced {@link Data} was used for.
+ * @see DataUsageStatColumns#USAGE_TYPE_CALL
+ * @see DataUsageStatColumns#USAGE_TYPE_LONG_TEXT
+ * @see DataUsageStatColumns#USAGE_TYPE_SHORT_TEXT
+ */
+ public static final String USAGE_TYPE = "usage_type";
+
+ /** The last time (in milliseconds) this {@link Data} was used. */
+ public static final String LAST_TIME_USED = "last_time_used";
+
+ /** The number of times the referenced {@link Data} has been used for the purpose described
+ * in {@link DataUsageStatColumns#USAGE_TYPE}.
+ */
+ public static final String TIMES_USED = "times_used";
+
+ /**
+ * Integer value for USAGE_TYPE.
+ * This type of usage refers to voice interaction, which includes phone calls, voice chat,
+ * and video chat.
+ *
+ * @see DataUsageFeedback#USAGE_TYPE
+ * @see DataUsageStatColumns#USAGE_TYPE
+ */
+ public static final int USAGE_TYPE_CALL = 0;
+
+ /**
+ * Integer value for USAGE_TYPE.
+ * This type of usage refers to text interaction involving longer messages, which includes
+ * email.
+ *
+ * @see DataUsageFeedback#USAGE_TYPE
+ * @see DataUsageStatColumns#USAGE_TYPE
+ */
+ public static final int USAGE_TYPE_LONG_TEXT = 1;
+
+ /**
+ * Integer value for USAGE_TYPE.
+ * This type of usage for text interaction involving shorter messages, which includes SMS
+ * and text chat with email addresses.
+ *
+ * @see DataUsageFeedback#USAGE_TYPE
+ * @see DataUsageStatColumns#USAGE_TYPE
+ */
+ public static final int USAGE_TYPE_SHORT_TEXT = 2;
+ }
+
+ /**
* Combines all columns returned by {@link ContactsContract.Data} table queries.
*
* @see ContactsContract.Data
*/
protected interface DataColumnsWithJoins extends BaseColumns, DataColumns, StatusColumns,
RawContactsColumns, ContactsColumns, ContactNameColumns, ContactOptionsColumns,
- ContactStatusColumns {
+ ContactStatusColumns, DataUsageStatColumns {
}
/**
@@ -4325,6 +4375,13 @@
public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "data");
/**
+ * A boolean parameter for {@link Data#CONTENT_URI}.
+ * This specifies whether or not the returned data items should be filtered to show
+ * data items belonging to visible contacts only.
+ */
+ public static final String VISIBLE_CONTACTS_ONLY = "visible_contacts_only";
+
+ /**
* The MIME type of the results from {@link #CONTENT_URI}.
*/
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/data";
@@ -6833,6 +6890,38 @@
public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath(CONTENT_URI,
"filter");
}
+
+ /**
+ * A special class of data items, used to refer to types of data that can be used to attempt
+ * to start communicating with a person ({@link Phone} and {@link Email}). Note that this
+ * is NOT a separate data kind.
+ *
+ * This URI allows the ContactsProvider to return a unified result for data items that users
+ * can use to initiate communications with another contact. {@link Phone} and {@link Email}
+ * are the current data types in this category.
+ */
+ public static final class Contactables implements DataColumnsWithJoins, CommonColumns {
+ /**
+ * The content:// style URI for these data items, which requests a directory of data
+ * rows matching the selection criteria.
+ */
+ public static final Uri CONTENT_URI = Uri.withAppendedPath(Data.CONTENT_URI,
+ "contactables");
+
+ /**
+ * The content:// style URI for these data items, which allows for a query parameter to
+ * be appended onto the end to filter for data items matching the query.
+ */
+ public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath(
+ Contactables.CONTENT_URI, "filter");
+
+ /**
+ * A boolean parameter for {@link Data#CONTENT_URI}.
+ * This specifies whether or not the returned data items should be filtered to show
+ * data items belonging to visible contacts only.
+ */
+ public static final String VISIBLE_CONTACTS_ONLY = "visible_contacts_only";
+ }
}
/**
diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java
index 7e9d811..5a88cf6 100644
--- a/core/java/android/text/format/DateUtils.java
+++ b/core/java/android/text/format/DateUtils.java
@@ -39,7 +39,6 @@
{
private static final Object sLock = new Object();
private static Configuration sLastConfig;
- private static java.text.DateFormat sStatusTimeFormat;
private static String sElapsedFormatMMSS;
private static String sElapsedFormatHMMSS;
@@ -95,14 +94,14 @@
// translated.
/**
* This is not actually the preferred 24-hour date format in all locales.
- * @deprecated use {@link java.text.SimpleDateFormat} instead.
+ * @deprecated Use {@link java.text.SimpleDateFormat} instead.
*/
@Deprecated
public static final String HOUR_MINUTE_24 = "%H:%M";
public static final String MONTH_FORMAT = "%B";
/**
* This is not actually a useful month name in all locales.
- * @deprecated use {@link java.text.SimpleDateFormat} instead.
+ * @deprecated Use {@link java.text.SimpleDateFormat} instead.
*/
@Deprecated
public static final String ABBREV_MONTH_FORMAT = "%b";
@@ -118,7 +117,7 @@
// The index is constructed from a bit-wise OR of the boolean values:
// {showTime, showYear, showWeekDay}. For example, if showYear and
// showWeekDay are both true, then the index would be 3.
- /** @deprecated do not use. */
+ /** @deprecated Do not use. */
public static final int sameYearTable[] = {
com.android.internal.R.string.same_year_md1_md2,
com.android.internal.R.string.same_year_wday1_md1_wday2_md2,
@@ -145,7 +144,7 @@
// The index is constructed from a bit-wise OR of the boolean values:
// {showTime, showYear, showWeekDay}. For example, if showYear and
// showWeekDay are both true, then the index would be 3.
- /** @deprecated do not use. */
+ /** @deprecated Do not use. */
public static final int sameMonthTable[] = {
com.android.internal.R.string.same_month_md1_md2,
com.android.internal.R.string.same_month_wday1_md1_wday2_md2,
@@ -172,7 +171,7 @@
*
* @more <p>
* e.g. "Sunday" or "January"
- * @deprecated use {@link java.text.SimpleDateFormat} instead.
+ * @deprecated Use {@link java.text.SimpleDateFormat} instead.
*/
@Deprecated
public static final int LENGTH_LONG = 10;
@@ -183,7 +182,7 @@
*
* @more <p>
* e.g. "Sun" or "Jan"
- * @deprecated use {@link java.text.SimpleDateFormat} instead.
+ * @deprecated Use {@link java.text.SimpleDateFormat} instead.
*/
@Deprecated
public static final int LENGTH_MEDIUM = 20;
@@ -195,7 +194,7 @@
* <p>e.g. "Su" or "Jan"
* <p>In most languages, the results returned for LENGTH_SHORT will be the same as
* the results returned for {@link #LENGTH_MEDIUM}.
- * @deprecated use {@link java.text.SimpleDateFormat} instead.
+ * @deprecated Use {@link java.text.SimpleDateFormat} instead.
*/
@Deprecated
public static final int LENGTH_SHORT = 30;
@@ -204,7 +203,7 @@
* Request an even shorter abbreviated version of the name.
* Do not use this. Currently this will always return the same result
* as {@link #LENGTH_SHORT}.
- * @deprecated use {@link java.text.SimpleDateFormat} instead.
+ * @deprecated Use {@link java.text.SimpleDateFormat} instead.
*/
@Deprecated
public static final int LENGTH_SHORTER = 40;
@@ -216,7 +215,7 @@
* <p>e.g. "S", "T", "T" or "J"
* <p>In some languages, the results returned for LENGTH_SHORTEST will be the same as
* the results returned for {@link #LENGTH_SHORT}.
- * @deprecated use {@link java.text.SimpleDateFormat} instead.
+ * @deprecated Use {@link java.text.SimpleDateFormat} instead.
*/
@Deprecated
public static final int LENGTH_SHORTEST = 50;
@@ -232,7 +231,7 @@
* Undefined lengths will return {@link #LENGTH_MEDIUM}
* but may return something different in the future.
* @throws IndexOutOfBoundsException if the dayOfWeek is out of bounds.
- * @deprecated use {@link java.text.SimpleDateFormat} instead.
+ * @deprecated Use {@link java.text.SimpleDateFormat} instead.
*/
@Deprecated
public static String getDayOfWeekString(int dayOfWeek, int abbrev) {
@@ -254,7 +253,7 @@
* @param ampm Either {@link Calendar#AM Calendar.AM} or {@link Calendar#PM Calendar.PM}.
* @throws IndexOutOfBoundsException if the ampm is out of bounds.
* @return Localized version of "AM" or "PM".
- * @deprecated use {@link java.text.SimpleDateFormat} instead.
+ * @deprecated Use {@link java.text.SimpleDateFormat} instead.
*/
@Deprecated
public static String getAMPMString(int ampm) {
@@ -270,7 +269,7 @@
* Undefined lengths will return {@link #LENGTH_MEDIUM}
* but may return something different in the future.
* @return Localized month of the year.
- * @deprecated use {@link java.text.SimpleDateFormat} instead.
+ * @deprecated Use {@link java.text.SimpleDateFormat} instead.
*/
@Deprecated
public static String getMonthString(int month, int abbrev) {
@@ -514,7 +513,6 @@
Configuration cfg = r.getConfiguration();
if (sLastConfig == null || !sLastConfig.equals(cfg)) {
sLastConfig = cfg;
- sStatusTimeFormat = java.text.DateFormat.getTimeInstance(java.text.DateFormat.SHORT);
sElapsedFormatMMSS = r.getString(com.android.internal.R.string.elapsed_time_short_format_mm_ss);
sElapsedFormatHMMSS = r.getString(com.android.internal.R.string.elapsed_time_short_format_h_mm_ss);
}
@@ -651,99 +649,6 @@
}
/**
- * Return a string containing the date and time in RFC2445 format.
- * Ensures that the time is written in UTC. The Calendar class doesn't
- * really help out with this, so this is slower than it ought to be.
- *
- * @param cal the date and time to write
- * @hide
- * @deprecated use {@link android.text.format.Time}
- */
- public static String writeDateTime(Calendar cal)
- {
- TimeZone tz = TimeZone.getTimeZone("GMT");
- GregorianCalendar c = new GregorianCalendar(tz);
- c.setTimeInMillis(cal.getTimeInMillis());
- return writeDateTime(c, true);
- }
-
- /**
- * Return a string containing the date and time in RFC2445 format.
- *
- * @param cal the date and time to write
- * @param zulu If the calendar is in UTC, pass true, and a Z will
- * be written at the end as per RFC2445. Otherwise, the time is
- * considered in localtime.
- * @hide
- * @deprecated use {@link android.text.format.Time}
- */
- public static String writeDateTime(Calendar cal, boolean zulu)
- {
- StringBuilder sb = new StringBuilder();
- sb.ensureCapacity(16);
- if (zulu) {
- sb.setLength(16);
- sb.setCharAt(15, 'Z');
- } else {
- sb.setLength(15);
- }
- return writeDateTime(cal, sb);
- }
-
- /**
- * Return a string containing the date and time in RFC2445 format.
- *
- * @param cal the date and time to write
- * @param sb a StringBuilder to use. It is assumed that setLength
- * has already been called on sb to the appropriate length
- * which is sb.setLength(zulu ? 16 : 15)
- * @hide
- * @deprecated use {@link android.text.format.Time}
- */
- public static String writeDateTime(Calendar cal, StringBuilder sb)
- {
- int n;
-
- n = cal.get(Calendar.YEAR);
- sb.setCharAt(3, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(2, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(1, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(0, (char)('0'+n%10));
-
- n = cal.get(Calendar.MONTH) + 1;
- sb.setCharAt(5, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(4, (char)('0'+n%10));
-
- n = cal.get(Calendar.DAY_OF_MONTH);
- sb.setCharAt(7, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(6, (char)('0'+n%10));
-
- sb.setCharAt(8, 'T');
-
- n = cal.get(Calendar.HOUR_OF_DAY);
- sb.setCharAt(10, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(9, (char)('0'+n%10));
-
- n = cal.get(Calendar.MINUTE);
- sb.setCharAt(12, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(11, (char)('0'+n%10));
-
- n = cal.get(Calendar.SECOND);
- sb.setCharAt(14, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(13, (char)('0'+n%10));
-
- return sb.toString();
- }
-
- /**
* Formats a date or a time range according to the local conventions.
* <p>
* Note that this is a convenience method. Using it involves creating an
diff --git a/core/java/android/text/format/Formatter.java b/core/java/android/text/format/Formatter.java
index 121c6f2..9c98b98 100644
--- a/core/java/android/text/format/Formatter.java
+++ b/core/java/android/text/format/Formatter.java
@@ -95,16 +95,12 @@
}
/**
- * Returns a string in the canonical IP format ###.###.###.### from a packed integer containing
- * the IP address. The IP address is expected to be in little-endian format (LSB first). That
- * is, 0x01020304 will return "4.3.2.1".
+ * Returns a string in the canonical IPv4 format ###.###.###.### from a packed integer
+ * containing the IP address. The IPv4 address is expected to be in little-endian
+ * format (LSB first). That is, 0x01020304 will return "4.3.2.1".
*
- * @param ipv4Address the IP address as a packed integer with LSB first.
- * @return string with canonical IP address format.
- *
- * @deprecated this method doesn't support IPv6 addresses. Prefer {@link
- * java.net.InetAddress#getHostAddress()}, which supports both IPv4 and
- * IPv6 addresses.
+ * @deprecated Use {@link java.net.InetAddress#getHostAddress()}, which supports both IPv4 and
+ * IPv6 addresses. This method does not support IPv6 addresses.
*/
@Deprecated
public static String formatIpAddress(int ipv4Address) {
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index e086f5a..7918823 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -428,6 +428,8 @@
interface HardwareDrawCallbacks {
/**
* Invoked before a view is drawn by a hardware renderer.
+ * This method can be used to apply transformations to the
+ * canvas but no drawing command should be issued.
*
* @param canvas The Canvas used to render the view.
*/
@@ -435,6 +437,7 @@
/**
* Invoked after a view is drawn by a hardware renderer.
+ * It is safe to invoke drawing commands from this method.
*
* @param canvas The Canvas used to render the view.
*/
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index f0c6241..a85a558 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -60,8 +60,12 @@
in IInputContext inputContext);
boolean inputMethodClientHasFocus(IInputMethodClient client);
+ void getInitialDisplaySize(int displayId, out Point size);
+ void getBaseDisplaySize(int displayId, out Point size);
void setForcedDisplaySize(int displayId, int width, int height);
void clearForcedDisplaySize(int displayId);
+ int getInitialDisplayDensity(int displayId);
+ int getBaseDisplayDensity(int displayId);
void setForcedDisplayDensity(int displayId, int density);
void clearForcedDisplayDensity(int displayId);
diff --git a/core/java/android/view/InputChannel.java b/core/java/android/view/InputChannel.java
index 523af04..a797176 100644
--- a/core/java/android/view/InputChannel.java
+++ b/core/java/android/view/InputChannel.java
@@ -78,7 +78,9 @@
* Creates a new input channel pair. One channel should be provided to the input
* dispatcher and the other to the application's input queue.
* @param name The descriptive (non-unique) name of the channel pair.
- * @return A pair of input channels. They are symmetric and indistinguishable.
+ * @return A pair of input channels. The first channel is designated as the
+ * server channel and should be used to publish input events. The second channel
+ * is designated as the client channel and should be used to consume input events.
*/
public static InputChannel[] openInputChannelPair(String name) {
if (name == null) {
@@ -123,10 +125,11 @@
nativeTransferTo(outParameter);
}
+ @Override
public int describeContents() {
return Parcelable.CONTENTS_FILE_DESCRIPTOR;
}
-
+
public void readFromParcel(Parcel in) {
if (in == null) {
throw new IllegalArgumentException("in must not be null");
@@ -134,7 +137,8 @@
nativeReadFromParcel(in);
}
-
+
+ @Override
public void writeToParcel(Parcel out, int flags) {
if (out == null) {
throw new IllegalArgumentException("out must not be null");
diff --git a/core/java/android/view/InputEventSender.java b/core/java/android/view/InputEventSender.java
new file mode 100644
index 0000000..adf63fe
--- /dev/null
+++ b/core/java/android/view/InputEventSender.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import dalvik.system.CloseGuard;
+
+import android.os.Looper;
+import android.os.MessageQueue;
+import android.util.Log;
+
+/**
+ * Provides a low-level mechanism for an application to send input events.
+ * @hide
+ */
+public abstract class InputEventSender {
+ private static final String TAG = "InputEventSender";
+
+ private final CloseGuard mCloseGuard = CloseGuard.get();
+
+ private int mSenderPtr;
+
+ // We keep references to the input channel and message queue objects here so that
+ // they are not GC'd while the native peer of the receiver is using them.
+ private InputChannel mInputChannel;
+ private MessageQueue mMessageQueue;
+
+ private static native int nativeInit(InputEventSender sender,
+ InputChannel inputChannel, MessageQueue messageQueue);
+ private static native void nativeDispose(int senderPtr);
+ private static native boolean nativeSendKeyEvent(int senderPtr, int seq, KeyEvent event);
+ private static native boolean nativeSendMotionEvent(int senderPtr, int seq, MotionEvent event);
+
+ /**
+ * Creates an input event sender bound to the specified input channel.
+ *
+ * @param inputChannel The input channel.
+ * @param looper The looper to use when invoking callbacks.
+ */
+ public InputEventSender(InputChannel inputChannel, Looper looper) {
+ if (inputChannel == null) {
+ throw new IllegalArgumentException("inputChannel must not be null");
+ }
+ if (looper == null) {
+ throw new IllegalArgumentException("looper must not be null");
+ }
+
+ mInputChannel = inputChannel;
+ mMessageQueue = looper.getQueue();
+ mSenderPtr = nativeInit(this, inputChannel, mMessageQueue);
+
+ mCloseGuard.open("dispose");
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ dispose(true);
+ } finally {
+ super.finalize();
+ }
+ }
+
+ /**
+ * Disposes the receiver.
+ */
+ public void dispose() {
+ dispose(false);
+ }
+
+ private void dispose(boolean finalized) {
+ if (mCloseGuard != null) {
+ if (finalized) {
+ mCloseGuard.warnIfOpen();
+ }
+ mCloseGuard.close();
+ }
+
+ if (mSenderPtr != 0) {
+ nativeDispose(mSenderPtr);
+ mSenderPtr = 0;
+ }
+ mInputChannel = null;
+ mMessageQueue = null;
+ }
+
+ /**
+ * Called when an input event is finished.
+ *
+ * @param seq The input event sequence number.
+ * @param handled True if the input event was handled.
+ */
+ public void onInputEventFinished(int seq, boolean handled) {
+ }
+
+ /**
+ * Sends an input event.
+ * Must be called on the same Looper thread to which the sender is attached.
+ *
+ * @param seq The input event sequence number.
+ * @param event The input event to send.
+ * @return True if the entire event was sent successfully. May return false
+ * if the input channel buffer filled before all samples were dispatched.
+ */
+ public final boolean sendInputEvent(int seq, InputEvent event) {
+ if (event == null) {
+ throw new IllegalArgumentException("event must not be null");
+ }
+ if (mSenderPtr == 0) {
+ Log.w(TAG, "Attempted to send an input event but the input event "
+ + "sender has already been disposed.");
+ return false;
+ }
+
+ if (event instanceof KeyEvent) {
+ return nativeSendKeyEvent(mSenderPtr, seq, (KeyEvent)event);
+ } else {
+ return nativeSendMotionEvent(mSenderPtr, seq, (MotionEvent)event);
+ }
+ }
+
+ // Called from native code.
+ @SuppressWarnings("unused")
+ private void dispatchInputEventFinished(int seq, boolean handled) {
+ onInputEventFinished(seq, handled);
+ }
+}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 688e17e..98edeae 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -51,6 +51,8 @@
import java.util.Collections;
import java.util.HashSet;
+import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
+
/**
* <p>
* A <code>ViewGroup</code> is a special view that can contain other views
@@ -5864,7 +5866,7 @@
* to this field.
*/
@ViewDebug.ExportedProperty(category = "layout")
- private int startMargin = DEFAULT_RELATIVE;
+ private int startMargin = DEFAULT_MARGIN_RELATIVE;
/**
* The end margin in pixels of the child.
@@ -5872,21 +5874,21 @@
* to this field.
*/
@ViewDebug.ExportedProperty(category = "layout")
- private int endMargin = DEFAULT_RELATIVE;
+ private int endMargin = DEFAULT_MARGIN_RELATIVE;
/**
* The default start and end margin.
* @hide
*/
- public static final int DEFAULT_RELATIVE = Integer.MIN_VALUE;
+ public static final int DEFAULT_MARGIN_RELATIVE = Integer.MIN_VALUE;
- private int initialLeftMargin;
- private int initialRightMargin;
+ // Layout direction is LTR by default
+ private int mLayoutDirection = LAYOUT_DIRECTION_LTR;
- private static int LAYOUT_DIRECTION_UNDEFINED = -1;
+ private static int DEFAULT_MARGIN_RESOLVED = 0;
- // Layout direction undefined by default
- private int layoutDirection = LAYOUT_DIRECTION_UNDEFINED;
+ private boolean mNeedResolution = false;
+ private boolean mIsRtlCompatibilityMode = true;
/**
* Creates a new set of layout parameters. The values are extracted from
@@ -5913,21 +5915,30 @@
bottomMargin = margin;
} else {
leftMargin = a.getDimensionPixelSize(
- R.styleable.ViewGroup_MarginLayout_layout_marginLeft, 0);
+ R.styleable.ViewGroup_MarginLayout_layout_marginLeft,
+ DEFAULT_MARGIN_RESOLVED);
topMargin = a.getDimensionPixelSize(
- R.styleable.ViewGroup_MarginLayout_layout_marginTop, 0);
+ R.styleable.ViewGroup_MarginLayout_layout_marginTop,
+ DEFAULT_MARGIN_RESOLVED);
rightMargin = a.getDimensionPixelSize(
- R.styleable.ViewGroup_MarginLayout_layout_marginRight, 0);
+ R.styleable.ViewGroup_MarginLayout_layout_marginRight,
+ DEFAULT_MARGIN_RESOLVED);
bottomMargin = a.getDimensionPixelSize(
- R.styleable.ViewGroup_MarginLayout_layout_marginBottom, 0);
+ R.styleable.ViewGroup_MarginLayout_layout_marginBottom,
+ DEFAULT_MARGIN_RESOLVED);
startMargin = a.getDimensionPixelSize(
- R.styleable.ViewGroup_MarginLayout_layout_marginStart, DEFAULT_RELATIVE);
+ R.styleable.ViewGroup_MarginLayout_layout_marginStart,
+ DEFAULT_MARGIN_RELATIVE);
endMargin = a.getDimensionPixelSize(
- R.styleable.ViewGroup_MarginLayout_layout_marginEnd, DEFAULT_RELATIVE);
+ R.styleable.ViewGroup_MarginLayout_layout_marginEnd,
+ DEFAULT_MARGIN_RELATIVE);
+
+ mNeedResolution = isMarginRelative();
}
- initialLeftMargin = leftMargin;
- initialRightMargin = rightMargin;
+ final boolean hasRtlSupport = c.getApplicationInfo().hasRtlSupport();
+ final int targetSdkVersion = c.getApplicationInfo().targetSdkVersion;
+ mIsRtlCompatibilityMode = targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport;
a.recycle();
}
@@ -5937,6 +5948,9 @@
*/
public MarginLayoutParams(int width, int height) {
super(width, height);
+
+ mNeedResolution = false;
+ mIsRtlCompatibilityMode = false;
}
/**
@@ -5955,10 +5969,10 @@
this.startMargin = source.startMargin;
this.endMargin = source.endMargin;
- this.initialLeftMargin = source.leftMargin;
- this.initialRightMargin = source.rightMargin;
+ this.mNeedResolution = source.mNeedResolution;
+ this.mIsRtlCompatibilityMode = source.mIsRtlCompatibilityMode;
- setLayoutDirection(source.layoutDirection);
+ setLayoutDirection(source.mLayoutDirection);
}
/**
@@ -5966,6 +5980,9 @@
*/
public MarginLayoutParams(LayoutParams source) {
super(source);
+
+ mNeedResolution = false;
+ mIsRtlCompatibilityMode = false;
}
/**
@@ -5988,8 +6005,7 @@
topMargin = top;
rightMargin = right;
bottomMargin = bottom;
- initialLeftMargin = left;
- initialRightMargin = right;
+ mNeedResolution = isMarginRelative();
}
/**
@@ -6015,8 +6031,7 @@
topMargin = top;
endMargin = end;
bottomMargin = bottom;
- initialLeftMargin = 0;
- initialRightMargin = 0;
+ mNeedResolution = true;
}
/**
@@ -6028,6 +6043,7 @@
*/
public void setMarginStart(int start) {
startMargin = start;
+ mNeedResolution = true;
}
/**
@@ -6038,8 +6054,11 @@
* @return the start margin in pixels.
*/
public int getMarginStart() {
- if (startMargin != DEFAULT_RELATIVE) return startMargin;
- switch(layoutDirection) {
+ if (startMargin != DEFAULT_MARGIN_RELATIVE) return startMargin;
+ if (mNeedResolution) {
+ doResolveMargins();
+ }
+ switch(mLayoutDirection) {
case View.LAYOUT_DIRECTION_RTL:
return rightMargin;
case View.LAYOUT_DIRECTION_LTR:
@@ -6057,6 +6076,7 @@
*/
public void setMarginEnd(int end) {
endMargin = end;
+ mNeedResolution = true;
}
/**
@@ -6067,8 +6087,11 @@
* @return the end margin in pixels.
*/
public int getMarginEnd() {
- if (endMargin != DEFAULT_RELATIVE) return endMargin;
- switch(layoutDirection) {
+ if (endMargin != DEFAULT_MARGIN_RELATIVE) return endMargin;
+ if (mNeedResolution) {
+ doResolveMargins();
+ }
+ switch(mLayoutDirection) {
case View.LAYOUT_DIRECTION_RTL:
return leftMargin;
case View.LAYOUT_DIRECTION_LTR:
@@ -6086,7 +6109,7 @@
* @return true if either marginStart or marginEnd has been set.
*/
public boolean isMarginRelative() {
- return (startMargin != DEFAULT_RELATIVE) || (endMargin != DEFAULT_RELATIVE);
+ return (startMargin != DEFAULT_MARGIN_RELATIVE || endMargin != DEFAULT_MARGIN_RELATIVE);
}
/**
@@ -6098,7 +6121,10 @@
public void setLayoutDirection(int layoutDirection) {
if (layoutDirection != View.LAYOUT_DIRECTION_LTR &&
layoutDirection != View.LAYOUT_DIRECTION_RTL) return;
- this.layoutDirection = layoutDirection;
+ if (layoutDirection != this.mLayoutDirection) {
+ this.mLayoutDirection = layoutDirection;
+ this.mNeedResolution = isMarginRelative();
+ }
}
/**
@@ -6108,7 +6134,7 @@
* @return the layout direction.
*/
public int getLayoutDirection() {
- return layoutDirection;
+ return mLayoutDirection;
}
/**
@@ -6119,26 +6145,41 @@
public void resolveLayoutDirection(int layoutDirection) {
setLayoutDirection(layoutDirection);
- if (!isMarginRelative()) return;
+ // No relative margin or pre JB-MR1 case or no need to resolve, just dont do anything
+ // Will use the left and right margins if no relative margin is defined.
+ if (!isMarginRelative() || !mNeedResolution || mIsRtlCompatibilityMode) return;
- switch(layoutDirection) {
+ // Proceed with resolution
+ doResolveMargins();
+ }
+
+ private void doResolveMargins() {
+ // We have some relative margins (either the start one or the end one or both). So use
+ // them and override what has been defined for left and right margins. If either start
+ // or end margin is not defined, just set it to default "0".
+ switch(mLayoutDirection) {
case View.LAYOUT_DIRECTION_RTL:
- leftMargin = (endMargin > DEFAULT_RELATIVE) ? endMargin : initialLeftMargin;
- rightMargin = (startMargin > DEFAULT_RELATIVE) ? startMargin : initialRightMargin;
+ leftMargin = (endMargin > DEFAULT_MARGIN_RELATIVE) ?
+ endMargin : DEFAULT_MARGIN_RESOLVED;
+ rightMargin = (startMargin > DEFAULT_MARGIN_RELATIVE) ?
+ startMargin : DEFAULT_MARGIN_RESOLVED;
break;
case View.LAYOUT_DIRECTION_LTR:
default:
- leftMargin = (startMargin > DEFAULT_RELATIVE) ? startMargin : initialLeftMargin;
- rightMargin = (endMargin > DEFAULT_RELATIVE) ? endMargin : initialRightMargin;
+ leftMargin = (startMargin > DEFAULT_MARGIN_RELATIVE) ?
+ startMargin : DEFAULT_MARGIN_RESOLVED;
+ rightMargin = (endMargin > DEFAULT_MARGIN_RELATIVE) ?
+ endMargin : DEFAULT_MARGIN_RESOLVED;
break;
}
+ mNeedResolution = false;
}
/**
* @hide
*/
public boolean isLayoutRtl() {
- return (layoutDirection == View.LAYOUT_DIRECTION_RTL);
+ return (mLayoutDirection == View.LAYOUT_DIRECTION_RTL);
}
/**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index b30dc83..7b34ce1 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2937,7 +2937,6 @@
private final static int MSG_DISPATCH_KEY = 7;
private final static int MSG_DISPATCH_APP_VISIBILITY = 8;
private final static int MSG_DISPATCH_GET_NEW_SURFACE = 9;
- private final static int MSG_IME_FINISHED_EVENT = 10;
private final static int MSG_DISPATCH_KEY_FROM_IME = 11;
private final static int MSG_FINISH_INPUT_CONNECTION = 12;
private final static int MSG_CHECK_FOCUS = 13;
@@ -2952,6 +2951,8 @@
private final static int MSG_DISPATCH_DONE_ANIMATING = 22;
private final static int MSG_INVALIDATE_WORLD = 23;
private final static int MSG_WINDOW_MOVED = 24;
+ private final static int MSG_ENQUEUE_X_AXIS_KEY_REPEAT = 25;
+ private final static int MSG_ENQUEUE_Y_AXIS_KEY_REPEAT = 26;
final class ViewRootHandler extends Handler {
@Override
@@ -2975,8 +2976,6 @@
return "MSG_DISPATCH_APP_VISIBILITY";
case MSG_DISPATCH_GET_NEW_SURFACE:
return "MSG_DISPATCH_GET_NEW_SURFACE";
- case MSG_IME_FINISHED_EVENT:
- return "MSG_IME_FINISHED_EVENT";
case MSG_DISPATCH_KEY_FROM_IME:
return "MSG_DISPATCH_KEY_FROM_IME";
case MSG_FINISH_INPUT_CONNECTION:
@@ -3003,6 +3002,10 @@
return "MSG_DISPATCH_DONE_ANIMATING";
case MSG_WINDOW_MOVED:
return "MSG_WINDOW_MOVED";
+ case MSG_ENQUEUE_X_AXIS_KEY_REPEAT:
+ return "MSG_ENQUEUE_X_AXIS_KEY_REPEAT";
+ case MSG_ENQUEUE_Y_AXIS_KEY_REPEAT:
+ return "MSG_ENQUEUE_Y_AXIS_KEY_REPEAT";
}
return super.getMessageName(message);
}
@@ -3018,9 +3021,6 @@
info.target.invalidate(info.left, info.top, info.right, info.bottom);
info.recycle();
break;
- case MSG_IME_FINISHED_EVENT:
- handleImeFinishedEvent(msg.arg1, msg.arg2 != 0);
- break;
case MSG_PROCESS_INPUT_EVENTS:
mProcessInputEventsScheduled = false;
doProcessInputEvents();
@@ -3229,6 +3229,18 @@
invalidateWorld(mView);
}
} break;
+ case MSG_ENQUEUE_X_AXIS_KEY_REPEAT:
+ case MSG_ENQUEUE_Y_AXIS_KEY_REPEAT: {
+ KeyEvent oldEvent = (KeyEvent)msg.obj;
+ KeyEvent e = KeyEvent.changeTimeRepeat(oldEvent, SystemClock.uptimeMillis(),
+ oldEvent.getRepeatCount() + 1);
+ if (mAttachInfo.mHasWindowFocus) {
+ enqueueInputEvent(e);
+ Message m = obtainMessage(msg.what, e);
+ m.setAsynchronous(true);
+ sendMessageDelayed(m, mViewConfiguration.getKeyRepeatDelay());
+ }
+ } break;
}
}
}
@@ -3444,26 +3456,15 @@
mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
}
+ int result = EVENT_POST_IME;
if (mView != null && mAdded && (q.mFlags & QueuedInputEvent.FLAG_DELIVER_POST_IME) == 0) {
if (LOCAL_LOGV)
Log.v(TAG, "Dispatching trackball " + event + " to " + mView);
// Dispatch to the IME before propagating down the view hierarchy.
- // The IME will eventually call back into handleImeFinishedEvent.
- if (mLastWasImTarget) {
- InputMethodManager imm = InputMethodManager.peekInstance();
- if (imm != null) {
- final int seq = event.getSequenceNumber();
- if (DEBUG_IMF)
- Log.v(TAG, "Sending trackball event to IME: seq="
- + seq + " event=" + event);
- return imm.dispatchTrackballEvent(mView.getContext(), seq, event,
- mInputMethodCallback);
- }
- }
+ result = dispatchImeInputEvent(q);
}
-
- return EVENT_POST_IME;
+ return result;
}
private int deliverTrackballEventPostIme(QueuedInputEvent q) {
@@ -3598,26 +3599,16 @@
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
}
+
+ int result = EVENT_POST_IME;
if (mView != null && mAdded && (q.mFlags & QueuedInputEvent.FLAG_DELIVER_POST_IME) == 0) {
if (LOCAL_LOGV)
Log.v(TAG, "Dispatching generic motion " + event + " to " + mView);
// Dispatch to the IME before propagating down the view hierarchy.
- // The IME will eventually call back into handleImeFinishedEvent.
- if (mLastWasImTarget) {
- InputMethodManager imm = InputMethodManager.peekInstance();
- if (imm != null) {
- final int seq = event.getSequenceNumber();
- if (DEBUG_IMF)
- Log.v(TAG, "Sending generic motion event to IME: seq="
- + seq + " event=" + event);
- return imm.dispatchGenericMotionEvent(mView.getContext(), seq, event,
- mInputMethodCallback);
- }
- }
+ result = dispatchImeInputEvent(q);
}
-
- return EVENT_POST_IME;
+ return result;
}
private int deliverGenericMotionEventPostIme(QueuedInputEvent q) {
@@ -3677,6 +3668,7 @@
if (xDirection != mLastJoystickXDirection) {
if (mLastJoystickXKeyCode != 0) {
+ mHandler.removeMessages(MSG_ENQUEUE_X_AXIS_KEY_REPEAT);
enqueueInputEvent(new KeyEvent(time, time,
KeyEvent.ACTION_UP, mLastJoystickXKeyCode, 0, metaState,
deviceId, 0, KeyEvent.FLAG_FALLBACK, source));
@@ -3688,14 +3680,19 @@
if (xDirection != 0 && synthesizeNewKeys) {
mLastJoystickXKeyCode = xDirection > 0
? KeyEvent.KEYCODE_DPAD_RIGHT : KeyEvent.KEYCODE_DPAD_LEFT;
- enqueueInputEvent(new KeyEvent(time, time,
+ final KeyEvent e = new KeyEvent(time, time,
KeyEvent.ACTION_DOWN, mLastJoystickXKeyCode, 0, metaState,
- deviceId, 0, KeyEvent.FLAG_FALLBACK, source));
+ deviceId, 0, KeyEvent.FLAG_FALLBACK, source);
+ enqueueInputEvent(e);
+ Message m = mHandler.obtainMessage(MSG_ENQUEUE_X_AXIS_KEY_REPEAT, e);
+ m.setAsynchronous(true);
+ mHandler.sendMessageDelayed(m, mViewConfiguration.getKeyRepeatTimeout());
}
}
if (yDirection != mLastJoystickYDirection) {
if (mLastJoystickYKeyCode != 0) {
+ mHandler.removeMessages(MSG_ENQUEUE_Y_AXIS_KEY_REPEAT);
enqueueInputEvent(new KeyEvent(time, time,
KeyEvent.ACTION_UP, mLastJoystickYKeyCode, 0, metaState,
deviceId, 0, KeyEvent.FLAG_FALLBACK, source));
@@ -3707,9 +3704,13 @@
if (yDirection != 0 && synthesizeNewKeys) {
mLastJoystickYKeyCode = yDirection > 0
? KeyEvent.KEYCODE_DPAD_DOWN : KeyEvent.KEYCODE_DPAD_UP;
- enqueueInputEvent(new KeyEvent(time, time,
+ final KeyEvent e = new KeyEvent(time, time,
KeyEvent.ACTION_DOWN, mLastJoystickYKeyCode, 0, metaState,
- deviceId, 0, KeyEvent.FLAG_FALLBACK, source));
+ deviceId, 0, KeyEvent.FLAG_FALLBACK, source);
+ enqueueInputEvent(e);
+ Message m = mHandler.obtainMessage(MSG_ENQUEUE_Y_AXIS_KEY_REPEAT, e);
+ m.setAsynchronous(true);
+ mHandler.sendMessageDelayed(m, mViewConfiguration.getKeyRepeatTimeout());
}
}
}
@@ -3806,6 +3807,7 @@
mInputEventConsistencyVerifier.onKeyEvent(event, 0);
}
+ int result = EVENT_POST_IME;
if (mView != null && mAdded && (q.mFlags & QueuedInputEvent.FLAG_DELIVER_POST_IME) == 0) {
if (LOCAL_LOGV) Log.v(TAG, "Dispatching key " + event + " to " + mView);
@@ -3815,20 +3817,9 @@
}
// Dispatch to the IME before propagating down the view hierarchy.
- // The IME will eventually call back into handleImeFinishedEvent.
- if (mLastWasImTarget) {
- InputMethodManager imm = InputMethodManager.peekInstance();
- if (imm != null) {
- final int seq = event.getSequenceNumber();
- if (DEBUG_IMF) Log.v(TAG, "Sending key event to IME: seq="
- + seq + " event=" + event);
- return imm.dispatchKeyEvent(mView.getContext(), seq, event,
- mInputMethodCallback);
- }
- }
+ result = dispatchImeInputEvent(q);
}
-
- return EVENT_POST_IME;
+ return result;
}
private int deliverKeyEventPostIme(QueuedInputEvent q) {
@@ -4317,14 +4308,6 @@
}
}
- void dispatchImeFinishedEvent(int seq, boolean handled) {
- Message msg = mHandler.obtainMessage(MSG_IME_FINISHED_EVENT);
- msg.arg1 = seq;
- msg.arg2 = handled ? 1 : 0;
- msg.setAsynchronous(true);
- mHandler.sendMessage(msg);
- }
-
public void dispatchFinishInputConnection(InputConnection connection) {
Message msg = mHandler.obtainMessage(MSG_FINISH_INPUT_CONNECTION, connection);
mHandler.sendMessage(msg);
@@ -4533,6 +4516,21 @@
return q;
}
+ int dispatchImeInputEvent(QueuedInputEvent q) {
+ if (mLastWasImTarget) {
+ InputMethodManager imm = InputMethodManager.peekInstance();
+ if (imm != null) {
+ final InputEvent event = q.mEvent;
+ final int seq = event.getSequenceNumber();
+ if (DEBUG_IMF)
+ Log.v(TAG, "Sending input event to IME: seq=" + seq + " event=" + event);
+ return imm.dispatchInputEvent(mView.getContext(), seq, event,
+ mInputMethodCallback);
+ }
+ }
+ return EVENT_POST_IME;
+ }
+
void handleImeFinishedEvent(int seq, boolean handled) {
QueuedInputEvent q = mCurrentInputEventHead;
if (q != null && q.mEvent.getSequenceNumber() == seq) {
@@ -5132,7 +5130,7 @@
public void finishedEvent(int seq, boolean handled) {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
- viewAncestor.dispatchImeFinishedEvent(seq, handled);
+ viewAncestor.handleImeFinishedEvent(seq, handled);
}
}
}
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index e602eb7..4207832 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -19,7 +19,6 @@
import com.android.internal.os.SomeArgs;
import com.android.internal.view.IInputConnectionWrapper;
import com.android.internal.view.IInputContext;
-import com.android.internal.view.IInputMethodCallback;
import com.android.internal.view.IInputMethodClient;
import com.android.internal.view.IInputMethodManager;
import com.android.internal.view.IInputMethodSession;
@@ -40,8 +39,10 @@
import android.util.Log;
import android.util.PrintWriterPrinter;
import android.util.Printer;
+import android.view.InputChannel;
+import android.view.InputEvent;
+import android.view.InputEventSender;
import android.view.KeyEvent;
-import android.view.MotionEvent;
import android.view.View;
import android.view.ViewRootImpl;
@@ -319,6 +320,8 @@
* The actual instance of the method to make calls on it.
*/
IInputMethodSession mCurMethod;
+ InputChannel mCurChannel;
+ ImeInputEventSender mCurSender;
PendingEvent mPendingEventPool;
int mPendingEventPoolSize;
@@ -363,10 +366,17 @@
if (mBindSequence < 0 || mBindSequence != res.sequence) {
Log.w(TAG, "Ignoring onBind: cur seq=" + mBindSequence
+ ", given seq=" + res.sequence);
+ if (res.channel != null) {
+ res.channel.dispose();
+ }
return;
}
mCurMethod = res.method;
+ if (mCurChannel != null) {
+ mCurChannel.dispose();
+ }
+ mCurChannel = res.channel;
mCurId = res.id;
mBindSequence = res.sequence;
}
@@ -482,10 +492,10 @@
}
final IInputMethodClient.Stub mClient = new IInputMethodClient.Stub() {
- @Override protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
// No need to check for dump permission, since we only give this
// interface to the system.
-
CountDownLatch latch = new CountDownLatch(1);
SomeArgs sargs = SomeArgs.obtain();
sargs.arg1 = fd;
@@ -501,32 +511,29 @@
fout.println("Interrupted waiting for dump");
}
}
-
+
+ @Override
public void setUsingInputMethod(boolean state) {
}
-
+
+ @Override
public void onBindMethod(InputBindResult res) {
mH.sendMessage(mH.obtainMessage(MSG_BIND, res));
}
-
+
+ @Override
public void onUnbindMethod(int sequence) {
mH.sendMessage(mH.obtainMessage(MSG_UNBIND, sequence, 0));
}
-
+
+ @Override
public void setActive(boolean active) {
mH.sendMessage(mH.obtainMessage(MSG_SET_ACTIVE, active ? 1 : 0, 0));
}
- };
-
+ };
+
final InputConnection mDummyInputConnection = new BaseInputConnection(this, false);
- final IInputMethodCallback mInputMethodCallback = new IInputMethodCallback.Stub() {
- @Override
- public void finishedEvent(int seq, boolean handled) {
- InputMethodManager.this.finishedEvent(seq, handled);
- }
- };
-
InputMethodManager(IInputMethodManager service, Looper looper) {
mService = service;
mMainLooper = looper;
@@ -714,6 +721,14 @@
mBindSequence = -1;
mCurId = null;
mCurMethod = null;
+ if (mCurSender != null) {
+ mCurSender.dispose();
+ mCurSender = null;
+ }
+ if (mCurChannel != null) {
+ mCurChannel.dispose();
+ mCurChannel = null;
+ }
}
/**
@@ -1085,6 +1100,7 @@
// we need to reschedule our work for over there.
if (DEBUG) Log.v(TAG, "Starting input: reschedule to view thread");
vh.post(new Runnable() {
+ @Override
public void run() {
startInputInner(null, 0, 0, 0);
}
@@ -1158,11 +1174,20 @@
if (res.id != null) {
mBindSequence = res.sequence;
mCurMethod = res.method;
+ if (mCurChannel != null) {
+ mCurChannel.dispose();
+ }
+ mCurChannel = res.channel;
mCurId = res.id;
- } else if (mCurMethod == null) {
- // This means there is no input method available.
- if (DEBUG) Log.v(TAG, "ABORT input: no input method!");
- return true;
+ } else {
+ if (res.channel != null) {
+ res.channel.dispose();
+ }
+ if (mCurMethod == null) {
+ // This means there is no input method available.
+ if (DEBUG) Log.v(TAG, "ABORT input: no input method!");
+ return true;
+ }
}
}
if (mCurMethod != null && mCompletions != null) {
@@ -1556,76 +1581,39 @@
throw new RuntimeException(e);
}
}
-
+
/**
* @hide
*/
- public int dispatchKeyEvent(Context context, int seq, KeyEvent key,
+ public int dispatchInputEvent(Context context, int seq, InputEvent event,
FinishedEventCallback callback) {
synchronized (mH) {
- if (DEBUG) Log.d(TAG, "dispatchKeyEvent");
+ if (DEBUG) Log.d(TAG, "dispatchInputEvent");
if (mCurMethod != null) {
- if (key.getAction() == KeyEvent.ACTION_DOWN
- && key.getKeyCode() == KeyEvent.KEYCODE_SYM
- && key.getRepeatCount() == 0) {
- showInputMethodPickerLocked();
- return ViewRootImpl.EVENT_HANDLED;
+ if (event instanceof KeyEvent) {
+ KeyEvent keyEvent = (KeyEvent)event;
+ if (keyEvent.getAction() == KeyEvent.ACTION_DOWN
+ && keyEvent.getKeyCode() == KeyEvent.KEYCODE_SYM
+ && keyEvent.getRepeatCount() == 0) {
+ showInputMethodPickerLocked();
+ return ViewRootImpl.EVENT_HANDLED;
+ }
}
- try {
- if (DEBUG) Log.v(TAG, "DISPATCH KEY: " + mCurMethod);
- final long startTime = SystemClock.uptimeMillis();
- enqueuePendingEventLocked(startTime, seq, mCurId, callback);
- mCurMethod.dispatchKeyEvent(seq, key, mInputMethodCallback);
- return ViewRootImpl.EVENT_PENDING_IME;
- } catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId + " dropping: " + key, e);
- }
- }
- }
- return ViewRootImpl.EVENT_POST_IME;
- }
- /**
- * @hide
- */
- public int dispatchTrackballEvent(Context context, int seq, MotionEvent motion,
- FinishedEventCallback callback) {
- synchronized (mH) {
- if (DEBUG) Log.d(TAG, "dispatchTrackballEvent");
-
- if (mCurMethod != null && mCurrentTextBoxAttribute != null) {
- try {
- if (DEBUG) Log.v(TAG, "DISPATCH TRACKBALL: " + mCurMethod);
- final long startTime = SystemClock.uptimeMillis();
- enqueuePendingEventLocked(startTime, seq, mCurId, callback);
- mCurMethod.dispatchTrackballEvent(seq, motion, mInputMethodCallback);
- return ViewRootImpl.EVENT_PENDING_IME;
- } catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId + " dropping trackball: " + motion, e);
- }
- }
- }
- return ViewRootImpl.EVENT_POST_IME;
- }
-
- /**
- * @hide
- */
- public int dispatchGenericMotionEvent(Context context, int seq, MotionEvent motion,
- FinishedEventCallback callback) {
- synchronized (mH) {
- if (DEBUG) Log.d(TAG, "dispatchGenericMotionEvent");
-
- if (mCurMethod != null && mCurrentTextBoxAttribute != null) {
- try {
- if (DEBUG) Log.v(TAG, "DISPATCH GENERIC MOTION: " + mCurMethod);
- final long startTime = SystemClock.uptimeMillis();
- enqueuePendingEventLocked(startTime, seq, mCurId, callback);
- mCurMethod.dispatchGenericMotionEvent(seq, motion, mInputMethodCallback);
- return ViewRootImpl.EVENT_PENDING_IME;
- } catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId + " dropping generic motion: " + motion, e);
+ if (DEBUG) Log.v(TAG, "DISPATCH INPUT EVENT: " + mCurMethod);
+ final long startTime = SystemClock.uptimeMillis();
+ if (mCurChannel != null) {
+ if (mCurSender == null) {
+ mCurSender = new ImeInputEventSender(mCurChannel, mH.getLooper());
+ }
+ if (mCurSender.sendInputEvent(seq, event)) {
+ enqueuePendingEventLocked(startTime, seq, mCurId, callback);
+ return ViewRootImpl.EVENT_PENDING_IME;
+ } else {
+ Log.w(TAG, "Unable to send input event to IME: "
+ + mCurId + " dropping: " + event);
+ }
}
}
}
@@ -1937,6 +1925,17 @@
public void finishedEvent(int seq, boolean handled);
}
+ private final class ImeInputEventSender extends InputEventSender {
+ public ImeInputEventSender(InputChannel inputChannel, Looper looper) {
+ super(inputChannel, looper);
+ }
+
+ @Override
+ public void onInputEventFinished(int seq, boolean handled) {
+ finishedEvent(seq, handled);
+ }
+ }
+
private static final class PendingEvent {
public PendingEvent mNext;
diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java
index 7c961bd..b2073b1 100644
--- a/core/java/android/widget/AppSecurityPermissions.java
+++ b/core/java/android/widget/AppSecurityPermissions.java
@@ -515,10 +515,12 @@
((pInfo.protectionLevel&PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0);
final boolean wasGranted =
((existingReqFlags&PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0);
+ final boolean isGranted =
+ ((newReqFlags&PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0);
// Dangerous and normal permissions are always shown to the user if the permission
// is required, or it was previously granted
- if ((isNormal || isDangerous) && (isRequired || wasGranted)) {
+ if ((isNormal || isDangerous) && (isRequired || wasGranted || isGranted)) {
return true;
}
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index c9d2d95..529de2e 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -1212,8 +1212,8 @@
private int mLeft, mTop, mRight, mBottom;
- private int mStart = DEFAULT_RELATIVE;
- private int mEnd = DEFAULT_RELATIVE;
+ private int mStart = DEFAULT_MARGIN_RELATIVE;
+ private int mEnd = DEFAULT_MARGIN_RELATIVE;
private boolean mRulesChanged = false;
private boolean mIsRtlCompatibilityMode = false;
@@ -1314,7 +1314,7 @@
break;
}
}
-
+ mRulesChanged = true;
System.arraycopy(rules, LEFT_OF, initialRules, LEFT_OF, VERB_COUNT);
a.recycle();
@@ -1574,11 +1574,11 @@
public void resolveLayoutDirection(int layoutDirection) {
final boolean isLayoutRtl = isLayoutRtl();
if (isLayoutRtl) {
- if (mStart != DEFAULT_RELATIVE) mRight = mStart;
- if (mEnd != DEFAULT_RELATIVE) mLeft = mEnd;
+ if (mStart != DEFAULT_MARGIN_RELATIVE) mRight = mStart;
+ if (mEnd != DEFAULT_MARGIN_RELATIVE) mLeft = mEnd;
} else {
- if (mStart != DEFAULT_RELATIVE) mLeft = mStart;
- if (mEnd != DEFAULT_RELATIVE) mRight = mEnd;
+ if (mStart != DEFAULT_MARGIN_RELATIVE) mLeft = mStart;
+ if (mEnd != DEFAULT_MARGIN_RELATIVE) mRight = mEnd;
}
if (hasRelativeRules() && layoutDirection != getLayoutDirection()) {
diff --git a/core/java/com/android/internal/view/IInputMethod.aidl b/core/java/com/android/internal/view/IInputMethod.aidl
index bd947e9..77456da 100644
--- a/core/java/com/android/internal/view/IInputMethod.aidl
+++ b/core/java/com/android/internal/view/IInputMethod.aidl
@@ -18,6 +18,7 @@
import android.os.IBinder;
import android.os.ResultReceiver;
+import android.view.InputChannel;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputBinding;
import android.view.inputmethod.InputMethodSubtype;
@@ -41,7 +42,7 @@
void restartInput(in IInputContext inputContext, in EditorInfo attribute);
- void createSession(IInputSessionCallback callback);
+ void createSession(in InputChannel channel, IInputSessionCallback callback);
void setSessionEnabled(IInputMethodSession session, boolean enabled);
diff --git a/core/java/com/android/internal/view/IInputMethodSession.aidl b/core/java/com/android/internal/view/IInputMethodSession.aidl
index cdec254..90210ce 100644
--- a/core/java/com/android/internal/view/IInputMethodSession.aidl
+++ b/core/java/com/android/internal/view/IInputMethodSession.aidl
@@ -22,7 +22,6 @@
import android.view.MotionEvent;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.ExtractedText;
-import com.android.internal.view.IInputMethodCallback;
/**
* Sub-interface of IInputMethod which is safe to give to client applications.
@@ -40,14 +39,8 @@
void viewClicked(boolean focusChanged);
void updateCursor(in Rect newCursor);
-
+
void displayCompletions(in CompletionInfo[] completions);
-
- void dispatchKeyEvent(int seq, in KeyEvent event, IInputMethodCallback callback);
-
- void dispatchTrackballEvent(int seq, in MotionEvent event, IInputMethodCallback callback);
-
- void dispatchGenericMotionEvent(int seq, in MotionEvent event, IInputMethodCallback callback);
void appPrivateCommand(String action, in Bundle data);
diff --git a/core/java/com/android/internal/view/InputBindResult.java b/core/java/com/android/internal/view/InputBindResult.java
index 658f098..9143c61 100644
--- a/core/java/com/android/internal/view/InputBindResult.java
+++ b/core/java/com/android/internal/view/InputBindResult.java
@@ -18,6 +18,7 @@
import android.os.Parcel;
import android.os.Parcelable;
+import android.view.InputChannel;
/**
* Bundle of information returned by input method manager about a successful
@@ -30,7 +31,12 @@
* The input method service.
*/
public final IInputMethodSession method;
-
+
+ /**
+ * The input channel used to send input events to this IME.
+ */
+ public final InputChannel channel;
+
/**
* The ID for this input method, as found in InputMethodInfo; null if
* no input method will be bound.
@@ -42,18 +48,25 @@
*/
public final int sequence;
- public InputBindResult(IInputMethodSession _method, String _id, int _sequence) {
+ public InputBindResult(IInputMethodSession _method, InputChannel _channel,
+ String _id, int _sequence) {
method = _method;
+ channel = _channel;
id = _id;
sequence = _sequence;
}
InputBindResult(Parcel source) {
method = IInputMethodSession.Stub.asInterface(source.readStrongBinder());
+ if (source.readInt() != 0) {
+ channel = InputChannel.CREATOR.createFromParcel(source);
+ } else {
+ channel = null;
+ }
id = source.readString();
sequence = source.readInt();
}
-
+
@Override
public String toString() {
return "InputBindResult{" + method + " " + id
@@ -62,12 +75,19 @@
/**
* Used to package this object into a {@link Parcel}.
- *
+ *
* @param dest The {@link Parcel} to be written.
* @param flags The flags used for parceling.
*/
+ @Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeStrongInterface(method);
+ if (channel != null) {
+ dest.writeInt(1);
+ channel.writeToParcel(dest, 0);
+ } else {
+ dest.writeInt(0);
+ }
dest.writeString(id);
dest.writeInt(sequence);
}
@@ -75,17 +95,21 @@
/**
* Used to make this class parcelable.
*/
- public static final Parcelable.Creator<InputBindResult> CREATOR = new Parcelable.Creator<InputBindResult>() {
+ public static final Parcelable.Creator<InputBindResult> CREATOR =
+ new Parcelable.Creator<InputBindResult>() {
+ @Override
public InputBindResult createFromParcel(Parcel source) {
return new InputBindResult(source);
}
+ @Override
public InputBindResult[] newArray(int size) {
return new InputBindResult[size];
}
};
+ @Override
public int describeContents() {
- return 0;
+ return channel != null ? channel.describeContents() : 0;
}
}
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 6bb7ac7..d1db230 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -835,6 +835,8 @@
(TextUtils.isEmpty(mTitle) && TextUtils.isEmpty(mSubtitle))) {
// Don't show while in expanded mode or with empty text
mTitleLayout.setVisibility(GONE);
+ } else {
+ mTitleLayout.setVisibility(VISIBLE);
}
}
@@ -1587,15 +1589,10 @@
mTitleLayout.setVisibility(VISIBLE);
}
}
- if (mTabScrollView != null && mNavigationMode == ActionBar.NAVIGATION_MODE_TABS) {
- mTabScrollView.setVisibility(VISIBLE);
- }
- if (mSpinner != null && mNavigationMode == ActionBar.NAVIGATION_MODE_LIST) {
- mSpinner.setVisibility(VISIBLE);
- }
- if (mCustomNavView != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
- mCustomNavView.setVisibility(VISIBLE);
- }
+ if (mTabScrollView != null) mTabScrollView.setVisibility(VISIBLE);
+ if (mSpinner != null) mSpinner.setVisibility(VISIBLE);
+ if (mCustomNavView != null) mCustomNavView.setVisibility(VISIBLE);
+
mExpandedHomeLayout.setIcon(null);
mCurrentExpandedItem = null;
setHomeButtonEnabled(mWasHomeEnabled); // Set by expandItemActionView above
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 1e27be8..66cea9d7 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -44,6 +44,7 @@
android_view_InputChannel.cpp \
android_view_InputDevice.cpp \
android_view_InputEventReceiver.cpp \
+ android_view_InputEventSender.cpp \
android_view_KeyEvent.cpp \
android_view_KeyCharacterMap.cpp \
android_view_HardwareRenderer.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 86d3cb6..1300d01 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -163,6 +163,7 @@
extern int register_android_view_InputChannel(JNIEnv* env);
extern int register_android_view_InputDevice(JNIEnv* env);
extern int register_android_view_InputEventReceiver(JNIEnv* env);
+extern int register_android_view_InputEventSender(JNIEnv* env);
extern int register_android_view_KeyCharacterMap(JNIEnv *env);
extern int register_android_view_KeyEvent(JNIEnv* env);
extern int register_android_view_MotionEvent(JNIEnv* env);
@@ -1195,6 +1196,7 @@
REG_JNI(register_android_app_NativeActivity),
REG_JNI(register_android_view_InputChannel),
REG_JNI(register_android_view_InputEventReceiver),
+ REG_JNI(register_android_view_InputEventSender),
REG_JNI(register_android_view_KeyEvent),
REG_JNI(register_android_view_MotionEvent),
REG_JNI(register_android_view_PointerIcon),
diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp
index 9501cf2..198814a 100644
--- a/core/jni/android_view_InputEventReceiver.cpp
+++ b/core/jni/android_view_InputEventReceiver.cpp
@@ -118,8 +118,13 @@
int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {
if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
- ALOGE("channel '%s' ~ Publisher closed input channel or an error occurred. "
+#if DEBUG_DISPATCH_CYCLE
+ // This error typically occurs when the publisher has closed the input channel
+ // as part of removing a window or finishing an IME session, in which case
+ // the consumer will soon be disposed as well.
+ ALOGD("channel '%s' ~ Publisher closed input channel or an error occurred. "
"events=0x%x", getInputChannelName(), events);
+#endif
return 0; // remove the callback
}
diff --git a/core/jni/android_view_InputEventSender.cpp b/core/jni/android_view_InputEventSender.cpp
new file mode 100644
index 0000000..2306cf2
--- /dev/null
+++ b/core/jni/android_view_InputEventSender.cpp
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "InputEventSender"
+
+//#define LOG_NDEBUG 0
+
+// Log debug messages about the dispatch cycle.
+#define DEBUG_DISPATCH_CYCLE 0
+
+
+#include "JNIHelp.h"
+
+#include <android_runtime/AndroidRuntime.h>
+#include <utils/Log.h>
+#include <utils/Looper.h>
+#include <utils/threads.h>
+#include <utils/KeyedVector.h>
+#include <androidfw/InputTransport.h>
+#include "android_os_MessageQueue.h"
+#include "android_view_InputChannel.h"
+#include "android_view_KeyEvent.h"
+#include "android_view_MotionEvent.h"
+
+namespace android {
+
+static struct {
+ jclass clazz;
+
+ jmethodID dispatchInputEventFinished;
+} gInputEventSenderClassInfo;
+
+
+class NativeInputEventSender : public LooperCallback {
+public:
+ NativeInputEventSender(JNIEnv* env,
+ jobject senderObj, const sp<InputChannel>& inputChannel,
+ const sp<MessageQueue>& messageQueue);
+
+ status_t initialize();
+ void dispose();
+ status_t sendKeyEvent(uint32_t seq, const KeyEvent* event);
+ status_t sendMotionEvent(uint32_t seq, const MotionEvent* event);
+
+protected:
+ virtual ~NativeInputEventSender();
+
+private:
+ jobject mSenderObjGlobal;
+ InputPublisher mInputPublisher;
+ sp<MessageQueue> mMessageQueue;
+ KeyedVector<uint32_t, uint32_t> mPublishedSeqMap;
+ uint32_t mNextPublishedSeq;
+
+ const char* getInputChannelName() {
+ return mInputPublisher.getChannel()->getName().string();
+ }
+
+ virtual int handleEvent(int receiveFd, int events, void* data);
+ status_t receiveFinishedSignals(JNIEnv* env);
+};
+
+
+NativeInputEventSender::NativeInputEventSender(JNIEnv* env,
+ jobject senderObj, const sp<InputChannel>& inputChannel,
+ const sp<MessageQueue>& messageQueue) :
+ mSenderObjGlobal(env->NewGlobalRef(senderObj)),
+ mInputPublisher(inputChannel), mMessageQueue(messageQueue),
+ mNextPublishedSeq(0) {
+#if DEBUG_DISPATCH_CYCLE
+ ALOGD("channel '%s' ~ Initializing input event sender.", getInputChannelName());
+#endif
+}
+
+NativeInputEventSender::~NativeInputEventSender() {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ env->DeleteGlobalRef(mSenderObjGlobal);
+}
+
+status_t NativeInputEventSender::initialize() {
+ int receiveFd = mInputPublisher.getChannel()->getFd();
+ mMessageQueue->getLooper()->addFd(receiveFd, 0, ALOOPER_EVENT_INPUT, this, NULL);
+ return OK;
+}
+
+void NativeInputEventSender::dispose() {
+#if DEBUG_DISPATCH_CYCLE
+ ALOGD("channel '%s' ~ Disposing input event sender.", getInputChannelName());
+#endif
+
+ mMessageQueue->getLooper()->removeFd(mInputPublisher.getChannel()->getFd());
+}
+
+status_t NativeInputEventSender::sendKeyEvent(uint32_t seq, const KeyEvent* event) {
+#if DEBUG_DISPATCH_CYCLE
+ ALOGD("channel '%s' ~ Sending key event, seq=%u.", getInputChannelName(), seq);
+#endif
+
+ uint32_t publishedSeq = mNextPublishedSeq++;
+ status_t status = mInputPublisher.publishKeyEvent(publishedSeq,
+ event->getDeviceId(), event->getSource(), event->getAction(), event->getFlags(),
+ event->getKeyCode(), event->getScanCode(), event->getMetaState(),
+ event->getRepeatCount(), event->getDownTime(), event->getEventTime());
+ if (status) {
+ ALOGW("Failed to send key event on channel '%s'. status=%d",
+ getInputChannelName(), status);
+ return status;
+ }
+ mPublishedSeqMap.add(publishedSeq, seq);
+ return OK;
+}
+
+status_t NativeInputEventSender::sendMotionEvent(uint32_t seq, const MotionEvent* event) {
+#if DEBUG_DISPATCH_CYCLE
+ ALOGD("channel '%s' ~ Sending motion event, seq=%u.", getInputChannelName(), seq);
+#endif
+
+ uint32_t publishedSeq;
+ for (size_t i = 0; i <= event->getHistorySize(); i++) {
+ publishedSeq = mNextPublishedSeq++;
+ status_t status = mInputPublisher.publishMotionEvent(publishedSeq,
+ event->getDeviceId(), event->getSource(), event->getAction(), event->getFlags(),
+ event->getEdgeFlags(), event->getMetaState(), event->getButtonState(),
+ event->getXOffset(), event->getYOffset(),
+ event->getXPrecision(), event->getYPrecision(),
+ event->getDownTime(), event->getHistoricalEventTime(i),
+ event->getPointerCount(), event->getPointerProperties(),
+ event->getHistoricalRawPointerCoords(0, i));
+ if (status) {
+ ALOGW("Failed to send motion event sample on channel '%s'. status=%d",
+ getInputChannelName(), status);
+ return status;
+ }
+ }
+ mPublishedSeqMap.add(publishedSeq, seq);
+ return OK;
+}
+
+int NativeInputEventSender::handleEvent(int receiveFd, int events, void* data) {
+ if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
+#if DEBUG_DISPATCH_CYCLE
+ // This error typically occurs when the consumer has closed the input channel
+ // as part of finishing an IME session, in which case the publisher will
+ // soon be disposed as well.
+ ALOGD("channel '%s' ~ Consumer closed input channel or an error occurred. "
+ "events=0x%x", getInputChannelName(), events);
+#endif
+ return 0; // remove the callback
+ }
+
+ if (!(events & ALOOPER_EVENT_INPUT)) {
+ ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
+ "events=0x%x", getInputChannelName(), events);
+ return 1;
+ }
+
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ status_t status = receiveFinishedSignals(env);
+ mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
+ return status == OK || status == NO_MEMORY ? 1 : 0;
+}
+
+status_t NativeInputEventSender::receiveFinishedSignals(JNIEnv* env) {
+#if DEBUG_DISPATCH_CYCLE
+ ALOGD("channel '%s' ~ Receiving finished signals.", getInputChannelName());
+#endif
+
+ bool skipCallbacks = false;
+ for (;;) {
+ uint32_t publishedSeq;
+ bool handled;
+ status_t status = mInputPublisher.receiveFinishedSignal(&publishedSeq, &handled);
+ if (status) {
+ if (status == WOULD_BLOCK) {
+ return OK;
+ }
+ ALOGE("channel '%s' ~ Failed to consume finished signals. status=%d",
+ getInputChannelName(), status);
+ return status;
+ }
+
+ ssize_t index = mPublishedSeqMap.indexOfKey(publishedSeq);
+ if (index >= 0) {
+ uint32_t seq = mPublishedSeqMap.valueAt(index);
+ mPublishedSeqMap.removeItemsAt(index);
+
+#if DEBUG_DISPATCH_CYCLE
+ ALOGD("channel '%s' ~ Received finished signal, seq=%u, handled=%s, "
+ "pendingEvents=%u.",
+ getInputChannelName(), seq, handled ? "true" : "false",
+ mPublishedSeqMap.size());
+#endif
+
+ if (!skipCallbacks) {
+ env->CallVoidMethod(mSenderObjGlobal,
+ gInputEventSenderClassInfo.dispatchInputEventFinished,
+ jint(seq), jboolean(handled));
+ if (env->ExceptionCheck()) {
+ ALOGE("Exception dispatching finished signal.");
+ skipCallbacks = true;
+ }
+ }
+ }
+ }
+}
+
+
+static jint nativeInit(JNIEnv* env, jclass clazz, jobject senderObj,
+ jobject inputChannelObj, jobject messageQueueObj) {
+ sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
+ inputChannelObj);
+ if (inputChannel == NULL) {
+ jniThrowRuntimeException(env, "InputChannel is not initialized.");
+ return 0;
+ }
+
+ sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
+ if (messageQueue == NULL) {
+ jniThrowRuntimeException(env, "MessageQueue is not initialized.");
+ return 0;
+ }
+
+ sp<NativeInputEventSender> sender = new NativeInputEventSender(env,
+ senderObj, inputChannel, messageQueue);
+ status_t status = sender->initialize();
+ if (status) {
+ String8 message;
+ message.appendFormat("Failed to initialize input event sender. status=%d", status);
+ jniThrowRuntimeException(env, message.string());
+ return 0;
+ }
+
+ sender->incStrong(gInputEventSenderClassInfo.clazz); // retain a reference for the object
+ return reinterpret_cast<jint>(sender.get());
+}
+
+static void nativeDispose(JNIEnv* env, jclass clazz, jint senderPtr) {
+ sp<NativeInputEventSender> sender =
+ reinterpret_cast<NativeInputEventSender*>(senderPtr);
+ sender->dispose();
+ sender->decStrong(gInputEventSenderClassInfo.clazz); // drop reference held by the object
+}
+
+static jboolean nativeSendKeyEvent(JNIEnv* env, jclass clazz, jint senderPtr,
+ jint seq, jobject eventObj) {
+ sp<NativeInputEventSender> sender =
+ reinterpret_cast<NativeInputEventSender*>(senderPtr);
+ KeyEvent event;
+ android_view_KeyEvent_toNative(env, eventObj, &event);
+ status_t status = sender->sendKeyEvent(seq, &event);
+ return !status;
+}
+
+static jboolean nativeSendMotionEvent(JNIEnv* env, jclass clazz, jint senderPtr,
+ jint seq, jobject eventObj) {
+ sp<NativeInputEventSender> sender =
+ reinterpret_cast<NativeInputEventSender*>(senderPtr);
+ MotionEvent* event = android_view_MotionEvent_getNativePtr(env, eventObj);
+ status_t status = sender->sendMotionEvent(seq, event);
+ return !status;
+}
+
+
+static JNINativeMethod gMethods[] = {
+ /* name, signature, funcPtr */
+ { "nativeInit",
+ "(Landroid/view/InputEventSender;Landroid/view/InputChannel;Landroid/os/MessageQueue;)I",
+ (void*)nativeInit },
+ { "nativeDispose", "(I)V",
+ (void*)nativeDispose },
+ { "nativeSendKeyEvent", "(IILandroid/view/KeyEvent;)Z",
+ (void*)nativeSendKeyEvent },
+ { "nativeSendMotionEvent", "(IILandroid/view/MotionEvent;)Z",
+ (void*)nativeSendMotionEvent },
+};
+
+#define FIND_CLASS(var, className) \
+ var = env->FindClass(className); \
+ LOG_FATAL_IF(! var, "Unable to find class " className); \
+ var = jclass(env->NewGlobalRef(var));
+
+#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
+ var = env->GetMethodID(clazz, methodName, methodDescriptor); \
+ LOG_FATAL_IF(! var, "Unable to find method " methodName);
+
+int register_android_view_InputEventSender(JNIEnv* env) {
+ int res = jniRegisterNativeMethods(env, "android/view/InputEventSender",
+ gMethods, NELEM(gMethods));
+ LOG_FATAL_IF(res < 0, "Unable to register native methods.");
+
+ FIND_CLASS(gInputEventSenderClassInfo.clazz, "android/view/InputEventSender");
+
+ GET_METHOD_ID(gInputEventSenderClassInfo.dispatchInputEventFinished,
+ gInputEventSenderClassInfo.clazz,
+ "dispatchInputEventFinished", "(IZ)V");
+ return 0;
+}
+
+} // namespace android
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index be8f5f4..9eca0ce 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -74,6 +74,11 @@
<protected-broadcast android:name="android.app.action.ENTER_DESK_MODE" />
<protected-broadcast android:name="android.app.action.EXIT_DESK_MODE" />
+ <protected-broadcast android:name="android.appwidget.action.APPWIDGET_UPDATE_OPTIONS" />
+ <protected-broadcast android:name="android.appwidget.action.APPWIDGET_DELETED" />
+ <protected-broadcast android:name="android.appwidget.action.APPWIDGET_DISABLED" />
+ <protected-broadcast android:name="android.appwidget.action.APPWIDGET_ENABLED" />
+
<protected-broadcast android:name="android.backup.intent.RUN" />
<protected-broadcast android:name="android.backup.intent.CLEAR" />
<protected-broadcast android:name="android.backup.intent.INIT" />
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 090c928..57e1797 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Aan:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Voer die vereiste PIN in:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Die foon sal tydelik van Wi-Fi ontkoppel terwyl dit aan <xliff:g id="DEVICE_NAME">%1$s</xliff:g> gekoppel is"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Die foon sal tydelik van Wi-Fi ontkoppel terwyl dit aan <xliff:g id="DEVICE_NAME">%1$s</xliff:g> gekoppel is"</string>
<string name="select_character" msgid="3365550120617701745">"Voeg karakter in"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Stuur SMS-boodskappe"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> stuur \'n groot aantal SMS-boodskappe. Wil jy hierdie program toelaat om voort te gaan om boodskappe te stuur?"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 0ee9f29..103f0b7 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"ለ፦"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"የሚፈለገውን ፒን ተይብ፦"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"ፒን፦"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"ስልኩ ከ<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ጋር ተገናኝቶ ባለበት ጊዜ በጊዜያዊነት ከWi-Fi ጋር ያለው ግንኙነት ይቋረጣል"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"ስልኩ ከ<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ጋር ተገናኝቶ ባለበት ጊዜ በጊዜያዊነት ከWi-Fi ጋር ያለው ግንኙነት ይቋረጣል"</string>
<string name="select_character" msgid="3365550120617701745">"ቁምፊ አስገባ"</string>
<string name="sms_control_title" msgid="7296612781128917719">"የSMS መልዕክቶች መበላክ ላይ"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ቁጥራቸው ብዙ የሆኑ የኤስ.ኤም.ኤስ. መልዕክቶችን እየላከ ነው። ይሄ መተግበሪያ መልዕክቶችን መላኩን እንዲቀጥል መፍቀድ ትፈልጋለህ?"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 0c5039f..b8fc281 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"إلى:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"اكتب رقم التعريف الشخصي المطلوب:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"رقم التعريف الشخصي:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"سيتم قطع اتصال الهاتف مؤقتًا بشبكة Wi-Fi في الوقت الذي يكون فيه متصلاً بـ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"سيتم قطع اتصال الهاتف مؤقتًا بشبكة Wi-Fi في الوقت الذي يكون فيه متصلاً بـ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="select_character" msgid="3365550120617701745">"إدراج حرف"</string>
<string name="sms_control_title" msgid="7296612781128917719">"إرسال رسائل قصيرة SMS"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> يرسل عددًا كبيرًا من الرسائل القصيرة SMS. هل تريد السماح لهذا التطبيق بالاستمرار في إرسال الرسائل؟"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 3fbd1f8..3746e91 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Каму:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Увядзіце патрэбны PIN-код:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN-код"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Тэлефон будзе часова адключаны ад Wi-Fi, пакуль ён падлучаны да прылады <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Тэлефон будзе часова адключаны ад Wi-Fi, пакуль ён падлучаны да прылады <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="select_character" msgid="3365550120617701745">"Уставіць сімвал"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Адпраўка SMS"</string>
<string name="sms_control_message" msgid="3867899169651496433">"Прыкладанне <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> дасылае вялікую колькасць SMS-паведамленняў. Дазволіць гэтаму прыкладанню працягваць адпраўляць паведамленні?"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 66f56b8..4831909 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"До:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Въведете задължителния ПИН:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"ПИН:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Телефонът временно ще прекрати връзката с Wi-Fi, докато е свързан с/ъс <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Телефонът временно ще прекрати връзката с Wi-Fi, докато е свързан с/ъс <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="select_character" msgid="3365550120617701745">"Вмъкване на знак"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Изпращане на SMS съобщения"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> изпраща голям брой SMS съобщения. Искате ли да разрешите на това приложение да продължи да го прави?"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 2faf80d..59323c7 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Per a:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Introdueix el PIN sol·licitat:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"El telèfon es desconnectarà temporalment de la Wi-Fi mentre estigui connectat a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"El telèfon es desconnectarà temporalment de la Wi-Fi mentre estigui connectat a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="select_character" msgid="3365550120617701745">"Insereix un caràcter"</string>
<string name="sms_control_title" msgid="7296612781128917719">"S\'estan enviant missatges SMS"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> està enviant molts missatges SMS. Vols permetre que aquesta aplicació continuï enviant missatges?"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 714813c..6e067b5 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Komu:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Zadejte požadovaný kód PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Telefon se při připojení k zařízení <xliff:g id="DEVICE_NAME">%1$s</xliff:g> dočasně odpojí od sítě Wi-Fi"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Telefon se při připojení k zařízení <xliff:g id="DEVICE_NAME">%1$s</xliff:g> dočasně odpojí od sítě Wi-Fi"</string>
<string name="select_character" msgid="3365550120617701745">"Vkládání znaků"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Odesílání zpráv SMS"</string>
<string name="sms_control_message" msgid="3867899169651496433">"Aplikace <b><xliff:g id="APP_NAME">%1$s</xliff:g></b>odesílá velký počet SMS zpráv. Chcete aplikaci povolit, aby zprávy odesílala i nadále?"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index ed3aa40..ea9c3ad 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Til:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Skriv den påkrævede pinkode:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"Pinkode:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Telefonens Wi-Fi-forbindelse vil midlertidigt blive afbrudt, når den er tilsluttet <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Telefonens Wi-Fi-forbindelse vil midlertidigt blive afbrudt, når den er tilsluttet <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="select_character" msgid="3365550120617701745">"Indsæt tegn"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Sender sms-beskeder"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> sender et stort antal sms-beskeder. Vil du tillade, at denne app fortsat sender beskeder?"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 7ebea96..f3f897a 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"An:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Geben Sie die erforderliche PIN ein:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Das Telefon wird vorübergehend vom WLAN getrennt, während eine Verbindung mit <xliff:g id="DEVICE_NAME">%1$s</xliff:g> hergestellt wird."</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Das Telefon wird vorübergehend vom WLAN getrennt, während eine Verbindung mit <xliff:g id="DEVICE_NAME">%1$s</xliff:g> hergestellt wird."</string>
<string name="select_character" msgid="3365550120617701745">"Zeichen einfügen"</string>
<string name="sms_control_title" msgid="7296612781128917719">"SMS werden gesendet"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> sendet eine große Anzahl SMS. Möchten Sie zulassen, dass die App weiterhin Nachrichten sendet?"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 4ac9aab..00fbd8f 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Προς:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Πληκτρολογήστε τον απαιτούμενο κωδικό PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Το τηλέφωνο θα αποσυνδεθεί προσωρινά από το δίκτυο Wi-Fi ενώ συνδέεται στη συσκευή <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Το τηλέφωνο θα αποσυνδεθεί προσωρινά από το δίκτυο Wi-Fi ενώ συνδέεται στη συσκευή <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="select_character" msgid="3365550120617701745">"Εισαγωγή χαρακτήρα"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Αποστολή μηνυμάτων SMS"</string>
<string name="sms_control_message" msgid="3867899169651496433">"Η εφαρμογή <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> στέλνει έναν μεγάλο αριθμό μηνυμάτων SMS. Θέλετε να επιτρέψετε σε αυτήν την εφαρμογή να συνεχίσει να στέλνει μηνύματα;"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index f0390be..0314fc9 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"To:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Type the required PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"The phone will temporarily disconnect from Wi-FI while it\'s connected to <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"The phone will temporarily disconnect from Wi-FI while it\'s connected to <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="select_character" msgid="3365550120617701745">"Insert character"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Sending SMS messages"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> is sending a large number of SMS messages. Do you want to allow this app to continue sending messages?"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 3a39920..c26998a 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Para:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Escribe el PIN solicitado:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"El dispositivo se desconectará temporalmente de la red Wi-Fi mientras esté conectado a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"El dispositivo se desconectará temporalmente de la red Wi-Fi mientras esté conectado a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
<string name="select_character" msgid="3365550120617701745">"Insertar caracteres"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Enviando mensajes SMS"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> está enviando una gran cantidad de mensajes SMS. ¿Quieres permitir que está aplicación siga enviando mensajes?"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 2217e30..b709983 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Para:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Escribe el PIN solicitado:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"El teléfono se desconectará temporalmente de la red Wi-Fi mientras está conectado a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"El teléfono se desconectará temporalmente de la red Wi-Fi mientras está conectado a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
<string name="select_character" msgid="3365550120617701745">"Insertar carácter"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Enviando mensajes SMS..."</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> está enviando un gran número de mensajes SMS. ¿Quieres permitir que está aplicación siga enviando mensajes?"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index ce8bd81..3abaf62e 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Saaja:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Sisestage nõutav PIN-kood:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN-kood:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Telefoni ühendus WiFi-ga katkestatakse ajutiselt, kui see on ühendatud seadmega <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Telefoni ühendus WiFi-ga katkestatakse ajutiselt, kui see on ühendatud seadmega <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="select_character" msgid="3365550120617701745">"Sisesta tähemärk"</string>
<string name="sms_control_title" msgid="7296612781128917719">"SMS-sõnumite saatmine"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> saadab suurel hulgal SMS-sõnumeid. Kas tahate lubada sellel rakendusel ka edaspidi sõnumeid saata?"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 49325e1..f8c1629 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"به:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"پین لازم را تایپ کنید:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"پین:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"این گوشی بهطور موقت از Wi-Fi قطع خواهد شد، در حالی که به <xliff:g id="DEVICE_NAME">%1$s</xliff:g> وصل است"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"این گوشی بهطور موقت از Wi-Fi قطع خواهد شد، در حالی که به <xliff:g id="DEVICE_NAME">%1$s</xliff:g> وصل است"</string>
<string name="select_character" msgid="3365550120617701745">"درج نویسه"</string>
<string name="sms_control_title" msgid="7296612781128917719">"ارسال پیامک ها"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> در حال ارسال تعداد زیادی پیامک است. آیا اجازه میدهید این برنامه همچنان پیامک ارسال کند؟"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 3711f19..da5c2db 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Kohde:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Kirjoita pyydetty PIN-koodi:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN-koodi:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Puhelimen yhteys wifi-verkkoon katkaistaan väliaikaisesti puhelimen ollessa yhdistettynä laitteeseen <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Puhelimen yhteys wifi-verkkoon katkaistaan väliaikaisesti puhelimen ollessa yhdistettynä laitteeseen <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="select_character" msgid="3365550120617701745">"Lisää merkki"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Tekstiviestien lähettäminen"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> lähettää suuria määriä tekstiviestejä. Annetaanko tämän sovelluksen jatkaa tekstiviestien lähettämistä?"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index dcd6ffd..c9a0eb5 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -906,7 +906,7 @@
<string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Permettre à l\'application titulaire d\'accéder à des fournisseurs de contenu depuis la commande shell. Les applications standards ne devraient jamais avoir recours à cette autorisation."</string>
<string name="permlab_updateLock" msgid="3527558366616680889">"déconseiller mises à jour auto appareil"</string>
<string name="permdesc_updateLock" msgid="1655625832166778492">"Permet à l\'application autorisée d\'indiquer au système le moment opportun pour un redémarrage non interactif en vue de la mise à jour de l\'appareil."</string>
- <string name="save_password_message" msgid="767344687139195790">"Voulez-vous que le navigateur se souvienne de ce mot de passe ?"</string>
+ <string name="save_password_message" msgid="767344687139195790">"Voulez-vous que le navigateur se souvienne de ce mot de passe ?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Pas maintenant"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Mémoriser"</string>
<string name="save_password_never" msgid="8274330296785855105">"Jamais"</string>
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"À :"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Saisissez le code PIN requis :"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"Code PIN :"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Le téléphone sera déconnecté du réseau Wi-Fi tant qu\'il sera connecté à l\'appareil <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Le téléphone sera déconnecté du réseau Wi-Fi tant qu\'il sera connecté à l\'appareil <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
<string name="select_character" msgid="3365550120617701745">"Insérer un caractère"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Envoi de messages SMS"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> envoie un grand nombre de SMS. Autorisez-vous cette application à poursuivre l\'envoi des messages ?"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index c0bd858..cbec3fe 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"प्रति:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"आवश्यक पिन लिखें:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"पिन:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"फ़ोन <xliff:g id="DEVICE_NAME">%1$s</xliff:g> से कनेक्ट रहते समय Wi-Fi से अस्थायी रूप से डिस्कनेक्ट हो जाएगा"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"फ़ोन <xliff:g id="DEVICE_NAME">%1$s</xliff:g> से कनेक्ट रहते समय Wi-Fi से अस्थायी रूप से डिस्कनेक्ट हो जाएगा"</string>
<string name="select_character" msgid="3365550120617701745">"वर्ण सम्मिलित करें"</string>
<string name="sms_control_title" msgid="7296612781128917719">"SMS संदेश भेज रहा है"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> बड़ी संख्या में SMS संदेश भेज रहा है. क्या आप इस एप्लिकेशन को संदेश भेजना जारी रखने देना चाहते हैं?"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 1564866..6eb3863 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Prima:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Upišite potreban PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Telefon će se privremeno isključiti s Wi-Fija dok je povezan s uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Telefon će se privremeno isključiti s Wi-Fija dok je povezan s uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="select_character" msgid="3365550120617701745">"Umetni znak"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Slanje SMS poruka"</string>
<string name="sms_control_message" msgid="3867899169651496433">"Aplikacija <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> šalje veliki broj SMS poruka. Želite li dopustiti ovoj aplikaciji da nastavi slati poruke?"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index e7dd28e..b621899 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Címzett:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Adja meg a szükséges PIN kódot:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN kód:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"A telefon ideiglenesen kilép a Wi-Fi hálózatról, míg a(z) <xliff:g id="DEVICE_NAME">%1$s</xliff:g> eszközhöz csatlakozik."</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"A telefon ideiglenesen kilép a Wi-Fi hálózatról, míg a(z) <xliff:g id="DEVICE_NAME">%1$s</xliff:g> eszközhöz csatlakozik."</string>
<string name="select_character" msgid="3365550120617701745">"Karakter beszúrása"</string>
<string name="sms_control_title" msgid="7296612781128917719">"SMS-ek küldése"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></ b> nagyszámú SMS üzenetet küld. Engedélyezi, hogy ez az alkalmazás továbbra is üzeneteket küldjön?"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 88b5a2d..2d8d75d 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Kepada:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Ketik PIN yang diminta:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Ponsel akan terputus sementara dari Wi-Fi saat tersambung ke <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Ponsel akan terputus sementara dari Wi-Fi saat tersambung ke <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="select_character" msgid="3365550120617701745">"Sisipkan huruf"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Mengirim pesan SMS"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> sedang mengirim pesan SMS dalam jumlah besar. Izinkan aplikasi ini untuk melanjutkan pengiriman pesan?"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index fab4740..4486e69 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"A:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Inserisci il PIN richiesto:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Il telefono verrà momentaneamente scollegato dalla rete Wi-Fi durante il collegamento a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Il telefono verrà momentaneamente scollegato dalla rete Wi-Fi durante il collegamento a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
<string name="select_character" msgid="3365550120617701745">"Inserisci carattere"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Invio SMS"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> sta inviando molti SMS. Vuoi consentire all\'applicazione di continuare a inviare messaggi?"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 763a105..17e8a37 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"אל:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"הקלד את קוד ה-PIN הנדרש."</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"הטלפון יתנתק מרשת ה-Wi-Fi באופן זמני בשעה שהוא מחובר אל <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"הטלפון יתנתק מרשת ה-Wi-Fi באופן זמני בשעה שהוא מחובר אל <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="select_character" msgid="3365550120617701745">"הוסף תו"</string>
<string name="sms_control_title" msgid="7296612781128917719">"שולח הודעות SMS"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b> <xliff:g id="APP_NAME">%1$s</xliff:g> </ b> שולח מספר רב של הודעות SMS. האם ברצונך לאפשר ליישום זה להמשיך לשלוח הודעות?"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 83925af..2b6cb00 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"To:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"必要なPINを入力してください:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"携帯端末が<xliff:g id="DEVICE_NAME">%1$s</xliff:g>に接続されている間は一時的にWi-Fi接続が解除されます。"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"携帯端末が<xliff:g id="DEVICE_NAME">%1$s</xliff:g>に接続されている間は一時的にWi-Fi接続が解除されます。"</string>
<string name="select_character" msgid="3365550120617701745">"文字を挿入"</string>
<string name="sms_control_title" msgid="7296612781128917719">"SMSメッセージの送信中"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>が大量のSMSメッセージを送信しています。このアプリにこのままメッセージの送信を許可しますか?"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index ce657f8..a810269 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"받는사람:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"필수 PIN 입력:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>에 연결되어 있는 동안 일시적으로 휴대전화의 Wi-Fi 연결이 해제됩니다."</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>에 연결되어 있는 동안 일시적으로 휴대전화의 Wi-Fi 연결이 해제됩니다."</string>
<string name="select_character" msgid="3365550120617701745">"문자 삽입"</string>
<string name="sms_control_title" msgid="7296612781128917719">"SMS 메시지를 보내는 중"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>이(가) SMS 메시지를 대량으로 보내고 있습니다. 해당 앱이 메시지를 계속 보내도록 하시겠습니까?"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 9922744..1a48fac 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Skirta:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Įveskite reikiamą PIN kodą:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN kodas:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Telefonas bus laikinai atjungtas nuo „Wi-Fi“, kol bus prijungtas prie „<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Telefonas bus laikinai atjungtas nuo „Wi-Fi“, kol bus prijungtas prie „<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“"</string>
<string name="select_character" msgid="3365550120617701745">"Įterpti simbolį"</string>
<string name="sms_control_title" msgid="7296612781128917719">"SMS pranešimų siuntimas"</string>
<string name="sms_control_message" msgid="3867899169651496433">"Naudojant <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> siunčiama daug SMS pranešimų. Ar norite leisti šiai programai toliau siųsti pranešimus?"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 861f37e..dcaf8e3 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Kam:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Ierakstiet pieprasīto PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Tālrunis tiks īslaicīgi atvienots no Wi-Fi tīkla, kamēr būs izveidots savienojums ar ierīci <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Tālrunis tiks īslaicīgi atvienots no Wi-Fi tīkla, kamēr būs izveidots savienojums ar ierīci <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
<string name="select_character" msgid="3365550120617701745">"Ievietojiet rakstzīmi"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Īsziņu sūtīšana"</string>
<string name="sms_control_message" msgid="3867899169651496433">"Lietotne <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> sūta daudz īsziņu. Vai vēlaties, lai šī lietotne turpinātu sūtīt ziņojumus?"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index c42697e..be04f9d 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Kepada:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Taipkan PIN yang diperlukan:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Sambungan telefon ke Wi-Fi akan diputuskan buat sementara waktu semasa telefon bersambung ke <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Sambungan telefon ke Wi-Fi akan diputuskan buat sementara waktu semasa telefon bersambung ke <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="select_character" msgid="3365550120617701745">"Masukkan aksara"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Menghantar mesej SMS"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> sedang menghantar banyak mesej SMS. Adakah anda mahu membenarkan apl ini terus menghantar mesej?"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 2d4f9cd..387676f 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Til:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Skriv inn påkrevd PIN-kode:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Telefonen frakobles Wi-Fi midlertidig mens den er tilkoblet <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Telefonen frakobles Wi-Fi midlertidig mens den er tilkoblet <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="select_character" msgid="3365550120617701745">"Sett inn tegn"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Sender SMS-meldinger"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> sender et stort antall SMS. Vil du la appen fortsette å sende ut meldinger?"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 85590ce..38619e5 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Naar:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Voer de gewenste pincode in:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"Pincode"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"De verbinding met het wifi-netwerk wordt tijdelijk uitgeschakeld terwijl de telefoon verbonden is met <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"De verbinding met het wifi-netwerk wordt tijdelijk uitgeschakeld terwijl de telefoon verbonden is met <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="select_character" msgid="3365550120617701745">"Teken invoegen"</string>
<string name="sms_control_title" msgid="7296612781128917719">"SMS-berichten verzenden"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> verzendt moment een groot aantal sms-berichten. Wilt u toestaan dat deze app berichten blijft verzenden?"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 9bcd359..a491104 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Do:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Wpisz wymagany kod PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"Kod PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Na czas połączenia z <xliff:g id="DEVICE_NAME">%1$s</xliff:g> telefon zostanie tymczasowo odłączony od Wi-Fi"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Na czas połączenia z <xliff:g id="DEVICE_NAME">%1$s</xliff:g> telefon zostanie tymczasowo odłączony od Wi-Fi"</string>
<string name="select_character" msgid="3365550120617701745">"Wstaw znak"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Wysyłanie wiadomości SMS"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> wysyła wiele SMS-ów. Chcesz pozwolić tej aplikacji dalej wysyłać SMS-y?"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 56a98ed..646bc3a 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Para:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Introduza o PIN solicitado:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"O telemóvel irá desligar-se temporariamente da rede Wi-Fi enquanto está ligado a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"O telemóvel irá desligar-se temporariamente da rede Wi-Fi enquanto está ligado a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="select_character" msgid="3365550120617701745">"Introduzir carácter"</string>
<string name="sms_control_title" msgid="7296612781128917719">"A enviar mensagens SMS"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> está a enviar um grande número de mensagens SMS. Pretende autorizar que a aplicação continue a enviar mensagens?"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 64e02f0..873c9db 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Para:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Digite o PIN obrigatório:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"O telefone desconectará temporariamente da rede Wi-Fi enquanto estiver conectado a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"O telefone desconectará temporariamente da rede Wi-Fi enquanto estiver conectado a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="select_character" msgid="3365550120617701745">"Inserir caractere"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Enviando mensagens SMS"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> envia uma grande quantidade de mensagens SMS. Deseja permitir que este aplicativo continue enviando mensagens?"</string>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index c081d7f..e934a08 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -1785,6 +1785,8 @@
<skip />
<!-- no translation found for wifi_p2p_show_pin_message (8530563323880921094) -->
<skip />
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
<!-- no translation found for wifi_p2p_frequency_conflict_message (7363907213787469151) -->
<skip />
<string name="select_character" msgid="3365550120617701745">"Inserir in caracter"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index f711741..c44b362 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Către:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Introduceţi codul PIN necesar:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"Cod PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Telefonul se va deconecta temporar de la reţeaua Wi-Fi cât timp este conectat la <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Telefonul se va deconecta temporar de la reţeaua Wi-Fi cât timp este conectat la <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="select_character" msgid="3365550120617701745">"Introduceţi caracterul"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Se trimit mesaje SMS"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> trimite un număr mare de mesaje SMS. Permiteţi acestei aplicaţii să trimită în continuare mesaje?"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index d230f8a..7152bb8 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Кому:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Введите PIN-код:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN-код:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"При подключении к устройству <xliff:g id="DEVICE_NAME">%1$s</xliff:g> телефон будет временно отключаться от сети Wi-Fi"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"При подключении к устройству <xliff:g id="DEVICE_NAME">%1$s</xliff:g> телефон будет временно отключаться от сети Wi-Fi"</string>
<string name="select_character" msgid="3365550120617701745">"Введите символ"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Отправка SMS-сообщений"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> отправляет большое количество SMS. Разрешить приложению и дальше отправлять сообщения?"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index f37ebf0..6f95ff6 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Komu:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Zadajte požadovaný kód PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Telefón bude počas pripojenia k zariadeniu <xliff:g id="DEVICE_NAME">%1$s</xliff:g> od siete Wi-Fi dočasne odpojený."</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Telefón bude počas pripojenia k zariadeniu <xliff:g id="DEVICE_NAME">%1$s</xliff:g> od siete Wi-Fi dočasne odpojený."</string>
<string name="select_character" msgid="3365550120617701745">"Vkladanie znakov"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Odosielanie správ SMS"</string>
<string name="sms_control_message" msgid="3867899169651496433">"Aplikácia <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> posiela veľký počet správ SMS. Chcete tejto aplikácií povoliť, aby aj naďalej posielala správy?"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index d865c7c..1486341 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Za:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Vnesite zahtevano kodo PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Telefon bo začasno prekinil povezavo z Wi-Fi-jem, ko je povezan z napravo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Telefon bo začasno prekinil povezavo z Wi-Fi-jem, ko je povezan z napravo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="select_character" msgid="3365550120617701745">"Vstavljanje znaka"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Pošiljanje sporočil SMS"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> pošilja veliko SMS-ov. Ali želite dovoliti, da jih še naprej pošilja?"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 8bc5879..a1b869f 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Коме:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Унесите потребни PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Телефон ће привремено прекинути везу са Wi-Fi-јем док је повезан са уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Телефон ће привремено прекинути везу са Wi-Fi-јем док је повезан са уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="select_character" msgid="3365550120617701745">"Уметање знака"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Слање SMS порука"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> шаље велики број SMS порука. Желите ли да дозволите овој апликацији да настави са слањем порука?"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 46f2d6e..4c98712 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Till:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Ange den obligatoriska PIN-koden:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN-kod:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Mobilen kommer tillfälligt att kopplas från Wi-Fi när den är ansluten till <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Mobilen kommer tillfälligt att kopplas från Wi-Fi när den är ansluten till <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="select_character" msgid="3365550120617701745">"Infoga tecken"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Skickar SMS"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> skickar ett stort antal SMS. Vill du tillåta att appen fortsätter att skicka meddelanden?"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 04ee91e..d1e4270 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Kwa:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Charaza PIN inayohitajika:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Simu itaukata muunganisho kwa muda kutoka kwenye Wi-Fi inapokuwa imeunganishwa kwenye <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Simu itaukata muunganisho kwa muda kutoka kwenye Wi-Fi inapokuwa imeunganishwa kwenye <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="select_character" msgid="3365550120617701745">"Ingiza kibambo"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Inatuma ujumbe wa SMS"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> inatuma idadi kubwa ya SMS. Je, unataka kuruhusu programu hii kuendelea kutuma SMS?"</string>
@@ -1437,7 +1439,7 @@
<string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Tenganisha"</string>
<string name="kg_emergency_call_label" msgid="684946192523830531">"Simu ya dharura"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Umesahau Ruwaza"</string>
- <string name="kg_wrong_pattern" msgid="1850806070801358830">"Ruwaza Isiyo sahihi"</string>
+ <string name="kg_wrong_pattern" msgid="1850806070801358830">"Mchoro Usio sahihi"</string>
<string name="kg_wrong_password" msgid="2333281762128113157">"Nenosiri Lisilo sahihi"</string>
<string name="kg_wrong_pin" msgid="1131306510833563801">"PIN isiyo sahihi"</string>
<string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Jaribu tena baada ya sekunde <xliff:g id="NUMBER">%d</xliff:g>."</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 9055408..4bca1b1 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"ถึง:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"พิมพ์ PIN ที่ต้องการ:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"โทรศัพท์จะยกเลิกการเชื่อมต่อกับ Wi-Fi ชั่วคราวในขณะที่เชื่อมต่อกับ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"โทรศัพท์จะยกเลิกการเชื่อมต่อกับ Wi-Fi ชั่วคราวในขณะที่เชื่อมต่อกับ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="select_character" msgid="3365550120617701745">"ใส่อักขระ"</string>
<string name="sms_control_title" msgid="7296612781128917719">"กำลังส่งข้อความ SMS"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> กำลังส่งข้อความ SMS จำนวนมาก คุณต้องการอนุญาตให้แอปพลิเคชันนี้ส่งข้อความต่อหรือไม่"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 59a91c2..00c9ef8 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Kay:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"I-type ang kinakailangang PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Pansamantalang madidiskoneta ang telepono sa Wi-Fi habang nakakonekta ito sa <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Pansamantalang madidiskoneta ang telepono sa Wi-Fi habang nakakonekta ito sa <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="select_character" msgid="3365550120617701745">"Magpasok ng character"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Nagpapadala ng mga SMS na mensahe"</string>
<string name="sms_control_message" msgid="3867899169651496433">"Ang <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ay nagpapadala ng maraming mensaheng SMS. Gusto mo bang payagan ang app na ito na magpatuloy sa pagpapadala ng mga mensahe?"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index b95998f..5595a7a 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Alıcı:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Gerekli PIN\'i yazın:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Telefon <xliff:g id="DEVICE_NAME">%1$s</xliff:g> adlı cihaza bağlıyken Kablosuz ağ bağlantısı geçici olarak kesilecektir"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Telefon <xliff:g id="DEVICE_NAME">%1$s</xliff:g> adlı cihaza bağlıyken Kablosuz ağ bağlantısı geçici olarak kesilecektir"</string>
<string name="select_character" msgid="3365550120617701745">"Karakter ekle"</string>
<string name="sms_control_title" msgid="7296612781128917719">"SMS mesajları gönderiliyor"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> çok sayıda SMS mesajı gönderiyor. Bu uygulamanın mesaj göndermeye devam etmesine izin veriyor musunuz?"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 994e8a1..49bc0c3 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Кому:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Введіть потрібний PIN-код:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN-код:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Під час з’єднання з пристроєм <xliff:g id="DEVICE_NAME">%1$s</xliff:g> телефон тимчасово від’єднається від мережі Wi-Fi"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Під час з’єднання з пристроєм <xliff:g id="DEVICE_NAME">%1$s</xliff:g> телефон тимчасово від’єднається від мережі Wi-Fi"</string>
<string name="select_character" msgid="3365550120617701745">"Вставл-ня символу"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Надсил. SMS повідомлень"</string>
<string name="sms_control_message" msgid="3867899169651496433">"Програма <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> надсилає велику кількість SMS-повідомлень. Дозволити цій програмі й надалі надсилати повідомлення?"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 0e61026..48e3fca 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Người nhận:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Nhập PIN bắt buộc:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"Mã PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Điện thoại sẽ tạm thời ngắt kết nối khỏi Wi-Fi trong khi điện thoại được kết nối với <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Điện thoại sẽ tạm thời ngắt kết nối khỏi Wi-Fi trong khi điện thoại được kết nối với <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="select_character" msgid="3365550120617701745">"Chèn ký tự"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Đang gửi tin nhắn SMS"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> đang gửi rất nhiều tin nhắn SMS. Bạn có muốn cho phép ứng dụng này tiếp tục gửi tin nhắn không?"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index ec33b27..ccc66fb 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"收件人:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"键入所需的 PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"手机连接到<xliff:g id="DEVICE_NAME">%1$s</xliff:g>时会暂时断开与 Wi-Fi 的连接。"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"手机连接到<xliff:g id="DEVICE_NAME">%1$s</xliff:g>时会暂时断开与 Wi-Fi 的连接。"</string>
<string name="select_character" msgid="3365550120617701745">"插入字符"</string>
<string name="sms_control_title" msgid="7296612781128917719">"正在发送短信"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>在发送大量短信。是否允许该应用继续发送短信?"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 905cdfb..53f578a 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"收件者:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"請輸入必要的 PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"手機與 <xliff:g id="DEVICE_NAME">%1$s</xliff:g> 連線期間將暫時中斷 WiFi 連線"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"手機與 <xliff:g id="DEVICE_NAME">%1$s</xliff:g> 連線期間將暫時中斷 WiFi 連線"</string>
<string name="select_character" msgid="3365550120617701745">"插入字元"</string>
<string name="sms_control_title" msgid="7296612781128917719">"傳送 SMS 簡訊"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b></b>「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在傳送大量簡訊。您要允許這個應用程式繼續傳送簡訊嗎?"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 52cb1b9..18f603c 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1147,7 +1147,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Ku:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Faka i-PIN edingekayo:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" msgid="7363907213787469151">"Ifoni izonqamuka okwesikhashana ku-Wi-Fi ngenkathi ixhumeke ku-<xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for wifi_p2p_frequency_conflict_message (8012981257742232475) -->
+ <skip />
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Ifoni izonqamuka okwesikhashana ku-Wi-Fi ngenkathi ixhumeke ku-<xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="select_character" msgid="3365550120617701745">"Faka uhlamvu"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Ithumela imiyalezo ye-SMS"</string>
<string name="sms_control_message" msgid="3867899169651496433">"I-<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ithumela inombolo enkulu yemilayezo ye-SMS. Ufuna ukuvumela lolu hlelo lokusebenza ukuqhubeka ukuthumela imilayezo?"</string>
diff --git a/core/tests/benchmarks/src/com/android/internal/util/IndentingPrintWriterBenchmark.java b/core/tests/benchmarks/src/com/android/internal/util/IndentingPrintWriterBenchmark.java
new file mode 100644
index 0000000..34c73e8
--- /dev/null
+++ b/core/tests/benchmarks/src/com/android/internal/util/IndentingPrintWriterBenchmark.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+import com.google.android.collect.Lists;
+import com.google.caliper.SimpleBenchmark;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+public class IndentingPrintWriterBenchmark extends SimpleBenchmark {
+
+ private PrintWriter mDirect;
+ private IndentingPrintWriter mIndenting;
+
+ private Node mSimple;
+ private Node mComplex;
+
+ @Override
+ protected void setUp() throws IOException {
+ final FileOutputStream os = new FileOutputStream(new File("/dev/null"));
+ mDirect = new PrintWriter(os);
+ mIndenting = new IndentingPrintWriter(mDirect, " ");
+
+ final Node manyChildren = Node.build("ManyChildren", Node.build("1"), Node.build("2"),
+ Node.build("3"), Node.build("4"), Node.build("5"), Node.build("6"), Node.build("7"),
+ Node.build("8"), Node.build("9"), Node.build("10"));
+
+ mSimple = Node.build("RED");
+ mComplex = Node.build("PARENT", Node.build("RED"), Node.build("GREEN",
+ Node.build("BLUE", manyChildren, manyChildren), manyChildren, manyChildren),
+ manyChildren);
+ }
+
+ @Override
+ protected void tearDown() {
+ mIndenting.close();
+ mIndenting = null;
+ mDirect = null;
+ }
+
+ public void timeSimpleDirect(int reps) {
+ for (int i = 0; i < reps; i++) {
+ mSimple.dumpDirect(mDirect, 0);
+ }
+ }
+
+ public void timeSimpleIndenting(int reps) {
+ for (int i = 0; i < reps; i++) {
+ mSimple.dumpIndenting(mIndenting);
+ }
+ }
+
+ public void timeComplexDirect(int reps) {
+ for (int i = 0; i < reps; i++) {
+ mComplex.dumpDirect(mDirect, 0);
+ }
+ }
+
+ public void timeComplexIndenting(int reps) {
+ for (int i = 0; i < reps; i++) {
+ mComplex.dumpIndenting(mIndenting);
+ }
+ }
+
+ public void timePairRaw(int reps) {
+ final int value = 1024;
+ for (int i = 0; i < reps; i++) {
+ mDirect.print("key=");
+ mDirect.print(value);
+ mDirect.print(" ");
+ }
+ }
+
+ public void timePairIndenting(int reps) {
+ final int value = 1024;
+ for (int i = 0; i < reps; i++) {
+ mIndenting.printPair("key", value);
+ }
+ }
+
+ private static class Node {
+ public String name;
+ public ArrayList<Node> children;
+
+ private static String[] sIndents = new String[] { "", " ", " ", " ", " " };
+
+ public static Node build(String name, Node... children) {
+ Node node = new Node();
+ node.name = name;
+ if (children != null && children.length > 0) {
+ node.children = Lists.newArrayList(children);
+ }
+ return node;
+ }
+
+ private void dumpSelf(PrintWriter pw) {
+ pw.print("Node ");
+ pw.print(name);
+ pw.print(" first ");
+ pw.print(512);
+ pw.print(" second ");
+ pw.print(1024);
+ pw.print(" third ");
+ pw.println(2048);
+ }
+
+ public void dumpDirect(PrintWriter pw, int depth) {
+ pw.print(sIndents[depth]);
+ dumpSelf(pw);
+
+ if (children != null) {
+ for (Node child : children) {
+ child.dumpDirect(pw, depth + 1);
+ }
+ }
+
+ pw.println();
+ }
+
+ public void dumpIndenting(IndentingPrintWriter pw) {
+ dumpSelf(pw);
+
+ if (children != null) {
+ pw.increaseIndent();
+ for (Node child : children) {
+ child.dumpIndenting(pw);
+ }
+ pw.decreaseIndent();
+ }
+
+ pw.println();
+ }
+ }
+}
diff --git a/core/tests/coretests/src/android/net/UriMatcherTest.java b/core/tests/coretests/src/android/net/UriMatcherTest.java
index 2872144..a728d4f 100644
--- a/core/tests/coretests/src/android/net/UriMatcherTest.java
+++ b/core/tests/coretests/src/android/net/UriMatcherTest.java
@@ -19,10 +19,11 @@
import android.content.UriMatcher;
import android.net.Uri;
import android.test.suitebuilder.annotation.SmallTest;
+
import junit.framework.TestCase;
-public class UriMatcherTest extends TestCase
-{
+public class UriMatcherTest extends TestCase {
+
static final int ROOT = 0;
static final int PEOPLE = 1;
static final int PEOPLE_ID = 2;
@@ -37,54 +38,76 @@
static final int CALLERID = 11;
static final int CALLERID_TEXT = 12;
static final int FILTERRECENT = 13;
-
+ static final int ANOTHER_PATH_SEGMENT = 13;
+
@SmallTest
public void testContentUris() {
- check("content://asdf", UriMatcher.NO_MATCH);
- check("content://people", PEOPLE);
- check("content://people/1", PEOPLE_ID);
- check("content://people/asdf", UriMatcher.NO_MATCH);
- check("content://people/2/phones", PEOPLE_PHONES);
- check("content://people/2/phones/3", PEOPLE_PHONES_ID);
- check("content://people/2/phones/asdf", UriMatcher.NO_MATCH);
- check("content://people/2/addresses", PEOPLE_ADDRESSES);
- check("content://people/2/addresses/3", PEOPLE_ADDRESSES_ID);
- check("content://people/2/addresses/asdf", UriMatcher.NO_MATCH);
- check("content://people/2/contact-methods", PEOPLE_CONTACTMETH);
- check("content://people/2/contact-methods/3", PEOPLE_CONTACTMETH_ID);
- check("content://people/2/contact-methods/asdf", UriMatcher.NO_MATCH);
- check("content://calls", CALLS);
- check("content://calls/1", CALLS_ID);
- check("content://calls/asdf", UriMatcher.NO_MATCH);
- check("content://caller-id", CALLERID);
- check("content://caller-id/asdf", CALLERID_TEXT);
- check("content://caller-id/1", CALLERID_TEXT);
- check("content://filter-recent", FILTERRECENT);
+ UriMatcher matcher = new UriMatcher(ROOT);
+ matcher.addURI("people", null, PEOPLE);
+ matcher.addURI("people", "#", PEOPLE_ID);
+ matcher.addURI("people", "#/phones", PEOPLE_PHONES);
+ matcher.addURI("people", "#/phones/blah", PEOPLE_PHONES_ID);
+ matcher.addURI("people", "#/phones/#", PEOPLE_PHONES_ID);
+ matcher.addURI("people", "#/addresses", PEOPLE_ADDRESSES);
+ matcher.addURI("people", "#/addresses/#", PEOPLE_ADDRESSES_ID);
+ matcher.addURI("people", "#/contact-methods", PEOPLE_CONTACTMETH);
+ matcher.addURI("people", "#/contact-methods/#", PEOPLE_CONTACTMETH_ID);
+ matcher.addURI("calls", null, CALLS);
+ matcher.addURI("calls", "#", CALLS_ID);
+ matcher.addURI("caller-id", null, CALLERID);
+ matcher.addURI("caller-id", "*", CALLERID_TEXT);
+ matcher.addURI("filter-recent", null, FILTERRECENT);
+ matcher.addURI("auth", "another/path/segment", ANOTHER_PATH_SEGMENT);
+ checkAll(matcher);
}
- private static final UriMatcher mURLMatcher = new UriMatcher(ROOT);
-
- static
- {
- mURLMatcher.addURI("people", null, PEOPLE);
- mURLMatcher.addURI("people", "#", PEOPLE_ID);
- mURLMatcher.addURI("people", "#/phones", PEOPLE_PHONES);
- mURLMatcher.addURI("people", "#/phones/blah", PEOPLE_PHONES_ID);
- mURLMatcher.addURI("people", "#/phones/#", PEOPLE_PHONES_ID);
- mURLMatcher.addURI("people", "#/addresses", PEOPLE_ADDRESSES);
- mURLMatcher.addURI("people", "#/addresses/#", PEOPLE_ADDRESSES_ID);
- mURLMatcher.addURI("people", "#/contact-methods", PEOPLE_CONTACTMETH);
- mURLMatcher.addURI("people", "#/contact-methods/#", PEOPLE_CONTACTMETH_ID);
- mURLMatcher.addURI("calls", null, CALLS);
- mURLMatcher.addURI("calls", "#", CALLS_ID);
- mURLMatcher.addURI("caller-id", null, CALLERID);
- mURLMatcher.addURI("caller-id", "*", CALLERID_TEXT);
- mURLMatcher.addURI("filter-recent", null, FILTERRECENT);
+ @SmallTest
+ public void testContentUrisWithLeadingSlash() {
+ UriMatcher matcher = new UriMatcher(ROOT);
+ matcher.addURI("people", null, PEOPLE);
+ matcher.addURI("people", "/#", PEOPLE_ID);
+ matcher.addURI("people", "/#/phones", PEOPLE_PHONES);
+ matcher.addURI("people", "/#/phones/blah", PEOPLE_PHONES_ID);
+ matcher.addURI("people", "/#/phones/#", PEOPLE_PHONES_ID);
+ matcher.addURI("people", "/#/addresses", PEOPLE_ADDRESSES);
+ matcher.addURI("people", "/#/addresses/#", PEOPLE_ADDRESSES_ID);
+ matcher.addURI("people", "/#/contact-methods", PEOPLE_CONTACTMETH);
+ matcher.addURI("people", "/#/contact-methods/#", PEOPLE_CONTACTMETH_ID);
+ matcher.addURI("calls", null, CALLS);
+ matcher.addURI("calls", "/#", CALLS_ID);
+ matcher.addURI("caller-id", null, CALLERID);
+ matcher.addURI("caller-id", "/*", CALLERID_TEXT);
+ matcher.addURI("filter-recent", null, FILTERRECENT);
+ matcher.addURI("auth", "/another/path/segment", ANOTHER_PATH_SEGMENT);
+ checkAll(matcher);
}
- void check(String uri, int expected)
- {
- int result = mURLMatcher.match(Uri.parse(uri));
+ private void checkAll(UriMatcher matcher) {
+ check("content://asdf", UriMatcher.NO_MATCH, matcher);
+ check("content://people", PEOPLE, matcher);
+ check("content://people/1", PEOPLE_ID, matcher);
+ check("content://people/asdf", UriMatcher.NO_MATCH, matcher);
+ check("content://people/2/phones", PEOPLE_PHONES, matcher);
+ check("content://people/2/phones/3", PEOPLE_PHONES_ID, matcher);
+ check("content://people/2/phones/asdf", UriMatcher.NO_MATCH, matcher);
+ check("content://people/2/addresses", PEOPLE_ADDRESSES, matcher);
+ check("content://people/2/addresses/3", PEOPLE_ADDRESSES_ID, matcher);
+ check("content://people/2/addresses/asdf", UriMatcher.NO_MATCH, matcher);
+ check("content://people/2/contact-methods", PEOPLE_CONTACTMETH, matcher);
+ check("content://people/2/contact-methods/3", PEOPLE_CONTACTMETH_ID, matcher);
+ check("content://people/2/contact-methods/asdf", UriMatcher.NO_MATCH, matcher);
+ check("content://calls", CALLS, matcher);
+ check("content://calls/1", CALLS_ID, matcher);
+ check("content://calls/asdf", UriMatcher.NO_MATCH, matcher);
+ check("content://caller-id", CALLERID, matcher);
+ check("content://caller-id/asdf", CALLERID_TEXT, matcher);
+ check("content://caller-id/1", CALLERID_TEXT, matcher);
+ check("content://filter-recent", FILTERRECENT, matcher);
+ check("content://auth/another/path/segment", ANOTHER_PATH_SEGMENT, matcher);
+ }
+
+ private void check(String uri, int expected, UriMatcher matcher) {
+ int result = matcher.match(Uri.parse(uri));
if (result != expected) {
String msg = "failed on " + uri;
msg += " expected " + expected + " got " + result;
diff --git a/libs/hwui/DeferredDisplayList.h b/libs/hwui/DeferredDisplayList.h
index cb9da8f..2afc8c1 100644
--- a/libs/hwui/DeferredDisplayList.h
+++ b/libs/hwui/DeferredDisplayList.h
@@ -52,6 +52,8 @@
kOpBatch_Count, // Add other batch ids before this
};
+ void clear();
+
bool isEmpty() { return mBatches.isEmpty(); }
/**
@@ -78,8 +80,6 @@
*/
void resetBatchingState();
- void clear();
-
void storeStateOpBarrier(OpenGLRenderer& renderer, StateOp* op);
void storeRestoreToCountBarrier(int newSaveCount);
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 1899002..2998535 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -18,6 +18,8 @@
#include <utils/Log.h>
+#include "DisplayList.h"
+#include "DeferredDisplayList.h"
#include "Layer.h"
#include "LayerRenderer.h"
#include "OpenGLRenderer.h"
@@ -43,15 +45,18 @@
fbo = 0;
stencil = NULL;
debugDrawUpdate = false;
+ deferredList = NULL;
Caches::getInstance().resourceCache.incrementRefcount(this);
}
Layer::~Layer() {
- if (mesh) delete mesh;
- if (meshIndices) delete meshIndices;
if (colorFilter) Caches::getInstance().resourceCache.decrementRefcount(colorFilter);
removeFbo();
deleteTexture();
+
+ delete[] mesh;
+ delete[] meshIndices;
+ delete deferredList;
}
uint32_t Layer::computeIdealWidth(uint32_t layerWidth) {
@@ -133,5 +138,43 @@
}
}
+void Layer::defer() {
+ if (!deferredList) {
+ deferredList = new DeferredDisplayList;
+ }
+ DeferStateStruct deferredState(*deferredList, *renderer,
+ DisplayList::kReplayFlag_ClipChildren);
+
+ const float width = layer.getWidth();
+ const float height = layer.getHeight();
+
+ if (dirtyRect.isEmpty() || (dirtyRect.left <= 0 && dirtyRect.top <= 0 &&
+ dirtyRect.right >= width && dirtyRect.bottom >= height)) {
+ dirtyRect.set(0, 0, width, height);
+ }
+
+ renderer->initViewport(width, height);
+ renderer->setupFrameState(dirtyRect.left, dirtyRect.top,
+ dirtyRect.right, dirtyRect.bottom, !isBlend());
+
+ displayList->defer(deferredState, 0);
+}
+
+void Layer::flush() {
+ if (deferredList && !deferredList->isEmpty()) {
+ renderer->setViewport(layer.getWidth(), layer.getHeight());
+ renderer->prepareDirty(dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom,
+ !isBlend());
+
+ deferredList->flush(*renderer, dirtyRect);
+
+ renderer->finish();
+ renderer = NULL;
+
+ dirtyRect.setEmpty();
+ deferredList->clear();
+ }
+}
+
}; // namespace uirenderer
}; // namespace android
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index ccf1da5..0e00191 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -42,6 +42,8 @@
// Forward declarations
class OpenGLRenderer;
class DisplayList;
+class DeferredDisplayList;
+class DeferStateStruct;
/**
* A layer has dimensions and is backed by an OpenGL texture or FBO.
@@ -271,6 +273,9 @@
return transform;
}
+ void defer();
+ void flush();
+
/**
* Bounds of the layer.
*/
@@ -379,6 +384,12 @@
*/
mat4 transform;
+ /**
+ * Used to defer display lists when the layer is updated with a
+ * display list.
+ */
+ DeferredDisplayList* deferredList;
+
}; // struct Layer
}; // namespace uirenderer
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 9aa9615..bb02286 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -129,8 +129,8 @@
void LayerRenderer::generateMesh() {
if (mLayer->region.isRect() || mLayer->region.isEmpty()) {
if (mLayer->mesh) {
- delete mLayer->mesh;
- delete mLayer->meshIndices;
+ delete[] mLayer->mesh;
+ delete[] mLayer->meshIndices;
mLayer->mesh = NULL;
mLayer->meshIndices = NULL;
@@ -153,8 +153,8 @@
GLsizei elementCount = count * 6;
if (mLayer->mesh && mLayer->meshElementCount < elementCount) {
- delete mLayer->mesh;
- delete mLayer->meshIndices;
+ delete[] mLayer->mesh;
+ delete[] mLayer->meshIndices;
mLayer->mesh = NULL;
mLayer->meshIndices = NULL;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 2cf7183..2903bcd 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -120,6 +120,7 @@
memcpy(mMeshVertices, gMeshVertices, sizeof(gMeshVertices));
mFirstSnapshot = new Snapshot;
+ mFrameStarted = false;
mScissorOptimizationDisabled = false;
}
@@ -179,14 +180,11 @@
mFirstSnapshot->viewport.set(0, 0, width, height);
}
-status_t OpenGLRenderer::prepare(bool opaque) {
- return prepareDirty(0.0f, 0.0f, mWidth, mHeight, opaque);
-}
-
-status_t OpenGLRenderer::prepareDirty(float left, float top,
+void OpenGLRenderer::setupFrameState(float left, float top,
float right, float bottom, bool opaque) {
mCaches.clearGarbage();
+ mOpaque = opaque;
mSnapshot = new Snapshot(mFirstSnapshot,
SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
mSnapshot->fbo = getTargetFbo();
@@ -194,13 +192,17 @@
mSnapshot->setClip(left, top, right, bottom);
mTilingClip.set(left, top, right, bottom);
+}
+
+status_t OpenGLRenderer::startFrame() {
+ if (mFrameStarted) return DrawGlInfo::kStatusDone;
+ mFrameStarted = true;
+
mDirtyClip = true;
- updateLayers();
+ discardFramebuffer(mTilingClip.left, mTilingClip.top, mTilingClip.right, mTilingClip.bottom);
- discardFramebuffer(left, top, right, bottom);
-
- syncState();
+ glViewport(0, 0, mWidth, mHeight);
// Functors break the tiling extension in pretty spectacular ways
// This ensures we don't use tiling when a functor is going to be
@@ -211,7 +213,30 @@
debugOverdraw(true, true);
- return clear(left, top, right, bottom, opaque);
+ return clear(mTilingClip.left, mTilingClip.top,
+ mTilingClip.right, mTilingClip.bottom, mOpaque);
+}
+
+status_t OpenGLRenderer::prepare(bool opaque) {
+ return prepareDirty(0.0f, 0.0f, mWidth, mHeight, opaque);
+}
+
+status_t OpenGLRenderer::prepareDirty(float left, float top,
+ float right, float bottom, bool opaque) {
+ setupFrameState(left, top, right, bottom, opaque);
+
+ // Layer renderers will start the frame immediately
+ // The framebuffer renderer will first defer the display list
+ // for each layer and wait until the first drawing command
+ // to start the frame
+ if (mSnapshot->fbo == 0) {
+ syncState();
+ updateLayers();
+ } else {
+ return startFrame();
+ }
+
+ return DrawGlInfo::kStatusDone;
}
void OpenGLRenderer::discardFramebuffer(float left, float top, float right, float bottom) {
@@ -241,8 +266,6 @@
}
void OpenGLRenderer::syncState() {
- glViewport(0, 0, mWidth, mHeight);
-
if (mCaches.blend) {
glEnable(GL_BLEND);
} else {
@@ -312,6 +335,8 @@
}
#endif
}
+
+ mFrameStarted = false;
}
void OpenGLRenderer::interrupt() {
@@ -406,6 +431,8 @@
}
status_t OpenGLRenderer::callDrawGLFunction(Functor* functor, Rect& dirty) {
+ if (mSnapshot->isIgnored()) return DrawGlInfo::kStatusDone;
+
interrupt();
detachFunctor(functor);
@@ -503,8 +530,8 @@
///////////////////////////////////////////////////////////////////////////////
bool OpenGLRenderer::updateLayer(Layer* layer, bool inFrame) {
- if (layer->deferredUpdateScheduled && layer->renderer && layer->displayList) {
- OpenGLRenderer* renderer = layer->renderer;
+ if (layer->deferredUpdateScheduled && layer->renderer &&
+ layer->displayList && layer->displayList->isRenderable()) {
Rect& dirty = layer->dirtyRect;
if (inFrame) {
@@ -512,19 +539,29 @@
debugOverdraw(false, false);
}
- renderer->setViewport(layer->layer.getWidth(), layer->layer.getHeight());
- renderer->prepareDirty(dirty.left, dirty.top, dirty.right, dirty.bottom, !layer->isBlend());
- renderer->drawDisplayList(layer->displayList, dirty, DisplayList::kReplayFlag_ClipChildren);
- renderer->finish();
+ if (CC_UNLIKELY(inFrame || mCaches.drawDeferDisabled)) {
+ OpenGLRenderer* renderer = layer->renderer;
+ renderer->setViewport(layer->layer.getWidth(), layer->layer.getHeight());
+ renderer->prepareDirty(dirty.left, dirty.top, dirty.right, dirty.bottom,
+ !layer->isBlend());
+ renderer->drawDisplayList(layer->displayList, dirty,
+ DisplayList::kReplayFlag_ClipChildren);
+ renderer->finish();
+ } else {
+ layer->defer();
+ }
if (inFrame) {
resumeAfterLayer();
startTiling(mSnapshot);
}
- dirty.setEmpty();
+ if (CC_UNLIKELY(inFrame || mCaches.drawDeferDisabled)) {
+ dirty.setEmpty();
+ layer->renderer = NULL;
+ }
+
layer->deferredUpdateScheduled = false;
- layer->renderer = NULL;
layer->displayList = NULL;
layer->debugDrawUpdate = mCaches.debugLayersUpdates;
@@ -535,19 +572,54 @@
}
void OpenGLRenderer::updateLayers() {
+ // If draw deferring is enabled this method will simply defer
+ // the display list of each individual layer. The layers remain
+ // in the layer updates list which will be cleared by flushLayers().
int count = mLayerUpdates.size();
if (count > 0) {
- startMark("Layer Updates");
+ if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
+ startMark("Layer Updates");
+ } else {
+ startMark("Defer Layer Updates");
+ }
// Note: it is very important to update the layers in reverse order
for (int i = count - 1; i >= 0; i--) {
Layer* layer = mLayerUpdates.itemAt(i);
updateLayer(layer, false);
- mCaches.resourceCache.decrementRefcount(layer);
+ if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
+ mCaches.resourceCache.decrementRefcount(layer);
+ }
}
- mLayerUpdates.clear();
+ if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
+ mLayerUpdates.clear();
+ glBindFramebuffer(GL_FRAMEBUFFER, getTargetFbo());
+ }
+ endMark();
+ }
+}
+
+void OpenGLRenderer::flushLayers() {
+ int count = mLayerUpdates.size();
+ if (count > 0) {
+ startMark("Apply Layer Updates");
+ char layerName[12];
+
+ // Note: it is very important to update the layers in reverse order
+ for (int i = count - 1; i >= 0; i--) {
+ sprintf(layerName, "Layer #%d", i);
+ startMark(layerName); {
+ Layer* layer = mLayerUpdates.itemAt(i);
+ layer->flush();
+ mCaches.resourceCache.decrementRefcount(layer);
+ }
+ endMark();
+ }
+
+ mLayerUpdates.clear();
glBindFramebuffer(GL_FRAMEBUFFER, getTargetFbo());
+
endMark();
}
}
@@ -679,6 +751,17 @@
}
}
+void OpenGLRenderer::updateSnapshotIgnoreForLayer(const Rect& bounds, const Rect& clip,
+ bool fboLayer, int alpha) {
+ if (bounds.isEmpty() || bounds.getWidth() > mCaches.maxTextureSize ||
+ bounds.getHeight() > mCaches.maxTextureSize ||
+ (fboLayer && clip.isEmpty())) {
+ mSnapshot->empty = fboLayer;
+ } else {
+ mSnapshot->invisible = mSnapshot->invisible || (alpha <= ALPHA_THRESHOLD && fboLayer);
+ }
+}
+
int OpenGLRenderer::saveLayerDeferred(float left, float top, float right, float bottom,
int alpha, SkXfermode::Mode mode, int flags) {
const GLuint previousFbo = mSnapshot->fbo;
@@ -692,8 +775,9 @@
Rect bounds(left, top, right, bottom);
Rect clip;
calculateLayerBoundsAndClip(bounds, clip, true);
+ updateSnapshotIgnoreForLayer(bounds, clip, true, alpha);
- if (!bounds.isEmpty() && !clip.isEmpty()) {
+ if (!mSnapshot->isIgnored()) {
mSnapshot->resetTransform(-bounds.left, -bounds.top, 0.0f);
mSnapshot->resetClip(clip.left, clip.top, clip.right, clip.bottom);
}
@@ -765,17 +849,10 @@
Rect clip;
Rect bounds(left, top, right, bottom);
calculateLayerBoundsAndClip(bounds, clip, fboLayer);
-
- if (bounds.isEmpty() || bounds.getWidth() > mCaches.maxTextureSize ||
- bounds.getHeight() > mCaches.maxTextureSize ||
- (fboLayer && clip.isEmpty())) {
- mSnapshot->empty = fboLayer;
- } else {
- mSnapshot->invisible = mSnapshot->invisible || (alpha <= ALPHA_THRESHOLD && fboLayer);
- }
+ updateSnapshotIgnoreForLayer(bounds, clip, fboLayer, alpha);
// Bail out if we won't draw in this snapshot
- if (mSnapshot->invisible || mSnapshot->empty) {
+ if (mSnapshot->isIgnored()) {
return false;
}
@@ -1832,6 +1909,7 @@
// will be performed by the display list itself
if (displayList && displayList->isRenderable()) {
if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
+ startFrame();
ReplayStateStruct replayStruct(*this, dirty, replayFlags);
displayList->replay(replayStruct, 0);
return replayStruct.mDrawGlStatus;
@@ -1840,6 +1918,10 @@
DeferredDisplayList deferredList;
DeferStateStruct deferStruct(deferredList, *this, replayFlags);
displayList->defer(deferStruct, 0);
+
+ flushLayers();
+ startFrame();
+
return deferredList.flush(*this, dirty);
}
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 7bb9395..b17bc3f 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -362,6 +362,18 @@
void initViewport(int width, int height);
/**
+ * Perform the setup specific to a frame. This method does not
+ * issue any OpenGL commands.
+ */
+ void setupFrameState(float left, float top, float right, float bottom, bool opaque);
+
+ /**
+ * Indicates the start of rendering. This method will setup the
+ * initial OpenGL state (viewport, clearing the buffer, etc.)
+ */
+ status_t startFrame();
+
+ /**
* Clears the underlying surface if needed.
*/
virtual status_t clear(float left, float top, float right, float bottom, bool opaque);
@@ -544,11 +556,17 @@
bool quickRejectPreStroke(float left, float top, float right, float bottom, SkPaint* paint);
/**
- * given the local bounds of the layer, calculates ...
+ * Given the local bounds of the layer, calculates ...
*/
void calculateLayerBoundsAndClip(Rect& bounds, Rect& clip, bool fboLayer);
/**
+ * Given the local bounds + clip of the layer, updates current snapshot's empty/invisible
+ */
+ void updateSnapshotIgnoreForLayer(const Rect& bounds, const Rect& clip,
+ bool fboLayer, int alpha);
+
+ /**
* Creates a new layer stored in the specified snapshot.
*
* @param snapshot The snapshot associated with the new layer
@@ -897,6 +915,7 @@
bool updateLayer(Layer* layer, bool inFrame);
void updateLayers();
+ void flushLayers();
/**
* Renders the specified region as a series of rectangles. This method
@@ -948,6 +967,10 @@
sp<Snapshot> mSnapshot;
// State used to define the clipping region
Rect mTilingClip;
+ // Is the target render surface opaque
+ bool mOpaque;
+ // Is a frame currently being rendered
+ bool mFrameStarted;
// Used to draw textured quads
TextureVertex mMeshVertices[4];
@@ -996,6 +1019,7 @@
String8 mName;
friend class DisplayListRenderer;
+ friend class Layer;
friend class TextSetupFunctor;
}; // class OpenGLRenderer
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index 07c4207..fdb10e2 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -262,12 +262,13 @@
PathTexture* texture = createTexture(left, top, offset, width, height,
path->getGenerationID());
- addTexture(entry, &bitmap, texture);
+ generateTexture(entry, &bitmap, texture);
return texture;
}
-void PathCache::addTexture(const PathDescription& entry, SkBitmap* bitmap, PathTexture* texture) {
+void PathCache::generateTexture(const PathDescription& entry, SkBitmap* bitmap,
+ PathTexture* texture, bool addToCache) {
generateTexture(*bitmap, texture);
uint32_t size = texture->width * texture->height;
@@ -278,7 +279,9 @@
if (mDebugEnabled) {
ALOGD("Shape created, size = %d", size);
}
- mCache.put(entry, texture);
+ if (addToCache) {
+ mCache.put(entry, texture);
+ }
} else {
texture->cleanup = true;
}
@@ -414,7 +417,7 @@
// producing the bitmap, so let's wait
SkBitmap* bitmap = task->getResult();
if (bitmap) {
- addTexture(entry, bitmap, texture);
+ generateTexture(entry, bitmap, texture, false);
texture->clearTask();
} else {
ALOGW("Path too large to be rendered into a texture");
@@ -423,6 +426,8 @@
mCache.remove(entry);
}
} else if (path->getGenerationID() != texture->generation) {
+ // The size of the path might have changed so we first
+ // remove the entry from the cache
mCache.remove(entry);
texture = addTexture(entry, path, paint);
}
diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h
index 1467231..dd1f996 100644
--- a/libs/hwui/PathCache.h
+++ b/libs/hwui/PathCache.h
@@ -253,7 +253,13 @@
PathTexture* addTexture(const PathDescription& entry,
const SkPath *path, const SkPaint* paint);
PathTexture* addTexture(const PathDescription& entry, SkBitmap* bitmap);
- void addTexture(const PathDescription& entry, SkBitmap* bitmap, PathTexture* texture);
+
+ /**
+ * Generates the texture from a bitmap into the specified texture structure.
+ */
+ void generateTexture(SkBitmap& bitmap, Texture* texture);
+ void generateTexture(const PathDescription& entry, SkBitmap* bitmap, PathTexture* texture,
+ bool addToCache = true);
PathTexture* get(const PathDescription& entry) {
return mCache.get(entry);
@@ -282,11 +288,6 @@
return true;
}
- /**
- * Generates the texture from a bitmap into the specified texture structure.
- */
- void generateTexture(SkBitmap& bitmap, Texture* texture);
-
void init();
class PathTask: public Task<SkBitmap*> {
diff --git a/media/java/android/media/audiofx/AudioEffect.java b/media/java/android/media/audiofx/AudioEffect.java
index 68a09de..031326e 100644
--- a/media/java/android/media/audiofx/AudioEffect.java
+++ b/media/java/android/media/audiofx/AudioEffect.java
@@ -72,55 +72,49 @@
* specification. The definitions match the corresponding interface IDs in
* OpenSLES_IID.h
*/
-
/**
- * UUID for environmental reverb effect
- * @hide
+ * UUID for environmental reverberation effect
*/
public static final UUID EFFECT_TYPE_ENV_REVERB = UUID
.fromString("c2e5d5f0-94bd-4763-9cac-4e234d06839e");
/**
- * UUID for preset reverb effect
- * @hide
+ * UUID for preset reverberation effect
*/
public static final UUID EFFECT_TYPE_PRESET_REVERB = UUID
.fromString("47382d60-ddd8-11db-bf3a-0002a5d5c51b");
/**
* UUID for equalizer effect
- * @hide
*/
public static final UUID EFFECT_TYPE_EQUALIZER = UUID
.fromString("0bed4300-ddd6-11db-8f34-0002a5d5c51b");
/**
* UUID for bass boost effect
- * @hide
*/
public static final UUID EFFECT_TYPE_BASS_BOOST = UUID
.fromString("0634f220-ddd4-11db-a0fc-0002a5d5c51b");
/**
* UUID for virtualizer effect
- * @hide
*/
public static final UUID EFFECT_TYPE_VIRTUALIZER = UUID
.fromString("37cc2c00-dddd-11db-8577-0002a5d5c51b");
/**
- * UUID for Automatic Gain Control (AGC) audio pre-processing
- * @hide
+ * UUIDs for effect types not covered by OpenSL ES.
+ */
+ /**
+ * UUID for Automatic Gain Control (AGC)
*/
public static final UUID EFFECT_TYPE_AGC = UUID
.fromString("0a8abfe0-654c-11e0-ba26-0002a5d5c51b");
/**
- * UUID for Acoustic Echo Canceler (AEC) audio pre-processing
- * @hide
+ * UUID for Acoustic Echo Canceler (AEC)
*/
public static final UUID EFFECT_TYPE_AEC = UUID
.fromString("7b491460-8d4d-11e0-bd61-0002a5d5c51b");
/**
- * UUID for Noise Suppressor (NS) audio pre-processing
- * @hide
+ * UUID for Noise Suppressor (NS)
*/
public static final UUID EFFECT_TYPE_NS = UUID
.fromString("58b4b260-8e06-11e0-aa8e-0002a5d5c51b");
@@ -199,7 +193,7 @@
* The effect descriptor contains information on a particular effect implemented in the
* audio framework:<br>
* <ul>
- * <li>type: UUID corresponding to the OpenSL ES interface implemented by this effect</li>
+ * <li>type: UUID identifying the effect type</li>
* <li>uuid: UUID for this particular implementation</li>
* <li>connectMode: {@link #EFFECT_INSERT}, {@link #EFFECT_AUXILIARY} or
* {at_link #EFFECT_PRE_PROCESSING}</li>
@@ -224,8 +218,14 @@
}
/**
- * Indicates the generic type of the effect (Equalizer, Bass boost ...). The UUID
- * corresponds to the OpenSL ES Interface ID for this type of effect.
+ * Indicates the generic type of the effect (Equalizer, Bass boost ...).
+ * One of {@link AudioEffect#EFFECT_TYPE_AEC},
+ * {@link AudioEffect#EFFECT_TYPE_AGC}, {@link AudioEffect#EFFECT_TYPE_BASS_BOOST},
+ * {@link AudioEffect#EFFECT_TYPE_ENV_REVERB}, {@link AudioEffect#EFFECT_TYPE_EQUALIZER},
+ * {@link AudioEffect#EFFECT_TYPE_NS}, {@link AudioEffect#EFFECT_TYPE_PRESET_REVERB}
+ * or {@link AudioEffect#EFFECT_TYPE_VIRTUALIZER}.<br>
+ * For reverberation, bass boost, EQ and virtualizer, the UUID
+ * corresponds to the OpenSL ES Interface ID.
*/
public UUID type;
/**
@@ -440,7 +440,7 @@
}
/**
- * Query all audio pre processing effects applied to the AudioRecord with the supplied
+ * Query all audio pre-processing effects applied to the AudioRecord with the supplied
* audio session ID. Returns an array of {@link android.media.audiofx.AudioEffect.Descriptor}
* objects.
* @param audioSession system wide unique audio session identifier.
diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h
index d4f932e..430721e 100644
--- a/services/input/InputDispatcher.h
+++ b/services/input/InputDispatcher.h
@@ -165,6 +165,8 @@
* Input dispatcher configuration.
*
* Specifies various options that modify the behavior of the input dispatcher.
+ * The values provided here are merely defaults. The actual values will come from ViewConfiguration
+ * and are passed into the dispatcher during initialization.
*/
struct InputDispatcherConfiguration {
// The key repeat initial timeout.
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index dd081a1..2d53023 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -88,6 +88,7 @@
import android.util.Slog;
import android.util.Xml;
import android.view.IWindowManager;
+import android.view.InputChannel;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -170,7 +171,7 @@
private final HardKeyboardListener mHardKeyboardListener;
private final WindowManagerService mWindowManagerService;
- final InputBindResult mNoBinding = new InputBindResult(null, null, -1);
+ final InputBindResult mNoBinding = new InputBindResult(null, null, null, -1);
// All known input methods. mMethodMap also serves as the global
// lock for this class.
@@ -202,7 +203,9 @@
class SessionState {
final ClientState client;
final IInputMethod method;
- final IInputMethodSession session;
+
+ IInputMethodSession session;
+ InputChannel channel;
@Override
public String toString() {
@@ -211,18 +214,20 @@
System.identityHashCode(method))
+ " session " + Integer.toHexString(
System.identityHashCode(session))
+ + " channel " + channel
+ "}";
}
SessionState(ClientState _client, IInputMethod _method,
- IInputMethodSession _session) {
+ IInputMethodSession _session, InputChannel _channel) {
client = _client;
method = _method;
session = _session;
+ channel = _channel;
}
}
- class ClientState {
+ static final class ClientState {
final IInputMethodClient client;
final IInputContext inputContext;
final int uid;
@@ -555,18 +560,21 @@
}
}
- private static class MethodCallback extends IInputSessionCallback.Stub {
- private final IInputMethod mMethod;
+ private static final class MethodCallback extends IInputSessionCallback.Stub {
private final InputMethodManagerService mParentIMMS;
+ private final IInputMethod mMethod;
+ private final InputChannel mChannel;
- MethodCallback(final IInputMethod method, final InputMethodManagerService imms) {
- mMethod = method;
+ MethodCallback(InputMethodManagerService imms, IInputMethod method,
+ InputChannel channel) {
mParentIMMS = imms;
+ mMethod = method;
+ mChannel = channel;
}
@Override
- public void sessionCreated(IInputMethodSession session) throws RemoteException {
- mParentIMMS.onSessionCreated(mMethod, session);
+ public void sessionCreated(IInputMethodSession session) {
+ mParentIMMS.onSessionCreated(mMethod, session, mChannel);
}
}
@@ -984,7 +992,10 @@
return;
}
synchronized (mMethodMap) {
- mClients.remove(client.asBinder());
+ ClientState cs = mClients.remove(client.asBinder());
+ if (cs != null) {
+ clearClientSessionLocked(cs);
+ }
}
}
@@ -1059,7 +1070,7 @@
if (DEBUG) Slog.v(TAG, "Attach new input asks to show input");
showCurrentInputLocked(getAppShowFlags(), null);
}
- return new InputBindResult(session.session, mCurId, mCurSeq);
+ return new InputBindResult(session.session, session.channel, mCurId, mCurSeq);
}
InputBindResult startInputLocked(IInputMethodClient client,
@@ -1137,16 +1148,10 @@
}
if (mHaveConnection) {
if (mCurMethod != null) {
- if (!cs.sessionRequested) {
- cs.sessionRequested = true;
- if (DEBUG) Slog.v(TAG, "Creating new session for client " + cs);
- executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
- MSG_CREATE_SESSION, mCurMethod,
- new MethodCallback(mCurMethod, this)));
- }
// Return to client, and we will get back with it when
// we have had a session made for it.
- return new InputBindResult(null, mCurId, mCurSeq);
+ requestClientSessionLocked(cs);
+ return new InputBindResult(null, null, mCurId, mCurSeq);
} else if (SystemClock.uptimeMillis()
< (mLastBindTime+TIME_TO_RECONNECT)) {
// In this case we have connected to the service, but
@@ -1156,7 +1161,7 @@
// we can report back. If it has been too long, we want
// to fall through so we can try a disconnect/reconnect
// to see if we can get back in touch with the service.
- return new InputBindResult(null, mCurId, mCurSeq);
+ return new InputBindResult(null, null, mCurId, mCurSeq);
} else {
EventLog.writeEvent(EventLogTags.IMF_FORCE_RECONNECT_IME,
mCurMethodId, SystemClock.uptimeMillis()-mLastBindTime, 0);
@@ -1175,7 +1180,7 @@
if (!mSystemReady) {
// If the system is not yet ready, we shouldn't be running third
// party code.
- return new InputBindResult(null, mCurMethodId, mCurSeq);
+ return new InputBindResult(null, null, mCurMethodId, mCurSeq);
}
InputMethodInfo info = mMethodMap.get(mCurMethodId);
@@ -1203,7 +1208,7 @@
WindowManager.LayoutParams.TYPE_INPUT_METHOD);
} catch (RemoteException e) {
}
- return new InputBindResult(null, mCurId, mCurSeq);
+ return new InputBindResult(null, null, mCurId, mCurSeq);
} else {
mCurIntent = null;
Slog.w(TAG, "Failure connecting to input method service: "
@@ -1246,32 +1251,34 @@
executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
MSG_ATTACH_TOKEN, mCurMethod, mCurToken));
if (mCurClient != null) {
- if (DEBUG) Slog.v(TAG, "Creating first session while with client "
- + mCurClient);
- executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
- MSG_CREATE_SESSION, mCurMethod,
- new MethodCallback(mCurMethod, this)));
+ clearClientSessionLocked(mCurClient);
+ requestClientSessionLocked(mCurClient);
}
}
}
}
- void onSessionCreated(IInputMethod method, IInputMethodSession session) {
+ void onSessionCreated(IInputMethod method, IInputMethodSession session,
+ InputChannel channel) {
synchronized (mMethodMap) {
if (mCurMethod != null && method != null
&& mCurMethod.asBinder() == method.asBinder()) {
if (mCurClient != null) {
+ clearClientSessionLocked(mCurClient);
mCurClient.curSession = new SessionState(mCurClient,
- method, session);
- mCurClient.sessionRequested = false;
+ method, session, channel);
InputBindResult res = attachNewInputLocked(true);
if (res.method != null) {
executeOrSendMessage(mCurClient.client, mCaller.obtainMessageOO(
MSG_BIND_METHOD, mCurClient.client, res));
}
+ return;
}
}
}
+
+ // Session abandoned. Close its associated input channel.
+ channel.dispose();
}
void unbindCurrentMethodLocked(boolean reportToClient, boolean savePosition) {
@@ -1306,14 +1313,38 @@
MSG_UNBIND_METHOD, mCurSeq, mCurClient.client));
}
}
-
- private void finishSession(SessionState sessionState) {
- if (sessionState != null && sessionState.session != null) {
- try {
- sessionState.session.finishSession();
- } catch (RemoteException e) {
- Slog.w(TAG, "Session failed to close due to remote exception", e);
- setImeWindowVisibilityStatusHiddenLocked();
+
+ void requestClientSessionLocked(ClientState cs) {
+ if (!cs.sessionRequested) {
+ if (DEBUG) Slog.v(TAG, "Creating new session for client " + cs);
+ InputChannel[] channels = InputChannel.openInputChannelPair(cs.toString());
+ cs.sessionRequested = true;
+ executeOrSendMessage(mCurMethod, mCaller.obtainMessageOOO(
+ MSG_CREATE_SESSION, mCurMethod, channels[1],
+ new MethodCallback(this, mCurMethod, channels[0])));
+ }
+ }
+
+ void clearClientSessionLocked(ClientState cs) {
+ finishSessionLocked(cs.curSession);
+ cs.curSession = null;
+ cs.sessionRequested = false;
+ }
+
+ private void finishSessionLocked(SessionState sessionState) {
+ if (sessionState != null) {
+ if (sessionState.session != null) {
+ try {
+ sessionState.session.finishSession();
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Session failed to close due to remote exception", e);
+ setImeWindowVisibilityStatusHiddenLocked();
+ }
+ sessionState.session = null;
+ }
+ if (sessionState.channel != null) {
+ sessionState.channel.dispose();
+ sessionState.channel = null;
}
}
}
@@ -1321,12 +1352,10 @@
void clearCurMethodLocked() {
if (mCurMethod != null) {
for (ClientState cs : mClients.values()) {
- cs.sessionRequested = false;
- finishSession(cs.curSession);
- cs.curSession = null;
+ clearClientSessionLocked(cs);
}
- finishSession(mEnabledSession);
+ finishSessionLocked(mEnabledSession);
mEnabledSession = null;
mCurMethod = null;
}
@@ -2325,15 +2354,21 @@
}
args.recycle();
return true;
- case MSG_CREATE_SESSION:
+ case MSG_CREATE_SESSION: {
args = (SomeArgs)msg.obj;
+ InputChannel channel = (InputChannel)args.arg2;
try {
- ((IInputMethod)args.arg1).createSession(
- (IInputSessionCallback)args.arg2);
+ ((IInputMethod)args.arg1).createSession(channel,
+ (IInputSessionCallback)args.arg3);
} catch (RemoteException e) {
+ } finally {
+ if (channel != null) {
+ channel.dispose();
+ }
}
args.recycle();
return true;
+ }
// ---------------------------------------------------------
case MSG_START_INPUT:
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 04ffbd9..88ef884 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -19,6 +19,7 @@
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import android.app.AppOpsManager;
+import android.appwidget.AppWidgetManager;
import com.android.internal.R;
import com.android.internal.os.BatteryStatsImpl;
import com.android.internal.os.ProcessStats;
@@ -11791,6 +11792,32 @@
+ callingPid + ", uid=" + callingUid;
Slog.w(TAG, msg);
throw new SecurityException(msg);
+ } else if (AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(intent.getAction())) {
+ // Special case for compatibility: we don't want apps to send this,
+ // but historically it has not been protected and apps may be using it
+ // to poke their own app widget. So, instead of making it protected,
+ // just limit it to the caller.
+ if (callerApp == null) {
+ String msg = "Permission Denial: not allowed to send broadcast "
+ + intent.getAction() + " from unknown caller.";
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
+ } else if (intent.getComponent() != null) {
+ // They are good enough to send to an explicit component... verify
+ // it is being sent to the calling app.
+ if (!intent.getComponent().getPackageName().equals(
+ callerApp.info.packageName)) {
+ String msg = "Permission Denial: not allowed to send broadcast "
+ + intent.getAction() + " to "
+ + intent.getComponent().getPackageName() + " from "
+ + callerApp.info.packageName;
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
+ }
+ } else {
+ // Limit broadcast to their own package.
+ intent.setPackage(callerApp.info.packageName);
+ }
}
} catch (RemoteException e) {
Slog.w(TAG, "Remote exception", e);
diff --git a/services/java/com/android/server/am/BroadcastQueue.java b/services/java/com/android/server/am/BroadcastQueue.java
index e8e8f25..ac7eb89 100644
--- a/services/java/com/android/server/am/BroadcastQueue.java
+++ b/services/java/com/android/server/am/BroadcastQueue.java
@@ -29,7 +29,6 @@
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -1080,6 +1079,9 @@
pw.print(" #"); pw.print(i); pw.print(": "); pw.println(r);
pw.print(" ");
pw.println(r.intent.toShortString(false, true, true, false));
+ if (r.targetComp != null && r.targetComp != r.intent.getComponent()) {
+ pw.print(" targetComp: "); pw.println(r.targetComp.toShortString());
+ }
Bundle bundle = r.intent.getExtras();
if (bundle != null) {
pw.print(" extras: "); pw.println(bundle.toString());
diff --git a/services/java/com/android/server/am/BroadcastRecord.java b/services/java/com/android/server/am/BroadcastRecord.java
index a98afb6..83cc0ea 100644
--- a/services/java/com/android/server/am/BroadcastRecord.java
+++ b/services/java/com/android/server/am/BroadcastRecord.java
@@ -38,6 +38,7 @@
*/
class BroadcastRecord extends Binder {
final Intent intent; // the original intent that generated us
+ final ComponentName targetComp; // original component name set on the intent
final ProcessRecord callerApp; // process that sent this
final String callerPackage; // who sent this
final int callingPid; // the pid of who sent this
@@ -84,9 +85,12 @@
pw.print(prefix); pw.print(this); pw.print(" to user "); pw.println(userId);
pw.print(prefix); pw.println(intent.toInsecureString());
+ if (targetComp != null && targetComp != intent.getComponent()) {
+ pw.print(prefix); pw.print(" targetComp: "); pw.println(targetComp.toShortString());
+ }
Bundle bundle = intent.getExtras();
if (bundle != null) {
- pw.print(prefix); pw.print("extras: "); pw.println(bundle.toString());
+ pw.print(prefix); pw.print(" extras: "); pw.println(bundle.toString());
}
pw.print(prefix); pw.print("caller="); pw.print(callerPackage); pw.print(" ");
pw.print(callerApp != null ? callerApp.toShortString() : "null");
@@ -174,6 +178,7 @@
int _userId) {
queue = _queue;
intent = _intent;
+ targetComp = _intent.getComponent();
callerApp = _callerApp;
callerPackage = _callerPackage;
callingPid = _callingPid;
diff --git a/services/java/com/android/server/content/ContentService.java b/services/java/com/android/server/content/ContentService.java
index 545ec93..68cf5fc 100644
--- a/services/java/com/android/server/content/ContentService.java
+++ b/services/java/com/android/server/content/ContentService.java
@@ -37,7 +37,6 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
-import android.text.format.DateUtils;
import android.util.Log;
import android.util.Slog;
import android.util.SparseIntArray;
@@ -408,10 +407,10 @@
"no permission to write the sync settings");
int userId = UserHandle.getCallingUserId();
- if (pollFrequency <= DateUtils.MINUTE_IN_MILLIS) {
+ if (pollFrequency < 60) {
Slog.w(TAG, "Requested poll frequency of " + pollFrequency
- + "ms being rounded up to 60 seconds.");
- pollFrequency = DateUtils.MINUTE_IN_MILLIS;
+ + " seconds being rounded up to 60 seconds.");
+ pollFrequency = 60;
}
long identityToken = clearCallingIdentity();
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index b46fb2f..34052f3 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -7291,6 +7291,7 @@
return false;
}
+ @Override
public void getInitialDisplaySize(int displayId, Point size) {
synchronized (mWindowMap) {
final DisplayContent displayContent = getDisplayContentLocked(displayId);
@@ -7304,6 +7305,19 @@
}
@Override
+ public void getBaseDisplaySize(int displayId, Point size) {
+ synchronized (mWindowMap) {
+ final DisplayContent displayContent = getDisplayContentLocked(displayId);
+ if (displayContent != null) {
+ synchronized(displayContent.mDisplaySizeLock) {
+ size.x = displayContent.mBaseDisplayWidth;
+ size.y = displayContent.mBaseDisplayHeight;
+ }
+ }
+ }
+ }
+
+ @Override
public void setForcedDisplaySize(int displayId, int width, int height) {
if (mContext.checkCallingOrSelfPermission(
android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
@@ -7406,6 +7420,32 @@
}
@Override
+ public int getInitialDisplayDensity(int displayId) {
+ synchronized (mWindowMap) {
+ final DisplayContent displayContent = getDisplayContentLocked(displayId);
+ if (displayContent != null) {
+ synchronized(displayContent.mDisplaySizeLock) {
+ return displayContent.mInitialDisplayDensity;
+ }
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public int getBaseDisplayDensity(int displayId) {
+ synchronized (mWindowMap) {
+ final DisplayContent displayContent = getDisplayContentLocked(displayId);
+ if (displayContent != null) {
+ synchronized(displayContent.mDisplaySizeLock) {
+ return displayContent.mBaseDisplayDensity;
+ }
+ }
+ }
+ return -1;
+ }
+
+ @Override
public void setForcedDisplayDensity(int displayId, int density) {
if (mContext.checkCallingOrSelfPermission(
android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 59ae1a1..6fbe32f 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -16,6 +16,7 @@
package android.view;
+import android.graphics.Point;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethodClient;
@@ -348,11 +349,31 @@
}
@Override
+ public void getInitialDisplaySize(int displayId, Point size) {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
+ public void getBaseDisplaySize(int displayId, Point size) {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
public void setForcedDisplaySize(int displayId, int arg0, int arg1) throws RemoteException {
// TODO Auto-generated method stub
}
@Override
+ public int getInitialDisplayDensity(int displayId) {
+ return -1;
+ }
+
+ @Override
+ public int getBaseDisplayDensity(int displayId) {
+ return -1;
+ }
+
+ @Override
public void setForcedDisplayDensity(int displayId, int density) throws RemoteException {
// TODO Auto-generated method stub
}