Merge "Fixed an issue with a test that didn't work properly"
diff --git a/api/current.txt b/api/current.txt
index bc2d893..ed114703 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -7267,6 +7267,7 @@
method public void registerSliceCallback(android.net.Uri, java.util.List<android.app.slice.SliceSpec>, java.util.concurrent.Executor, android.app.slice.SliceManager.SliceCallback);
method public void unpinSlice(android.net.Uri);
method public void unregisterSliceCallback(android.net.Uri, android.app.slice.SliceManager.SliceCallback);
+ field public static final java.lang.String SLICE_METADATA_KEY = "android.metadata.SLICE_URI";
}
public static abstract interface SliceManager.SliceCallback {
@@ -24075,13 +24076,14 @@
method public static final android.media.MediaPlayer2 create();
method public abstract void deselectTrack(int);
method public abstract android.media.DataSourceDesc editPlaylistItem(int, android.media.DataSourceDesc);
+ method public abstract android.media.AudioAttributes getAudioAttributes();
method public abstract int getAudioSessionId();
method public abstract android.media.DataSourceDesc getCurrentDataSource();
method public abstract int getCurrentPlaylistItemIndex();
- method public abstract int getCurrentPosition();
+ method public abstract long getCurrentPosition();
method public abstract android.media.MediaPlayer2.DrmInfo getDrmInfo();
method public abstract java.lang.String getDrmPropertyString(java.lang.String) throws android.media.MediaPlayer2.NoDrmSchemeException;
- method public abstract int getDuration();
+ method public abstract long getDuration();
method public abstract android.media.MediaDrm.KeyRequest getKeyRequest(byte[], byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws android.media.MediaPlayer2.NoDrmSchemeException;
method public abstract int getLoopingMode();
method public abstract android.os.PersistableBundle getMetrics();
@@ -24167,8 +24169,8 @@
public static abstract class MediaPlayer2.DrmEventCallback {
ctor public MediaPlayer2.DrmEventCallback();
- method public void onDrmInfo(android.media.MediaPlayer2, android.media.MediaPlayer2.DrmInfo);
- method public void onDrmPrepared(android.media.MediaPlayer2, int);
+ method public void onDrmInfo(android.media.MediaPlayer2, long, android.media.MediaPlayer2.DrmInfo);
+ method public void onDrmPrepared(android.media.MediaPlayer2, long, int);
}
public static abstract class MediaPlayer2.DrmInfo {
@@ -24206,7 +24208,7 @@
}
public static abstract interface MediaPlayer2.OnDrmConfigHelper {
- method public abstract void onDrmConfig(android.media.MediaPlayer2);
+ method public abstract void onDrmConfig(android.media.MediaPlayer2, long);
}
public static abstract class MediaPlayer2.ProvisioningNetworkErrorException extends android.media.MediaDrmException {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index ccbf21b..a45c500 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -7624,6 +7624,19 @@
/** @hide */
@Override
+ public final void autofillClientDispatchUnhandledKey(@NonNull View anchor,
+ @NonNull KeyEvent keyEvent) {
+ ViewRootImpl rootImpl = anchor.getViewRootImpl();
+ if (rootImpl != null) {
+ // dont care if anchorView is current focus, for example a custom view may only receive
+ // touchEvent, not focusable but can still trigger autofill window. The Key handling
+ // might be inside parent of the custom view.
+ rootImpl.dispatchKeyFromAutofill(keyEvent);
+ }
+ }
+
+ /** @hide */
+ @Override
public final boolean autofillClientRequestHideFillUi() {
if (mAutofillPopupWindow == null) {
return false;
diff --git a/core/java/android/app/slice/Slice.java b/core/java/android/app/slice/Slice.java
index 126deef..0a5795e 100644
--- a/core/java/android/app/slice/Slice.java
+++ b/core/java/android/app/slice/Slice.java
@@ -71,16 +71,6 @@
public @interface SliceHint {}
/**
- * The meta-data key that allows an activity to easily be linked directly to a slice.
- * <p>
- * An activity can be statically linked to a slice uri by including a meta-data item
- * for this key that contains a valid slice uri for the same application declaring
- * the activity.
- * @hide
- */
- public static final String SLICE_METADATA_KEY = "android.metadata.SLICE_URI";
-
- /**
* Hint that this content is a title of other content in the slice. This can also indicate that
* the content should be used in the shortcut representation of the slice (icon, label, action),
* normally this should be indicated by adding the hint on the action containing that content.
diff --git a/core/java/android/app/slice/SliceManager.java b/core/java/android/app/slice/SliceManager.java
index 3f13fff..a978e5b 100644
--- a/core/java/android/app/slice/SliceManager.java
+++ b/core/java/android/app/slice/SliceManager.java
@@ -60,6 +60,15 @@
public static final String ACTION_REQUEST_SLICE_PERMISSION =
"android.intent.action.REQUEST_SLICE_PERMISSION";
+ /**
+ * The meta-data key that allows an activity to easily be linked directly to a slice.
+ * <p>
+ * An activity can be statically linked to a slice uri by including a meta-data item
+ * for this key that contains a valid slice uri for the same application declaring
+ * the activity.
+ */
+ public static final String SLICE_METADATA_KEY = "android.metadata.SLICE_URI";
+
private final ISliceManager mService;
private final Context mContext;
private final ArrayMap<Pair<Uri, SliceCallback>, ISliceListener> mListenerLookup =
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 1e4f568..3c76242 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -7309,7 +7309,7 @@
}
private boolean isAccessibilityPane() {
- return !TextUtils.isEmpty(mAccessibilityPaneTitle);
+ return mAccessibilityPaneTitle != null;
}
/**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 810864e..01d9265 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -3925,6 +3925,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_DISPATCH_KEY_FROM_IME = 11;
+ private final static int MSG_DISPATCH_KEY_FROM_AUTOFILL = 12;
private final static int MSG_CHECK_FOCUS = 13;
private final static int MSG_CLOSE_SYSTEM_DIALOGS = 14;
private final static int MSG_DISPATCH_DRAG_EVENT = 15;
@@ -3966,6 +3967,8 @@
return "MSG_DISPATCH_GET_NEW_SURFACE";
case MSG_DISPATCH_KEY_FROM_IME:
return "MSG_DISPATCH_KEY_FROM_IME";
+ case MSG_DISPATCH_KEY_FROM_AUTOFILL:
+ return "MSG_DISPATCH_KEY_FROM_AUTOFILL";
case MSG_CHECK_FOCUS:
return "MSG_CHECK_FOCUS";
case MSG_CLOSE_SYSTEM_DIALOGS:
@@ -4143,6 +4146,15 @@
}
enqueueInputEvent(event, null, QueuedInputEvent.FLAG_DELIVER_POST_IME, true);
} break;
+ case MSG_DISPATCH_KEY_FROM_AUTOFILL: {
+ if (LOCAL_LOGV) {
+ Log.v(TAG, "Dispatching key " + msg.obj + " from Autofill to " + mView);
+ }
+ KeyEvent event = (KeyEvent) msg.obj;
+ // send InputEvent to pre IME, set FLAG_FROM_AUTOFILL so the InputEvent
+ // wont be dropped as app window is not focus.
+ enqueueInputEvent(event, null, QueuedInputEvent.FLAG_FROM_AUTOFILL, true);
+ } break;
case MSG_CHECK_FOCUS: {
InputMethodManager imm = InputMethodManager.peekInstance();
if (imm != null) {
@@ -4433,7 +4445,8 @@
Slog.w(mTag, "Dropping event due to root view being removed: " + q.mEvent);
return true;
} else if ((!mAttachInfo.mHasWindowFocus
- && !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) || mStopped
+ && !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)
+ && (q.mFlags & QueuedInputEvent.FLAG_FROM_AUTOFILL) == 0) || mStopped
|| (mIsAmbientMode && !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_BUTTON))
|| (mPausedForTransition && !isBack(q.mEvent))) {
// This is a focus event and the window doesn't currently have input focus or
@@ -6805,6 +6818,7 @@
public static final int FLAG_FINISHED_HANDLED = 1 << 3;
public static final int FLAG_RESYNTHESIZED = 1 << 4;
public static final int FLAG_UNHANDLED = 1 << 5;
+ public static final int FLAG_FROM_AUTOFILL = 1 << 6;
public QueuedInputEvent mNext;
@@ -7262,6 +7276,12 @@
mHandler.sendMessage(msg);
}
+ public void dispatchKeyFromAutofill(KeyEvent event) {
+ Message msg = mHandler.obtainMessage(MSG_DISPATCH_KEY_FROM_AUTOFILL, event);
+ msg.setAsynchronous(true);
+ mHandler.sendMessage(msg);
+ }
+
/**
* Reinject unhandled {@link InputEvent}s in order to synthesize fallbacks events.
*
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 7792fa6..dd9b69f 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -46,6 +46,7 @@
import android.util.Log;
import android.util.SparseArray;
import android.view.Choreographer;
+import android.view.KeyEvent;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
@@ -411,6 +412,13 @@
@Nullable Rect virtualBounds, IAutofillWindowPresenter presenter);
/**
+ * Dispatch unhandled keyevent from Autofill window
+ * @param anchor The real view the UI needs to anchor to.
+ * @param keyEvent Unhandled KeyEvent from autofill window.
+ */
+ void autofillClientDispatchUnhandledKey(@NonNull View anchor, @NonNull KeyEvent keyEvent);
+
+ /**
* Request hiding the autofill UI.
*
* @return Whether the UI was hidden.
@@ -1668,6 +1676,24 @@
}
}
+ private void dispatchUnhandledKey(int sessionId, AutofillId id, KeyEvent keyEvent) {
+ final View anchor = findView(id);
+ if (anchor == null) {
+ return;
+ }
+
+ AutofillCallback callback = null;
+ synchronized (mLock) {
+ if (mSessionId == sessionId) {
+ AutofillClient client = getClient();
+
+ if (client != null) {
+ client.autofillClientDispatchUnhandledKey(anchor, keyEvent);
+ }
+ }
+ }
+ }
+
/** @hide */
public static final int SET_STATE_FLAG_ENABLED = 0x01;
/** @hide */
@@ -2610,6 +2636,14 @@
}
@Override
+ public void dispatchUnhandledKey(int sessionId, AutofillId id, KeyEvent fullScreen) {
+ final AutofillManager afm = mAfm.get();
+ if (afm != null) {
+ afm.post(() -> afm.dispatchUnhandledKey(sessionId, id, fullScreen));
+ }
+ }
+
+ @Override
public void startIntentSender(IntentSender intentSender, Intent intent) {
final AutofillManager afm = mAfm.get();
if (afm != null) {
diff --git a/core/java/android/view/autofill/IAutoFillManagerClient.aidl b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
index 254c8a5..0ff7a0b 100644
--- a/core/java/android/view/autofill/IAutoFillManagerClient.aidl
+++ b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
@@ -25,6 +25,7 @@
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillValue;
import android.view.autofill.IAutofillWindowPresenter;
+import android.view.KeyEvent;
/**
* Object running in the application process and responsible for autofilling it.
@@ -74,6 +75,13 @@
void notifyNoFillUi(int sessionId, in AutofillId id, int sessionFinishedState);
/**
+ * Dispatches unhandled keyevent from autofill ui. Autofill ui handles DPAD and ENTER events,
+ * other unhandled keyevents are dispatched to app's window to filter autofill result.
+ * Note this method is not called when autofill ui is in fullscreen mode (TV only).
+ */
+ void dispatchUnhandledKey(int sessionId, in AutofillId id, in KeyEvent keyEvent);
+
+ /**
* Starts the provided intent sender.
*/
void startIntentSender(in IntentSender intentSender, in Intent intent);
diff --git a/core/res/res/layout/autofill_dataset_picker.xml b/core/res/res/layout/autofill_dataset_picker.xml
index a88836e..ef19f87 100644
--- a/core/res/res/layout/autofill_dataset_picker.xml
+++ b/core/res/res/layout/autofill_dataset_picker.xml
@@ -14,7 +14,8 @@
limitations under the License.
-->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<view xmlns:android="http://schemas.android.com/apk/res/android"
+ class="com.android.server.autofill.ui.FillUi$AutofillFrameLayout"
android:id="@+id/autofill_dataset_picker"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
@@ -30,4 +31,4 @@
android:visibility="gone">
</ListView>
-</FrameLayout>
+</view>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index e6186023..f4be888 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2106,6 +2106,10 @@
<string name="keyguard_accessibility_face_unlock">Face unlock.</string>
<!-- Accessibility description of the pin lock. [CHAR_LIMIT=none] -->
<string name="keyguard_accessibility_pin_unlock">Pin unlock.</string>
+ <!-- Accessibility description of the sim pin lock. [CHAR_LIMIT=none] -->
+ <string name="keyguard_accessibility_sim_pin_unlock">Sim Pin unlock.</string>
+ <!-- Accessibility description of the sim puk lock. [CHAR_LIMIT=none] -->
+ <string name="keyguard_accessibility_sim_puk_unlock">Sim Puk unlock.</string>
<!-- Accessibility description of the password lock. [CHAR_LIMIT=none] -->
<string name="keyguard_accessibility_password_unlock">Password unlock.</string>
<!-- Accessibility description of the unlock pattern area. [CHAR_LIMIT=none] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ab4c12b..fc4d4e7 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3234,6 +3234,11 @@
<java-symbol type="string" name="unsupported_compile_sdk_check_update" />
<java-symbol type="string" name="battery_saver_warning_title" />
+ <java-symbol type="string" name="keyguard_accessibility_pattern_unlock" />
+ <java-symbol type="string" name="keyguard_accessibility_pin_unlock" />
+ <java-symbol type="string" name="keyguard_accessibility_sim_pin_unlock" />
+ <java-symbol type="string" name="keyguard_accessibility_sim_puk_unlock" />
+ <java-symbol type="string" name="keyguard_accessibility_password_unlock" />
<java-symbol type="string" name="global_action_logout" />
<java-symbol type="string" name="config_mainBuiltInDisplayCutout" />
diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java
index 2f3d972..1446660 100644
--- a/media/java/android/media/MediaPlayer2.java
+++ b/media/java/android/media/MediaPlayer2.java
@@ -1223,7 +1223,7 @@
*
* @return the current position in milliseconds
*/
- public abstract int getCurrentPosition();
+ public abstract long getCurrentPosition();
/**
* Gets the duration of the file.
@@ -1231,7 +1231,7 @@
* @return the duration in milliseconds, if no duration is available
* (for example, if streaming live content), -1 is returned.
*/
- public abstract int getDuration();
+ public abstract long getDuration();
/**
* Gets the media metadata.
@@ -1278,27 +1278,6 @@
}
/**
- * Set the MediaPlayer2 to start when this MediaPlayer2 finishes playback
- * (i.e. reaches the end of the stream).
- * The media framework will attempt to transition from this player to
- * the next as seamlessly as possible. The next player can be set at
- * any time before completion, but shall be after setDataSource has been
- * called successfully. The next player must be prepared by the
- * app, and the application should not call play() on it.
- * The next MediaPlayer2 must be different from 'this'. An exception
- * will be thrown if next == this.
- * The application may call setNextMediaPlayer(null) to indicate no
- * next player should be started at the end of playback.
- * If the current player is looping, it will keep looping and the next
- * player will not be started.
- *
- * @param next the player to start after this one completes playback.
- *
- * @hide
- */
- public void setNextMediaPlayer(MediaPlayer2 next) { }
-
- /**
* Resets the MediaPlayer2 to its uninitialized state. After calling
* this method, you will have to initialize it again by setting the
* data source and calling prepareAsync().
@@ -1326,6 +1305,13 @@
public abstract void setAudioAttributes(AudioAttributes attributes);
/**
+ * Gets the audio attributes for this MediaPlayer2.
+ * @return attributes a set of audio attributes
+ * @throws IllegalArgumentException if the attributes are null or invalid.
+ */
+ public abstract AudioAttributes getAudioAttributes();
+
+ /**
* Sets the player to be looping or non-looping.
*
* @param looping whether to loop or not
@@ -2029,8 +2015,9 @@
* Called to give the app the opportunity to configure DRM before the session is created
*
* @param mp the {@code MediaPlayer2} associated with this callback
+ * @param srcId the Id of this data source
*/
- public void onDrmConfig(MediaPlayer2 mp);
+ public void onDrmConfig(MediaPlayer2 mp, long srcId);
}
/**
@@ -2051,24 +2038,25 @@
/**
* Called to indicate DRM info is available
*
- * @param mp the {@code MediaPlayer2} associated with this callback
- * @param drmInfo DRM info of the source including PSSH, and subset
- * of crypto schemes supported by this device
+ * @param mp the {@code MediaPlayer2} associated with this callback
+ * @param srcId the Id of this data source
+ * @param drmInfo DRM info of the source including PSSH, and subset
+ * of crypto schemes supported by this device
*/
- public void onDrmInfo(MediaPlayer2 mp, DrmInfo drmInfo) { }
+ public void onDrmInfo(MediaPlayer2 mp, long srcId, DrmInfo drmInfo) { }
/**
* Called to notify the client that {@code prepareDrm} is finished and ready for key request/response.
*
- * @param mp the {@code MediaPlayer2} associated with this callback
- * @param status the result of DRM preparation which can be
+ * @param mp the {@code MediaPlayer2} associated with this callback
+ * @param srcId the Id of this data source
+ * @param status the result of DRM preparation which can be
* {@link #PREPARE_DRM_STATUS_SUCCESS},
* {@link #PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR},
* {@link #PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR}, or
* {@link #PREPARE_DRM_STATUS_PREPARATION_ERROR}.
*/
- public void onDrmPrepared(MediaPlayer2 mp, @PrepareDrmStatusCode int status) { }
-
+ public void onDrmPrepared(MediaPlayer2 mp, long srcId, @PrepareDrmStatusCode int status) { }
}
/**
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java
index 1b21b5b..7794e08 100644
--- a/media/java/android/media/MediaPlayer2Impl.java
+++ b/media/java/android/media/MediaPlayer2Impl.java
@@ -1889,7 +1889,7 @@
* @return the current position in milliseconds
*/
@Override
- public native int getCurrentPosition();
+ public native long getCurrentPosition();
/**
* Gets the duration of the file.
@@ -1898,7 +1898,7 @@
* (for example, if streaming live content), -1 is returned.
*/
@Override
- public native int getDuration();
+ public native long getDuration();
/**
* Gets the media metadata.
@@ -1986,28 +1986,6 @@
}
/**
- * Set the MediaPlayer2 to start when this MediaPlayer2 finishes playback
- * (i.e. reaches the end of the stream).
- * The media framework will attempt to transition from this player to
- * the next as seamlessly as possible. The next player can be set at
- * any time before completion, but shall be after setDataSource has been
- * called successfully. The next player must be prepared by the
- * app, and the application should not call play() on it.
- * The next MediaPlayer2 must be different from 'this'. An exception
- * will be thrown if next == this.
- * The application may call setNextMediaPlayer(null) to indicate no
- * next player should be started at the end of playback.
- * If the current player is looping, it will keep looping and the next
- * player will not be started.
- *
- * @param next the player to start after this one completes playback.
- *
- * @hide
- */
- @Override
- public native void setNextMediaPlayer(MediaPlayer2 next);
-
- /**
* Resets the MediaPlayer2 to its uninitialized state. After calling
* this method, you will have to initialize it again by setting the
* data source and calling prepareAsync().
@@ -2078,10 +2056,11 @@
* @param key key indicates the parameter to be set.
* @param value value of the parameter to be set.
* @return true if the parameter is set successfully, false otherwise
- * {@hide}
*/
private native boolean setParameter(int key, Parcel value);
+ private native Parcel getParameter(int key);
+
/**
* Sets the audio attributes for this MediaPlayer2.
* See {@link AudioAttributes} for how to build and configure an instance of this class.
@@ -2105,6 +2084,14 @@
pattributes.recycle();
}
+ @Override
+ public AudioAttributes getAudioAttributes() {
+ Parcel pattributes = getParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES);
+ AudioAttributes attributes = AudioAttributes.CREATOR.createFromParcel(pattributes);
+ pattributes.recycle();
+ return attributes;
+ }
+
/**
* Sets the player to be looping or non-looping.
*
@@ -3211,11 +3198,12 @@
}
// notifying the client outside the lock
+ // TODO: get srcId
if (drmInfo != null) {
synchronized (mEventCbLock) {
for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) {
cb.first.execute(() -> cb.second.onDrmInfo(
- mMediaPlayer, drmInfo));
+ mMediaPlayer, 0, drmInfo));
}
}
}
@@ -3747,8 +3735,9 @@
// call the callback outside the lock
+ // TODO: get srcId
if (mOnDrmConfigHelper != null) {
- mOnDrmConfigHelper.onDrmConfig(this);
+ mOnDrmConfigHelper.onDrmConfig(this, 0);
}
synchronized (mDrmLock) {
@@ -3818,11 +3807,12 @@
// if finished successfully without provisioning, call the callback outside the lock
+ // TODO: get srcId
if (allDoneWithoutProvisioning) {
synchronized (mDrmEventCbLock) {
for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) {
cb.first.execute(() -> cb.second.onDrmPrepared(
- this, PREPARE_DRM_STATUS_SUCCESS));
+ this, 0, PREPARE_DRM_STATUS_SUCCESS));
}
}
}
@@ -4488,9 +4478,10 @@
} // synchronized
// calling the callback outside the lock
+ // TODO: get srcId
synchronized (mDrmEventCbLock) {
for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) {
- cb.first.execute(() -> cb.second.onDrmPrepared(mediaPlayer, status));
+ cb.first.execute(() -> cb.second.onDrmPrepared(mediaPlayer, 0, status));
}
}
} else { // blocking mode already has the lock
diff --git a/media/jni/android_media_MediaPlayer2.cpp b/media/jni/android_media_MediaPlayer2.cpp
index cf115a4..2258c78 100644
--- a/media/jni/android_media_MediaPlayer2.cpp
+++ b/media/jni/android_media_MediaPlayer2.cpp
@@ -760,7 +760,8 @@
return;
}
ALOGV("seekTo: %lld(msec), mode=%d", (long long)msec, mode);
- process_media_player_call( env, thiz, mp->seekTo((int)msec, (MediaPlayer2SeekMode)mode), NULL, NULL );
+ process_media_player_call(env, thiz, mp->seekTo((int64_t)msec, (MediaPlayer2SeekMode)mode),
+ NULL, NULL);
}
static void
@@ -838,7 +839,7 @@
return mybundle;
}
-static jint
+static jlong
android_media_MediaPlayer2_getCurrentPosition(JNIEnv *env, jobject thiz)
{
sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
@@ -846,13 +847,13 @@
jniThrowException(env, "java/lang/IllegalStateException", NULL);
return 0;
}
- int msec;
+ int64_t msec;
process_media_player_call( env, thiz, mp->getCurrentPosition(&msec), NULL, NULL );
- ALOGV("getCurrentPosition: %d (msec)", msec);
- return (jint) msec;
+ ALOGV("getCurrentPosition: %lld (msec)", (long long)msec);
+ return (jlong) msec;
}
-static jint
+static jlong
android_media_MediaPlayer2_getDuration(JNIEnv *env, jobject thiz)
{
sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
@@ -860,10 +861,10 @@
jniThrowException(env, "java/lang/IllegalStateException", NULL);
return 0;
}
- int msec;
+ int64_t msec;
process_media_player_call( env, thiz, mp->getDuration(&msec), NULL, NULL );
- ALOGV("getDuration: %d (msec)", msec);
- return (jint) msec;
+ ALOGV("getDuration: %lld (msec)", (long long)msec);
+ return (jlong) msec;
}
static void
@@ -911,6 +912,28 @@
}
}
+static jobject
+android_media_MediaPlayer2_getParameter(JNIEnv *env, jobject thiz, jint key)
+{
+ ALOGV("getParameter: key %d", key);
+ sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
+ if (mp == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ return NULL;
+ }
+
+ jobject jParcel = createJavaParcelObject(env);
+ if (jParcel != NULL) {
+ Parcel* nativeParcel = parcelForJavaObject(env, jParcel);
+ status_t err = mp->getParameter(key, nativeParcel);
+ if (err != OK) {
+ env->DeleteLocalRef(jParcel);
+ return NULL;
+ }
+ }
+ return jParcel;
+}
+
static void
android_media_MediaPlayer2_setLooping(JNIEnv *env, jobject thiz, jboolean looping)
{
@@ -1171,33 +1194,6 @@
process_media_player_call( env, thiz, mp->attachAuxEffect(effectId), NULL, NULL );
}
-static void
-android_media_MediaPlayer2_setNextMediaPlayer(JNIEnv *env, jobject thiz, jobject java_player)
-{
- ALOGV("setNextMediaPlayer");
- sp<MediaPlayer2> thisplayer = getMediaPlayer(env, thiz);
- if (thisplayer == NULL) {
- jniThrowException(env, "java/lang/IllegalStateException", "This player not initialized");
- return;
- }
- sp<MediaPlayer2> nextplayer = (java_player == NULL) ? NULL : getMediaPlayer(env, java_player);
- if (nextplayer == NULL && java_player != NULL) {
- jniThrowException(env, "java/lang/IllegalStateException", "That player not initialized");
- return;
- }
-
- if (nextplayer == thisplayer) {
- jniThrowException(env, "java/lang/IllegalArgumentException", "Next player can't be self");
- return;
- }
- // tie the two players together
- process_media_player_call(
- env, thiz, thisplayer->setNextMediaPlayer(nextplayer),
- "java/lang/IllegalArgumentException",
- "setNextMediaPlayer failed." );
- ;
-}
-
/////////////////////////////////////////////////////////////////////////////////////
// Modular DRM begin
@@ -1498,12 +1494,13 @@
{"_notifyAt", "(J)V", (void *)android_media_MediaPlayer2_notifyAt},
{"_pause", "()V", (void *)android_media_MediaPlayer2_pause},
{"isPlaying", "()Z", (void *)android_media_MediaPlayer2_isPlaying},
- {"getCurrentPosition", "()I", (void *)android_media_MediaPlayer2_getCurrentPosition},
- {"getDuration", "()I", (void *)android_media_MediaPlayer2_getDuration},
+ {"getCurrentPosition", "()J", (void *)android_media_MediaPlayer2_getCurrentPosition},
+ {"getDuration", "()J", (void *)android_media_MediaPlayer2_getDuration},
{"_release", "()V", (void *)android_media_MediaPlayer2_release},
{"_reset", "()V", (void *)android_media_MediaPlayer2_reset},
{"_getAudioStreamType", "()I", (void *)android_media_MediaPlayer2_getAudioStreamType},
{"setParameter", "(ILandroid/os/Parcel;)Z", (void *)android_media_MediaPlayer2_setParameter},
+ {"getParameter", "(I)Landroid/os/Parcel;", (void *)android_media_MediaPlayer2_getParameter},
{"setLooping", "(Z)V", (void *)android_media_MediaPlayer2_setLooping},
{"isLooping", "()Z", (void *)android_media_MediaPlayer2_isLooping},
{"_setVolume", "(FF)V", (void *)android_media_MediaPlayer2_setVolume},
@@ -1517,7 +1514,6 @@
{"setAudioSessionId", "(I)V", (void *)android_media_MediaPlayer2_set_audio_session_id},
{"_setAuxEffectSendLevel", "(F)V", (void *)android_media_MediaPlayer2_setAuxEffectSendLevel},
{"attachAuxEffect", "(I)V", (void *)android_media_MediaPlayer2_attachAuxEffect},
- {"setNextMediaPlayer", "(Landroid/media/MediaPlayer2;)V", (void *)android_media_MediaPlayer2_setNextMediaPlayer},
// Modular DRM
{ "_prepareDrm", "([B[B)V", (void *)android_media_MediaPlayer2_prepareDrm },
{ "_releaseDrm", "()V", (void *)android_media_MediaPlayer2_releaseDrm },
diff --git a/packages/InputDevices/res/values-as/strings.xml b/packages/InputDevices/res/values-as/strings.xml
new file mode 100644
index 0000000..26da1b1
--- /dev/null
+++ b/packages/InputDevices/res/values-as/strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="8016145283189546017">"ইনপুট ডিভাইচসমূহ"</string>
+ <string name="keyboard_layouts_label" msgid="6688773268302087545">"Android কীব\'ৰ্ড"</string>
+ <string name="keyboard_layout_english_uk_label" msgid="6664258463319999632">"ইংৰাজী (ইউ. কে.)"</string>
+ <string name="keyboard_layout_english_us_label" msgid="8994890249649106291">"ইংৰাজী ( ইউ. এছ.)"</string>
+ <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"ইংৰাজী (ইউ. কে.), আন্তঃৰাষ্ট্ৰীয় ষ্টাইল"</string>
+ <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"ইংৰাজী (ইউ. কে.), ক\'লমেক ষ্টাইল"</string>
+ <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"ইংৰাজী (ইউ. কে.), ডভ\'ৰাক ষ্টাইল"</string>
+ <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
+ <skip />
+ <string name="keyboard_layout_german_label" msgid="8451565865467909999">"জাৰ্মান"</string>
+ <string name="keyboard_layout_french_label" msgid="813450119589383723">"ফৰাচী"</string>
+ <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"ফৰাচী (কানাডা)"</string>
+ <string name="keyboard_layout_russian_label" msgid="8724879775815042968">"ৰাছিয়ান"</string>
+ <string name="keyboard_layout_russian_mac_label" msgid="3795866869038264796">"ৰাছিয়ান, মেক ষ্টাইল"</string>
+ <string name="keyboard_layout_spanish_label" msgid="7091555148131908240">"স্পেনিশ্ব"</string>
+ <string name="keyboard_layout_swiss_french_label" msgid="4659191025396371684">"ছুইছ ফৰাচী"</string>
+ <string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"ছুইছ জাৰ্মান"</string>
+ <string name="keyboard_layout_belgian" msgid="2011984572838651558">"বেলজিয়ান"</string>
+ <string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"বুলগেৰিয়ান"</string>
+ <string name="keyboard_layout_italian" msgid="6497079660449781213">"ইটালিয়ান"</string>
+ <string name="keyboard_layout_danish" msgid="8036432066627127851">"ডেনিশ্ব"</string>
+ <string name="keyboard_layout_norwegian" msgid="9090097917011040937">"ন\'ৰৱেয়ান"</string>
+ <string name="keyboard_layout_swedish" msgid="732959109088479351">"ছুইডিশ্ব"</string>
+ <string name="keyboard_layout_finnish" msgid="5585659438924315466">"ফিনিশ্ব"</string>
+ <string name="keyboard_layout_croatian" msgid="4172229471079281138">"ক্ৰ\'ৱেশ্বিয়ান"</string>
+ <string name="keyboard_layout_czech" msgid="1349256901452975343">"চ্চেক"</string>
+ <string name="keyboard_layout_estonian" msgid="8775830985185665274">"ইষ্ট\'নিয়া"</string>
+ <string name="keyboard_layout_hungarian" msgid="4154963661406035109">"হাংগেৰিয়ান"</string>
+ <string name="keyboard_layout_icelandic" msgid="5836645650912489642">"আইচলেণ্ডিক"</string>
+ <string name="keyboard_layout_brazilian" msgid="5117896443147781939">"ব্ৰাজিলিয়ান"</string>
+ <string name="keyboard_layout_portuguese" msgid="2888198587329660305">"পৰ্টুগীজ"</string>
+ <string name="keyboard_layout_slovak" msgid="2469379934672837296">"শ্ল\'ভাক"</string>
+ <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"শ্ল\'ভেনিয়া"</string>
+ <string name="keyboard_layout_turkish" msgid="7736163250907964898">"তুৰ্কী"</string>
+ <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ইউক্ৰেনিয়ান"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"আৰবী"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"গ্ৰীক"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"হিব্ৰু"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"লিথুৱানিয়ান"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"স্পেনিশ্ব (লেটিন)"</string>
+ <string name="keyboard_layout_latvian" msgid="4405417142306250595">"লাটভিয়ান"</string>
+ <!-- no translation found for keyboard_layout_persian (3920643161015888527) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_azerbaijani (7315895417176467567) -->
+ <skip />
+</resources>
diff --git a/packages/InputDevices/res/values-or/strings.xml b/packages/InputDevices/res/values-or/strings.xml
new file mode 100644
index 0000000..2b982da
--- /dev/null
+++ b/packages/InputDevices/res/values-or/strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="8016145283189546017">"ଇନପୁଟ୍ ଡିଭାଇସ୍"</string>
+ <string name="keyboard_layouts_label" msgid="6688773268302087545">"Android କୀ’ବୋର୍ଡ"</string>
+ <string name="keyboard_layout_english_uk_label" msgid="6664258463319999632">"ଇଂରାଜୀ (ୟୁକେ)"</string>
+ <string name="keyboard_layout_english_us_label" msgid="8994890249649106291">"ଇଂରାଜୀ (ୟୁଏସ୍)"</string>
+ <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"ଇଂରାଜୀ (ୟୁଏସ୍), ଇଣ୍ଟରନେସନାଲ୍ ଷ୍ଟାଇଲ୍"</string>
+ <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"ଇଂରାଜୀ (ୟୁଏସ୍), କୋଲେମକ୍ ଷ୍ଟାଇଲ୍"</string>
+ <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"ଇଂରାଜୀ (ୟୁଏସ୍), ଡଭୋରାକ୍ ଷ୍ଟାଇଲ୍"</string>
+ <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
+ <skip />
+ <string name="keyboard_layout_german_label" msgid="8451565865467909999">"ଜର୍ମାନ୍"</string>
+ <string name="keyboard_layout_french_label" msgid="813450119589383723">"ଫ୍ରେଞ୍ଚ"</string>
+ <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"ଫ୍ରେଞ୍ଚ (କାନାଡ଼ା)"</string>
+ <string name="keyboard_layout_russian_label" msgid="8724879775815042968">"ଋଷିଆନ୍"</string>
+ <string name="keyboard_layout_russian_mac_label" msgid="3795866869038264796">"ଋଷିଆନ୍, ମ୍ୟାକ୍ ଷ୍ଟାଇଲ୍"</string>
+ <string name="keyboard_layout_spanish_label" msgid="7091555148131908240">"ସ୍ପାନିଶ୍"</string>
+ <string name="keyboard_layout_swiss_french_label" msgid="4659191025396371684">"ସୁଇସ୍ ଫ୍ରେଞ୍ଚ"</string>
+ <string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"ସୁଇସ୍ ଜର୍ମାନ୍"</string>
+ <string name="keyboard_layout_belgian" msgid="2011984572838651558">"ବେଲ୍ଜିଆନ୍"</string>
+ <string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"ବୁଲଗାରିଆନ୍"</string>
+ <string name="keyboard_layout_italian" msgid="6497079660449781213">"ଇଟାଲିୟାନ୍"</string>
+ <string name="keyboard_layout_danish" msgid="8036432066627127851">"ଡାନିଶ୍"</string>
+ <string name="keyboard_layout_norwegian" msgid="9090097917011040937">"ନରୱେଜିଆନ୍"</string>
+ <string name="keyboard_layout_swedish" msgid="732959109088479351">"ସ୍ଵେଡିଶ୍"</string>
+ <string name="keyboard_layout_finnish" msgid="5585659438924315466">"ଫିନ୍ନିଶ୍"</string>
+ <string name="keyboard_layout_croatian" msgid="4172229471079281138">"କ୍ରୋଆଶିଆନ୍"</string>
+ <string name="keyboard_layout_czech" msgid="1349256901452975343">"ଚେକ୍"</string>
+ <string name="keyboard_layout_estonian" msgid="8775830985185665274">"ଇଷ୍ଟୋନିଆନ୍"</string>
+ <string name="keyboard_layout_hungarian" msgid="4154963661406035109">"ହଙ୍ଗେରିଆନ୍"</string>
+ <string name="keyboard_layout_icelandic" msgid="5836645650912489642">"ଆଇସଲାଣ୍ଡିକ୍"</string>
+ <string name="keyboard_layout_brazilian" msgid="5117896443147781939">"ବ୍ରାଜିଲିୟାନ୍"</string>
+ <string name="keyboard_layout_portuguese" msgid="2888198587329660305">"ପର୍ତ୍ତୁଗୀଜ୍"</string>
+ <string name="keyboard_layout_slovak" msgid="2469379934672837296">"ସ୍ଲୋଭାକ୍"</string>
+ <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"ସ୍ଲୋଭେନିଆନ୍"</string>
+ <string name="keyboard_layout_turkish" msgid="7736163250907964898">"ତୁର୍କିସ୍"</string>
+ <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ୟୁକ୍ରାନିଆନ୍"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"ଆରବିକ୍"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"ଗ୍ରୀକ୍"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"ହିବ୍ର୍ୟୁ"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"ଲିଥୁଆନିଆନ୍"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"ସ୍ପାନିଶ୍ (ଲାଟିନ୍)"</string>
+ <string name="keyboard_layout_latvian" msgid="4405417142306250595">"ଲାଟିଭିଆନ୍"</string>
+ <!-- no translation found for keyboard_layout_persian (3920643161015888527) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_azerbaijani (7315895417176467567) -->
+ <skip />
+</resources>
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index d919d6a..d284bf9 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -145,6 +145,8 @@
android:name="android.permission.MANAGE_WIFI_WHEN_PERMISSION_REVIEW_REQUIRED" />
<uses-permission android:name="android.permission.WATCH_APPOPS" />
+ <uses-permission android:name="android.permission.CONTROL_KEYGUARD" />
+
<application android:label="@string/app_label"
android:defaultToDeviceProtectedStorage="true"
android:directBootAware="true">
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
index f1a5ca9..474fc90 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
@@ -197,16 +197,6 @@
return false;
}
- @Override
- public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
- if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
- event.getText().add(mSecurityContainer.getCurrentSecurityModeContentDescription());
- return true;
- } else {
- return super.dispatchPopulateAccessibilityEvent(event);
- }
- }
-
protected KeyguardSecurityContainer getSecurityContainer() {
return mSecurityContainer;
}
@@ -255,6 +245,10 @@
}
}
+ public CharSequence getAccessibilityTitleForCurrentMode() {
+ return mSecurityContainer.getTitle();
+ }
+
public void userActivity() {
if (mViewMediatorCallback != null) {
mViewMediatorCallback.userActivity();
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
index ff5f5e7..75c52d8 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
@@ -361,4 +361,10 @@
}
return false;
}
+
+ @Override
+ public CharSequence getTitle() {
+ return getContext().getString(
+ com.android.internal.R.string.keyguard_accessibility_password_unlock);
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
index cb066a1..651831e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
@@ -491,4 +491,10 @@
public boolean hasOverlappingRendering() {
return false;
}
+
+ @Override
+ public CharSequence getTitle() {
+ return getContext().getString(
+ com.android.internal.R.string.keyguard_accessibility_pattern_unlock);
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
index 6539ccf..1d3f9a1 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -252,4 +252,10 @@
}
return false;
}
+
+ @Override
+ public CharSequence getTitle() {
+ return getContext().getString(
+ com.android.internal.R.string.keyguard_accessibility_pin_unlock);
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 8dc4609..c3413d9 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -119,19 +119,8 @@
return false;
}
- public void announceCurrentSecurityMethod() {
- View v = (View) getSecurityView(mCurrentSecuritySelection);
- if (v != null) {
- v.announceForAccessibility(v.getContentDescription());
- }
- }
-
- public CharSequence getCurrentSecurityModeContentDescription() {
- View v = (View) getSecurityView(mCurrentSecuritySelection);
- if (v != null) {
- return v.getContentDescription();
- }
- return "";
+ public CharSequence getTitle() {
+ return mSecurityViewFlipper.getTitle();
}
private KeyguardSecurityView getSecurityView(SecurityMode securityMode) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
index 360dba3..6e445ff 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
@@ -127,4 +127,12 @@
* animation started and {@code finishRunnable} will not be run
*/
boolean startDisappearAnimation(Runnable finishRunnable);
+
+ /**
+ * The localized name of the security view, provided to accessibility. This may be the content
+ * description, but content descriptions have other implications, so the title is kept separate.
+ *
+ * @return The View's title.
+ */
+ CharSequence getTitle();
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
index a2ff8f7..3aede56 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
@@ -173,6 +173,15 @@
}
@Override
+ public CharSequence getTitle() {
+ KeyguardSecurityView ksv = getSecurityView();
+ if (ksv != null) {
+ return ksv.getTitle();
+ }
+ return "";
+ }
+
+ @Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
return p instanceof LayoutParams;
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
index 703b205..c71c433 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
@@ -390,5 +390,11 @@
public boolean startDisappearAnimation(Runnable finishRunnable) {
return false;
}
+
+ @Override
+ public CharSequence getTitle() {
+ return getContext().getString(
+ com.android.internal.R.string.keyguard_accessibility_sim_pin_unlock);
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
index 347c979..1b61568 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
@@ -460,6 +460,12 @@
public boolean startDisappearAnimation(Runnable finishRunnable) {
return false;
}
+
+ @Override
+ public CharSequence getTitle() {
+ return getContext().getString(
+ com.android.internal.R.string.keyguard_accessibility_sim_puk_unlock);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 699e8cf..380c08e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -152,7 +152,6 @@
mKeyguardView.requestLayout();
}
mShowingSoon = false;
- mKeyguardView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
}
};
@@ -264,6 +263,7 @@
mStatusBarHeight = mRoot.getResources().getDimensionPixelOffset(
com.android.systemui.R.dimen.status_bar_height);
mRoot.setVisibility(View.INVISIBLE);
+ mRoot.setAccessibilityPaneTitle(mKeyguardView.getAccessibilityTitleForCurrentMode());
final WindowInsets rootInsets = mRoot.getRootWindowInsets();
if (rootInsets != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index dc400e6..e86d88d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -580,8 +580,7 @@
private boolean shouldDisableNavbarGestures() {
return !mStatusBar.isDeviceProvisioned()
- || (mDisabledFlags1 & StatusBarManager.DISABLE_SEARCH) != 0
- || mNavigationBarView.getRecentsButton().getVisibility() != View.VISIBLE;
+ || (mDisabledFlags1 & StatusBarManager.DISABLE_SEARCH) != 0;
}
private void repositionNavigationBar() {
@@ -600,13 +599,10 @@
// Change the cancel pin gesture to home and back if recents button is invisible
boolean recentsVisible = mNavigationBarView.isRecentsButtonVisible();
- ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
ButtonDispatcher backButton = mNavigationBarView.getBackButton();
if (recentsVisible) {
- homeButton.setOnLongClickListener(this::onHomeLongClick);
backButton.setOnLongClickListener(this::onLongPressBackRecents);
} else {
- homeButton.setOnLongClickListener(this::onLongPressBackHome);
backButton.setOnLongClickListener(this::onLongPressBackHome);
}
}
@@ -629,6 +625,7 @@
ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
homeButton.setOnTouchListener(this::onHomeTouch);
+ homeButton.setOnLongClickListener(this::onHomeLongClick);
ButtonDispatcher accessibilityButton = mNavigationBarView.getAccessibilityButton();
accessibilityButton.setOnClickListener(this::onAccessibilityClick);
@@ -681,6 +678,9 @@
@VisibleForTesting
boolean onHomeLongClick(View v) {
+ if (!mNavigationBarView.isRecentsButtonVisible() && mNavigationBarView.inScreenPinning()) {
+ return onLongPressBackHome(v);
+ }
if (shouldDisableNavbarGestures()) {
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java
index dd4d1f6..b82b0ee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java
@@ -380,7 +380,7 @@
}
private void startQuickScrub() {
- if (!mQuickScrubActive) {
+ if (!mQuickScrubActive && mDraggingActive) {
mQuickScrubActive = true;
mLightTrackColor = mContext.getColor(R.color.quick_step_track_background_light);
mDarkTrackColor = mContext.getColor(R.color.quick_step_track_background_dark);
@@ -394,6 +394,9 @@
} catch (RemoteException e) {
Log.e(TAG, "Failed to send start of quick scrub.", e);
}
+ } else {
+ // After long press do not allow quick scrub/switch
+ mTouchDownX = -1;
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
index fc043c5..944e888 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
@@ -26,6 +26,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
+import android.support.test.filters.FlakyTest;
import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -76,6 +77,7 @@
mSpacing = res.getDimensionPixelSize(R.dimen.smart_reply_button_spacing);
}
+ @FlakyTest
@Test
public void testSendSmartReply_intentContainsResultsAndSource() throws InterruptedException {
setRepliesFromRemoteInput(TEST_CHOICES);
@@ -180,6 +182,7 @@
assertEqualLayouts(expectedView.getChildAt(2), mView.getChildAt(2));
}
+ @FlakyTest
@Test
public void testMeasure_choiceWithThreeLines() {
final CharSequence[] choices = new CharSequence[]{"Hi", "Hello\nevery\nbody", "Bye"};
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 32f03b3..bcfe1b6 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -76,6 +76,7 @@
import android.util.Slog;
import android.util.SparseArray;
import android.util.TimeUtils;
+import android.view.KeyEvent;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillValue;
@@ -812,6 +813,27 @@
}
}
+ @Override
+ public void dispatchUnhandledKey(AutofillId id, KeyEvent keyEvent) {
+ synchronized (mLock) {
+ if (mDestroyed) {
+ Slog.w(TAG, "Call to Session#dispatchUnhandledKey() rejected - session: "
+ + id + " destroyed");
+ return;
+ }
+ if (id.equals(mCurrentViewId)) {
+ try {
+ mClient.dispatchUnhandledKey(this.id, id, keyEvent);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Error requesting to dispatch unhandled key", e);
+ }
+ } else {
+ Slog.w(TAG, "Do not dispatch unhandled key on " + id
+ + " as it is not the current view (" + mCurrentViewId + ") anymore");
+ }
+ }
+ }
+
// AutoFillUiCallback
@Override
public void requestHideFillUi(AutofillId id) {
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index dc36518..e28a204 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -34,6 +34,7 @@
import android.service.autofill.ValueFinder;
import android.text.TextUtils;
import android.util.Slog;
+import android.view.KeyEvent;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
import android.view.autofill.IAutofillWindowPresenter;
@@ -78,6 +79,7 @@
IAutofillWindowPresenter presenter);
void requestHideFillUi(AutofillId id);
void startIntentSender(IntentSender intentSender);
+ void dispatchUnhandledKey(AutofillId id, KeyEvent keyEvent);
}
public AutoFillUI(@NonNull Context context) {
@@ -240,6 +242,13 @@
mCallback.startIntentSender(intentSender);
}
}
+
+ @Override
+ public void dispatchUnhandledKey(KeyEvent keyEvent) {
+ if (mCallback != null) {
+ mCallback.dispatchUnhandledKey(focusedId, keyEvent);
+ }
+ }
});
});
}
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index d64244d..7278e83 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -18,6 +18,7 @@
import static com.android.server.autofill.Helper.sDebug;
import static com.android.server.autofill.Helper.sVerbose;
+import android.annotation.AttrRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.PendingIntent;
@@ -31,8 +32,10 @@
import android.service.autofill.Dataset.DatasetFieldFilter;
import android.service.autofill.FillResponse;
import android.text.TextUtils;
+import android.util.AttributeSet;
import android.util.Slog;
import android.util.TypedValue;
+import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
@@ -47,6 +50,7 @@
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
+import android.widget.FrameLayout;
import android.widget.ListView;
import android.widget.RemoteViews;
@@ -69,6 +73,28 @@
private static final TypedValue sTempTypedValue = new TypedValue();
+ public static final class AutofillFrameLayout extends FrameLayout {
+
+ OnKeyListener mUnhandledListener;
+
+ public AutofillFrameLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public AutofillFrameLayout(Context context, AttributeSet attrs, @AttrRes int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ boolean handled = super.dispatchKeyEvent(event);
+ if (!handled) {
+ handled = mUnhandledListener.onKey(this, event.getKeyCode(), event);
+ }
+ return handled;
+ }
+ }
+
interface Callback {
void onResponsePicked(@NonNull FillResponse response);
void onDatasetPicked(@NonNull Dataset dataset);
@@ -78,6 +104,7 @@
IAutofillWindowPresenter windowPresenter);
void requestHideFillUi();
void startIntentSender(IntentSender intentSender);
+ void dispatchUnhandledKey(KeyEvent keyEvent);
}
private final @NonNull Point mTempPoint = new Point();
@@ -122,6 +149,31 @@
mFullScreen ? R.layout.autofill_dataset_picker_fullscreen
: R.layout.autofill_dataset_picker, null);
+ // if autofill ui is not fullscreen, send unhandled keyevent to app window.
+ if (!mFullScreen) {
+ if (decor instanceof AutofillFrameLayout) {
+ ((AutofillFrameLayout) decor).mUnhandledListener =
+ (View view, int keyCode, KeyEvent event) -> {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_BACK:
+ case KeyEvent.KEYCODE_ESCAPE:
+ case KeyEvent.KEYCODE_ENTER:
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ case KeyEvent.KEYCODE_DPAD_UP:
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ return false;
+ default:
+ mCallback.dispatchUnhandledKey(event);
+ return true;
+ }
+ };
+ } else {
+ Slog.wtf(TAG, "Unable to send unhandled key");
+ }
+ }
+
final RemoteViews.OnClickHandler interceptionHandler = new RemoteViews.OnClickHandler() {
@Override
public boolean onClickHandler(View view, PendingIntent pendingIntent,
diff --git a/services/net/java/android/net/ip/IpClient.java b/services/net/java/android/net/ip/IpClient.java
index d3a97b3..1f370a5 100644
--- a/services/net/java/android/net/ip/IpClient.java
+++ b/services/net/java/android/net/ip/IpClient.java
@@ -72,6 +72,7 @@
import java.util.List;
import java.util.Set;
import java.util.StringJoiner;
+import java.util.concurrent.CountDownLatch;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@@ -100,6 +101,11 @@
/**
* Callbacks for handling IpClient events.
+ *
+ * These methods are called by IpClient on its own thread. Implementations
+ * of this class MUST NOT carry out long-running computations or hold locks
+ * for which there might be contention with other code calling public
+ * methods of the same IpClient instance.
*/
public static class Callback {
// In order to receive onPreDhcpAction(), call #withPreDhcpAction()
@@ -545,6 +551,7 @@
private final String mClatInterfaceName;
@VisibleForTesting
protected final Callback mCallback;
+ private final CountDownLatch mShutdownLatch;
private final INetworkManagementService mNwService;
private final NetlinkTracker mNetlinkTracker;
private final WakeupMessage mProvisioningTimeoutAlarm;
@@ -597,6 +604,7 @@
mInterfaceName = ifName;
mClatInterfaceName = CLAT_PREFIX + ifName;
mCallback = new LoggingCallbackWrapper(callback);
+ mShutdownLatch = new CountDownLatch(1);
mNwService = nwService;
mLog = new SharedLog(MAX_LOG_RECORDS, mTag);
@@ -704,6 +712,7 @@
@Override
protected void onQuitting() {
mCallback.onQuit();
+ mShutdownLatch.countDown();
}
// Shut down this IpClient instance altogether.
@@ -712,6 +721,17 @@
sendMessage(CMD_TERMINATE_AFTER_STOP);
}
+ // In order to avoid deadlock, this method MUST NOT be called on the
+ // IpClient instance's thread. This prohibition includes code executed by
+ // when methods on the passed-in IpClient.Callback instance are called.
+ public void awaitShutdown() {
+ try {
+ mShutdownLatch.await();
+ } catch (InterruptedException e) {
+ mLog.e("Interrupted while awaiting shutdown: " + e);
+ }
+ }
+
public static ProvisioningConfiguration.Builder buildProvisioningConfiguration() {
return new ProvisioningConfiguration.Builder();
}