summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--api/current.txt24
-rw-r--r--api/system-current.txt24
-rw-r--r--core/java/android/annotation/TransitionRes.java37
-rw-r--r--core/java/android/app/ActivityManagerNative.java24
-rw-r--r--core/java/android/app/IActivityManager.java4
-rw-r--r--core/java/android/app/ResourcesManager.java17
-rw-r--r--core/java/android/app/VoiceInteractor.aidl19
-rw-r--r--core/java/android/app/VoiceInteractor.java282
-rw-r--r--core/java/android/content/Intent.java25
-rw-r--r--core/java/android/hardware/camera2/DngCreator.java2
-rw-r--r--core/java/android/os/Parcel.java34
-rw-r--r--core/java/android/preference/PreferenceFragment.java3
-rw-r--r--core/java/android/provider/Settings.java1
-rw-r--r--core/java/android/service/voice/VoiceInteractionSession.java90
-rw-r--r--core/java/android/speech/tts/TextToSpeech.java2
-rw-r--r--core/java/android/transition/TransitionInflater.java8
-rw-r--r--core/java/android/view/ContextThemeWrapper.java3
-rw-r--r--core/java/android/view/View.java3
-rw-r--r--core/java/android/view/Window.java3
-rw-r--r--core/java/android/view/animation/Animation.java3
-rw-r--r--core/java/android/view/animation/LayoutAnimationController.java6
-rw-r--r--core/java/android/widget/ActionMenuView.java3
-rw-r--r--core/java/android/widget/ArrayAdapter.java11
-rw-r--r--core/java/android/widget/FastScroller.java3
-rw-r--r--core/java/android/widget/SimpleAdapter.java4
-rw-r--r--core/java/android/widget/Toolbar.java24
-rw-r--r--core/java/android/widget/ViewAnimator.java5
-rw-r--r--core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl1
-rw-r--r--core/java/com/android/internal/app/IVoiceInteractor.aidl4
-rw-r--r--core/java/com/android/internal/app/IVoiceInteractorCallback.aidl5
-rw-r--r--core/java/com/android/internal/os/HandlerCaller.java9
-rw-r--r--core/jni/android_database_SQLiteGlobal.cpp12
-rw-r--r--core/res/AndroidManifest.xml2
-rw-r--r--graphics/java/android/graphics/PorterDuffColorFilter.java3
-rw-r--r--graphics/java/android/graphics/drawable/Drawable.java2
-rw-r--r--media/java/android/media/MediaCodecInfo.java4
-rw-r--r--media/java/android/media/MediaFormat.java4
-rw-r--r--media/java/android/media/WebVttRenderer.java4
-rw-r--r--media/java/android/media/midi/MidiDeviceInfo.java12
-rw-r--r--media/java/android/media/tv/TvTrackInfo.java34
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java12
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java125
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java9
-rw-r--r--rs/java/android/renderscript/Script.java6
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java48
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java54
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java4
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java8
-rw-r--r--services/core/java/com/android/server/notification/ManagedServices.java83
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java18
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java12
-rw-r--r--tests/VoiceInteraction/res/layout/test_interaction.xml7
-rw-r--r--tests/VoiceInteraction/res/values/strings.xml2
-rw-r--r--tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java73
-rw-r--r--tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java49
-rw-r--r--tools/aapt/XMLNode.cpp36
57 files changed, 1109 insertions, 198 deletions
diff --git a/Android.mk b/Android.mk
index 452d72c1e28d..84cad4e268f7 100644
--- a/Android.mk
+++ b/Android.mk
@@ -559,6 +559,7 @@ aidl_files := \
frameworks/base/core/java/android/app/PendingIntent.aidl \
frameworks/base/core/java/android/app/AlarmManager.aidl \
frameworks/base/core/java/android/app/SearchableInfo.aidl \
+ frameworks/base/core/java/android/app/VoiceInteractor.aidl \
frameworks/base/core/java/android/app/job/JobParameters.aidl \
frameworks/base/core/java/android/app/job/JobInfo.aidl \
frameworks/base/core/java/android/appwidget/AppWidgetProviderInfo.aidl \
diff --git a/api/current.txt b/api/current.txt
index c05254a7c86a..7bac613a5c56 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5355,8 +5355,25 @@ package android.app {
method public void onConfirmationResult(boolean, android.os.Bundle);
}
+ public static class VoiceInteractor.PickOptionRequest extends android.app.VoiceInteractor.Request {
+ ctor public VoiceInteractor.PickOptionRequest(java.lang.CharSequence, android.app.VoiceInteractor.PickOptionRequest.Option[], android.os.Bundle);
+ method public void onPickOptionResult(boolean, android.app.VoiceInteractor.PickOptionRequest.Option[], android.os.Bundle);
+ }
+
+ public static final class VoiceInteractor.PickOptionRequest.Option implements android.os.Parcelable {
+ ctor public VoiceInteractor.PickOptionRequest.Option(java.lang.CharSequence);
+ method public android.app.VoiceInteractor.PickOptionRequest.Option addSynonym(java.lang.CharSequence);
+ method public int countSynonyms();
+ method public int describeContents();
+ method public android.os.Bundle getExtras();
+ method public java.lang.CharSequence getLabel();
+ method public java.lang.CharSequence getSynonymAt(int);
+ method public void setExtras(android.os.Bundle);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.VoiceInteractor.PickOptionRequest.Option> CREATOR;
+ }
+
public static abstract class VoiceInteractor.Request {
- ctor public VoiceInteractor.Request();
method public void cancel();
method public android.app.Activity getActivity();
method public android.content.Context getContext();
@@ -17315,6 +17332,7 @@ package android.media.tv {
method public int describeContents();
method public final int getAudioChannelCount();
method public final int getAudioSampleRate();
+ method public final java.lang.String getDescription();
method public final android.os.Bundle getExtra();
method public final java.lang.String getId();
method public final java.lang.String getLanguage();
@@ -17334,6 +17352,7 @@ package android.media.tv {
method public android.media.tv.TvTrackInfo build();
method public final android.media.tv.TvTrackInfo.Builder setAudioChannelCount(int);
method public final android.media.tv.TvTrackInfo.Builder setAudioSampleRate(int);
+ method public final android.media.tv.TvTrackInfo.Builder setDescription(java.lang.String);
method public final android.media.tv.TvTrackInfo.Builder setExtra(android.os.Bundle);
method public final android.media.tv.TvTrackInfo.Builder setLanguage(java.lang.String);
method public final android.media.tv.TvTrackInfo.Builder setVideoFrameRate(float);
@@ -27895,10 +27914,12 @@ package android.service.voice {
method public boolean onKeyLongPress(int, android.view.KeyEvent);
method public boolean onKeyMultiple(int, int, android.view.KeyEvent);
method public boolean onKeyUp(int, android.view.KeyEvent);
+ method public abstract void onPickOption(android.service.voice.VoiceInteractionSession.Caller, android.service.voice.VoiceInteractionSession.Request, java.lang.CharSequence, android.app.VoiceInteractor.PickOptionRequest.Option[], android.os.Bundle);
method public void onShow(android.os.Bundle, int);
method public void onTaskFinished(android.content.Intent, int);
method public void onTaskStarted(android.content.Intent, int);
method public void setContentView(android.view.View);
+ method public void setKeepAwake(boolean);
method public void setTheme(int);
method public void show();
method public void showWindow();
@@ -27924,6 +27945,7 @@ package android.service.voice {
method public void sendCommandResult(boolean, android.os.Bundle);
method public void sendCompleteVoiceResult(android.os.Bundle);
method public void sendConfirmResult(boolean, android.os.Bundle);
+ method public void sendPickOptionResult(boolean, android.app.VoiceInteractor.PickOptionRequest.Option[], android.os.Bundle);
}
public abstract class VoiceInteractionSessionService extends android.app.Service {
diff --git a/api/system-current.txt b/api/system-current.txt
index 538820723e30..89c0460e9883 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5445,8 +5445,25 @@ package android.app {
method public void onConfirmationResult(boolean, android.os.Bundle);
}
+ public static class VoiceInteractor.PickOptionRequest extends android.app.VoiceInteractor.Request {
+ ctor public VoiceInteractor.PickOptionRequest(java.lang.CharSequence, android.app.VoiceInteractor.PickOptionRequest.Option[], android.os.Bundle);
+ method public void onPickOptionResult(boolean, android.app.VoiceInteractor.PickOptionRequest.Option[], android.os.Bundle);
+ }
+
+ public static final class VoiceInteractor.PickOptionRequest.Option implements android.os.Parcelable {
+ ctor public VoiceInteractor.PickOptionRequest.Option(java.lang.CharSequence);
+ method public android.app.VoiceInteractor.PickOptionRequest.Option addSynonym(java.lang.CharSequence);
+ method public int countSynonyms();
+ method public int describeContents();
+ method public android.os.Bundle getExtras();
+ method public java.lang.CharSequence getLabel();
+ method public java.lang.CharSequence getSynonymAt(int);
+ method public void setExtras(android.os.Bundle);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.VoiceInteractor.PickOptionRequest.Option> CREATOR;
+ }
+
public static abstract class VoiceInteractor.Request {
- ctor public VoiceInteractor.Request();
method public void cancel();
method public android.app.Activity getActivity();
method public android.content.Context getContext();
@@ -18734,6 +18751,7 @@ package android.media.tv {
method public int describeContents();
method public final int getAudioChannelCount();
method public final int getAudioSampleRate();
+ method public final java.lang.String getDescription();
method public final android.os.Bundle getExtra();
method public final java.lang.String getId();
method public final java.lang.String getLanguage();
@@ -18753,6 +18771,7 @@ package android.media.tv {
method public android.media.tv.TvTrackInfo build();
method public final android.media.tv.TvTrackInfo.Builder setAudioChannelCount(int);
method public final android.media.tv.TvTrackInfo.Builder setAudioSampleRate(int);
+ method public final android.media.tv.TvTrackInfo.Builder setDescription(java.lang.String);
method public final android.media.tv.TvTrackInfo.Builder setExtra(android.os.Bundle);
method public final android.media.tv.TvTrackInfo.Builder setLanguage(java.lang.String);
method public final android.media.tv.TvTrackInfo.Builder setVideoFrameRate(float);
@@ -29779,10 +29798,12 @@ package android.service.voice {
method public boolean onKeyLongPress(int, android.view.KeyEvent);
method public boolean onKeyMultiple(int, int, android.view.KeyEvent);
method public boolean onKeyUp(int, android.view.KeyEvent);
+ method public abstract void onPickOption(android.service.voice.VoiceInteractionSession.Caller, android.service.voice.VoiceInteractionSession.Request, java.lang.CharSequence, android.app.VoiceInteractor.PickOptionRequest.Option[], android.os.Bundle);
method public void onShow(android.os.Bundle, int);
method public void onTaskFinished(android.content.Intent, int);
method public void onTaskStarted(android.content.Intent, int);
method public void setContentView(android.view.View);
+ method public void setKeepAwake(boolean);
method public void setTheme(int);
method public void show();
method public void showWindow();
@@ -29808,6 +29829,7 @@ package android.service.voice {
method public void sendCommandResult(boolean, android.os.Bundle);
method public void sendCompleteVoiceResult(android.os.Bundle);
method public void sendConfirmResult(boolean, android.os.Bundle);
+ method public void sendPickOptionResult(boolean, android.app.VoiceInteractor.PickOptionRequest.Option[], android.os.Bundle);
}
public abstract class VoiceInteractionSessionService extends android.app.Service {
diff --git a/core/java/android/annotation/TransitionRes.java b/core/java/android/annotation/TransitionRes.java
new file mode 100644
index 000000000000..06bac74984a5
--- /dev/null
+++ b/core/java/android/annotation/TransitionRes.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2015 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.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+/**
+ * Denotes that an integer parameter, field or method return value is expected
+ * to be a transition resource reference.
+ *
+ * {@hide}
+ */
+@Documented
+@Retention(SOURCE)
+@Target({METHOD, PARAMETER, FIELD})
+public @interface TransitionRes {
+}
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 997f69dc0f81..1484af8aa691 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2440,6 +2440,16 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
reply.writeNoException();
return true;
}
+
+ case SET_VOICE_KEEP_AWAKE_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ IVoiceInteractionSession session = IVoiceInteractionSession.Stub.asInterface(
+ data.readStrongBinder());
+ boolean keepAwake = data.readInt() != 0;
+ setVoiceKeepAwake(session, keepAwake);
+ reply.writeNoException();
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
@@ -5658,5 +5668,19 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
}
+ @Override
+ public void setVoiceKeepAwake(IVoiceInteractionSession session, boolean keepAwake)
+ throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeStrongBinder(session.asBinder());
+ data.writeInt(keepAwake ? 1 : 0);
+ mRemote.transact(SET_VOICE_KEEP_AWAKE_TRANSACTION, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
private IBinder mRemote;
}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 3dcbdd229288..d794aa3a37de 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -485,6 +485,9 @@ public interface IActivityManager extends IInterface {
public void setDumpHeapDebugLimit(String processName, long maxMemSize) throws RemoteException;
public void dumpHeapFinished(String path) throws RemoteException;
+ public void setVoiceKeepAwake(IVoiceInteractionSession session, boolean keepAwake)
+ throws RemoteException;
+
/*
* Private non-Binder interfaces
*/
@@ -818,4 +821,5 @@ public interface IActivityManager extends IInterface {
int GET_LOCK_TASK_MODE_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+286;
int SET_DUMP_HEAP_DEBUG_LIMIT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+287;
int DUMP_HEAP_FINISHED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+288;
+ int SET_VOICE_KEEP_AWAKE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+289;
}
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 8abe22325904..79797c947171 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -27,6 +27,7 @@ import android.content.res.ResourcesKey;
import android.hardware.display.DisplayManagerGlobal;
import android.util.ArrayMap;
import android.util.DisplayMetrics;
+import android.util.Log;
import android.util.Pair;
import android.util.Slog;
import android.view.Display;
@@ -164,7 +165,7 @@ public class ResourcesManager {
WeakReference<Resources> wr = mActiveResources.get(key);
r = wr != null ? wr.get() : null;
- //if (r != null) Slog.i(TAG, "isUpToDate " + resDir + ": " + r.getAssets().isUpToDate());
+ //if (r != null) Log.i(TAG, "isUpToDate " + resDir + ": " + r.getAssets().isUpToDate());
if (r != null && r.getAssets().isUpToDate()) {
if (DEBUG) Slog.w(TAG, "Returning cached resources " + r + " " + resDir
+ ": appScale=" + r.getCompatibilityInfo().applicationScale
@@ -174,7 +175,7 @@ public class ResourcesManager {
}
//if (r != null) {
- // Slog.w(TAG, "Throwing away out-of-date resources!!!! "
+ // Log.w(TAG, "Throwing away out-of-date resources!!!! "
// + r + " " + resDir);
//}
@@ -204,14 +205,18 @@ public class ResourcesManager {
if (libDirs != null) {
for (String libDir : libDirs) {
- if (assets.addAssetPath(libDir) == 0) {
- Slog.w(TAG, "Asset path '" + libDir +
- "' does not exist or contains no resources.");
+ if (libDir.endsWith(".apk")) {
+ // Avoid opening files we know do not have resources,
+ // like code-only .jar files.
+ if (assets.addAssetPath(libDir) == 0) {
+ Log.w(TAG, "Asset path '" + libDir +
+ "' does not exist or contains no resources.");
+ }
}
}
}
- //Slog.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
+ //Log.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
DisplayMetrics dm = getDisplayMetricsLocked(displayId);
Configuration config;
final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
diff --git a/core/java/android/app/VoiceInteractor.aidl b/core/java/android/app/VoiceInteractor.aidl
new file mode 100644
index 000000000000..40a4a0e9be1a
--- /dev/null
+++ b/core/java/android/app/VoiceInteractor.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2015, 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.app;
+
+parcelable VoiceInteractor.PickOptionRequest.Option;
diff --git a/core/java/android/app/VoiceInteractor.java b/core/java/android/app/VoiceInteractor.java
index 7b84cb4c82ff..da7bb05f4862 100644
--- a/core/java/android/app/VoiceInteractor.java
+++ b/core/java/android/app/VoiceInteractor.java
@@ -21,6 +21,8 @@ import android.os.Bundle;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.Log;
@@ -69,6 +71,7 @@ public class VoiceInteractor {
public void executeMessage(Message msg) {
SomeArgs args = (SomeArgs)msg.obj;
Request request;
+ boolean complete;
switch (msg.what) {
case MSG_CONFIRMATION_RESULT:
request = pullRequest((IVoiceInteractorRequest)args.arg1, true);
@@ -81,13 +84,28 @@ public class VoiceInteractor {
request.clear();
}
break;
+ case MSG_PICK_OPTION_RESULT:
+ complete = msg.arg1 != 0;
+ request = pullRequest((IVoiceInteractorRequest)args.arg1, complete);
+ if (DEBUG) Log.d(TAG, "onPickOptionResult: req="
+ + ((IVoiceInteractorRequest)args.arg1).asBinder() + "/" + request
+ + " finished=" + complete + " selection=" + args.arg2
+ + " result=" + args.arg3);
+ if (request != null) {
+ ((PickOptionRequest)request).onPickOptionResult(complete,
+ (PickOptionRequest.Option[]) args.arg2, (Bundle) args.arg3);
+ if (complete) {
+ request.clear();
+ }
+ }
+ break;
case MSG_COMPLETE_VOICE_RESULT:
request = pullRequest((IVoiceInteractorRequest)args.arg1, true);
if (DEBUG) Log.d(TAG, "onCompleteVoice: req="
+ ((IVoiceInteractorRequest)args.arg1).asBinder() + "/" + request
+ " result=" + args.arg1);
if (request != null) {
- ((CompleteVoiceRequest)request).onCompleteResult((Bundle) args.arg2);
+ ((CompleteVoiceRequest)request).onCompleteResult((Bundle) args.arg1);
request.clear();
}
break;
@@ -95,21 +113,22 @@ public class VoiceInteractor {
request = pullRequest((IVoiceInteractorRequest)args.arg1, true);
if (DEBUG) Log.d(TAG, "onAbortVoice: req="
+ ((IVoiceInteractorRequest)args.arg1).asBinder() + "/" + request
- + " result=" + args.arg1);
+ + " result=" + args.arg2);
if (request != null) {
((AbortVoiceRequest)request).onAbortResult((Bundle) args.arg2);
request.clear();
}
break;
case MSG_COMMAND_RESULT:
- request = pullRequest((IVoiceInteractorRequest)args.arg1, msg.arg1 != 0);
+ complete = msg.arg1 != 0;
+ request = pullRequest((IVoiceInteractorRequest)args.arg1, complete);
if (DEBUG) Log.d(TAG, "onCommandResult: req="
+ ((IVoiceInteractorRequest)args.arg1).asBinder() + "/" + request
+ " completed=" + msg.arg1 + " result=" + args.arg2);
if (request != null) {
((CommandRequest)request).onCommandResult(msg.arg1 != 0,
(Bundle) args.arg2);
- if (msg.arg1 != 0) {
+ if (complete) {
request.clear();
}
}
@@ -129,10 +148,17 @@ public class VoiceInteractor {
final IVoiceInteractorCallback.Stub mCallback = new IVoiceInteractorCallback.Stub() {
@Override
- public void deliverConfirmationResult(IVoiceInteractorRequest request, boolean confirmed,
+ public void deliverConfirmationResult(IVoiceInteractorRequest request, boolean finished,
Bundle result) {
mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageIOO(
- MSG_CONFIRMATION_RESULT, confirmed ? 1 : 0, request, result));
+ MSG_CONFIRMATION_RESULT, finished ? 1 : 0, request, result));
+ }
+
+ @Override
+ public void deliverPickOptionResult(IVoiceInteractorRequest request,
+ boolean finished, PickOptionRequest.Option[] options, Bundle result) {
+ mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageIOOO(
+ MSG_PICK_OPTION_RESULT, finished ? 1 : 0, request, options, result));
}
@Override
@@ -164,17 +190,22 @@ public class VoiceInteractor {
final ArrayMap<IBinder, Request> mActiveRequests = new ArrayMap<IBinder, Request>();
static final int MSG_CONFIRMATION_RESULT = 1;
- static final int MSG_COMPLETE_VOICE_RESULT = 2;
- static final int MSG_ABORT_VOICE_RESULT = 3;
- static final int MSG_COMMAND_RESULT = 4;
- static final int MSG_CANCEL_RESULT = 5;
+ static final int MSG_PICK_OPTION_RESULT = 2;
+ static final int MSG_COMPLETE_VOICE_RESULT = 3;
+ static final int MSG_ABORT_VOICE_RESULT = 4;
+ static final int MSG_COMMAND_RESULT = 5;
+ static final int MSG_CANCEL_RESULT = 6;
+ /**
+ * Base class for voice interaction requests that can be submitted to the interactor.
+ * Do not instantiate this directly -- instead, use the appropriate subclass.
+ */
public static abstract class Request {
IVoiceInteractorRequest mRequestInterface;
Context mContext;
Activity mActivity;
- public Request() {
+ Request() {
}
public void cancel() {
@@ -212,22 +243,25 @@ public class VoiceInteractor {
String packageName, IVoiceInteractorCallback callback) throws RemoteException;
}
+ /**
+ * Confirms an operation with the user via the trusted system
+ * VoiceInteractionService. This allows an Activity to complete an unsafe operation that
+ * would require the user to touch the screen when voice interaction mode is not enabled.
+ * The result of the confirmation will be returned through an asynchronous call to
+ * either {@link #onConfirmationResult(boolean, android.os.Bundle)} or
+ * {@link #onCancel()}.
+ *
+ * <p>In some cases this may be a simple yes / no confirmation or the confirmation could
+ * include context information about how the action will be completed
+ * (e.g. booking a cab might include details about how long until the cab arrives)
+ * so the user can give a confirmation.
+ */
public static class ConfirmationRequest extends Request {
final CharSequence mPrompt;
final Bundle mExtras;
/**
- * Confirms an operation with the user via the trusted system
- * VoiceInteractionService. This allows an Activity to complete an unsafe operation that
- * would require the user to touch the screen when voice interaction mode is not enabled.
- * The result of the confirmation will be returned through an asynchronous call to
- * either {@link #onConfirmationResult(boolean, android.os.Bundle)} or
- * {@link #onCancel()}.
- *
- * <p>In some cases this may be a simple yes / no confirmation or the confirmation could
- * include context information about how the action will be completed
- * (e.g. booking a cab might include details about how long until the cab arrives)
- * so the user can give a confirmation.
+ * Create a new confirmation request.
* @param prompt Optional confirmation text to read to the user as the action being
* confirmed.
* @param extras Additional optional information.
@@ -246,19 +280,155 @@ public class VoiceInteractor {
}
}
+ /**
+ * Select a single option from multiple potential options with the user via the trusted system
+ * VoiceInteractionService. Typically, the application would present this visually as
+ * a list view to allow selecting the option by touch.
+ * The result of the confirmation will be returned through an asynchronous call to
+ * either {@link #onPickOptionResult} or {@link #onCancel()}.
+ */
+ public static class PickOptionRequest extends Request {
+ final CharSequence mPrompt;
+ final Option[] mOptions;
+ final Bundle mExtras;
+
+ /**
+ * Represents a single option that the user may select using their voice.
+ */
+ public static final class Option implements Parcelable {
+ final CharSequence mLabel;
+ ArrayList<CharSequence> mSynonyms;
+ Bundle mExtras;
+
+ /**
+ * Creates an option that a user can select with their voice by matching the label
+ * or one of several synonyms.
+ * @param label The label that will both be matched against what the user speaks
+ * and displayed visually.
+ */
+ public Option(CharSequence label) {
+ mLabel = label;
+ }
+
+ /**
+ * Add a synonym term to the option to indicate an alternative way the content
+ * may be matched.
+ * @param synonym The synonym that will be matched against what the user speaks,
+ * but not displayed.
+ */
+ public Option addSynonym(CharSequence synonym) {
+ if (mSynonyms == null) {
+ mSynonyms = new ArrayList<>();
+ }
+ mSynonyms.add(synonym);
+ return this;
+ }
+
+ public CharSequence getLabel() {
+ return mLabel;
+ }
+
+ public int countSynonyms() {
+ return mSynonyms != null ? mSynonyms.size() : 0;
+ }
+
+ public CharSequence getSynonymAt(int index) {
+ return mSynonyms != null ? mSynonyms.get(index) : null;
+ }
+
+ /**
+ * Set optional extra information associated with this option. Note that this
+ * method takes ownership of the supplied extras Bundle.
+ */
+ public void setExtras(Bundle extras) {
+ mExtras = extras;
+ }
+
+ /**
+ * Return any optional extras information associated with this option, or null
+ * if there is none. Note that this method returns a reference to the actual
+ * extras Bundle in the option, so modifications to it will directly modify the
+ * extras in the option.
+ */
+ public Bundle getExtras() {
+ return mExtras;
+ }
+
+ Option(Parcel in) {
+ mLabel = in.readCharSequence();
+ mSynonyms = in.readCharSequenceList();
+ mExtras = in.readBundle();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeCharSequence(mLabel);
+ dest.writeCharSequenceList(mSynonyms);
+ dest.writeBundle(mExtras);
+ }
+
+ public static final Parcelable.Creator<Option> CREATOR
+ = new Parcelable.Creator<Option>() {
+ public Option createFromParcel(Parcel in) {
+ return new Option(in);
+ }
+
+ public Option[] newArray(int size) {
+ return new Option[size];
+ }
+ };
+ };
+
+ /**
+ * Create a new pick option request.
+ * @param prompt Optional question to be spoken to the user via text to speech.
+ * @param options The set of {@link Option}s the user is selecting from.
+ * @param extras Additional optional information.
+ */
+ public PickOptionRequest(CharSequence prompt, Option[] options, Bundle extras) {
+ mPrompt = prompt;
+ mOptions = options;
+ mExtras = extras;
+ }
+
+ /**
+ * Called when a single option is confirmed or narrowed to one of several options.
+ * @param finished True if the voice interaction has finished making a selection, in
+ * which case {@code selections} contains the final result. If false, this request is
+ * still active and you will continue to get calls on it.
+ * @param selections Either a single {@link Option} or one of several {@link Option}s the
+ * user has narrowed the choices down to.
+ * @param result Additional optional information.
+ */
+ public void onPickOptionResult(boolean finished, Option[] selections, Bundle result) {
+ }
+
+ IVoiceInteractorRequest submit(IVoiceInteractor interactor, String packageName,
+ IVoiceInteractorCallback callback) throws RemoteException {
+ return interactor.startPickOption(packageName, callback, mPrompt, mOptions, mExtras);
+ }
+ }
+
+ /**
+ * Reports that the current interaction was successfully completed with voice, so the
+ * application can report the final status to the user. When the response comes back, the
+ * voice system has handled the request and is ready to switch; at that point the
+ * application can start a new non-voice activity or finish. Be sure when starting the new
+ * activity to use {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK
+ * Intent.FLAG_ACTIVITY_NEW_TASK} to keep the new activity out of the current voice
+ * interaction task.
+ */
public static class CompleteVoiceRequest extends Request {
final CharSequence mMessage;
final Bundle mExtras;
/**
- * Reports that the current interaction was successfully completed with voice, so the
- * application can report the final status to the user. When the response comes back, the
- * voice system has handled the request and is ready to switch; at that point the
- * application can start a new non-voice activity or finish. Be sure when starting the new
- * activity to use {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK
- * Intent.FLAG_ACTIVITY_NEW_TASK} to keep the new activity out of the current voice
- * interaction task.
- *
+ * Create a new completed voice interaction request.
* @param message Optional message to tell user about the completion status of the task.
* @param extras Additional optional information.
*/
@@ -276,21 +446,23 @@ public class VoiceInteractor {
}
}
+ /**
+ * Reports that the current interaction can not be complete with voice, so the
+ * application will need to switch to a traditional input UI. Applications should
+ * only use this when they need to completely bail out of the voice interaction
+ * and switch to a traditional UI. When the response comes back, the voice
+ * system has handled the request and is ready to switch; at that point the application
+ * can start a new non-voice activity. Be sure when starting the new activity
+ * to use {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK
+ * Intent.FLAG_ACTIVITY_NEW_TASK} to keep the new activity out of the current voice
+ * interaction task.
+ */
public static class AbortVoiceRequest extends Request {
final CharSequence mMessage;
final Bundle mExtras;
/**
- * Reports that the current interaction can not be complete with voice, so the
- * application will need to switch to a traditional input UI. Applications should
- * only use this when they need to completely bail out of the voice interaction
- * and switch to a traditional UI. When the response comes back, the voice
- * system has handled the request and is ready to switch; at that point the application
- * can start a new non-voice activity. Be sure when starting the new activity
- * to use {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK
- * Intent.FLAG_ACTIVITY_NEW_TASK} to keep the new activity out of the current voice
- * interaction task.
- *
+ * Create a new voice abort request.
* @param message Optional message to tell user about not being able to complete
* the interaction with voice.
* @param extras Additional optional information.
@@ -309,25 +481,27 @@ public class VoiceInteractor {
}
}
+ /**
+ * Execute an extended command using the trusted system VoiceInteractionService.
+ * This allows an Activity to request additional information from the user needed to
+ * complete an action (e.g. booking a table might have several possible times that the
+ * user could select from or an app might need the user to agree to a terms of service).
+ * The result of the confirmation will be returned through an asynchronous call to
+ * either {@link #onCommandResult(boolean, android.os.Bundle)} or
+ * {@link #onCancel()}.
+ *
+ * <p>The command is a string that describes the generic operation to be performed.
+ * The command will determine how the properties in extras are interpreted and the set of
+ * available commands is expected to grow over time. An example might be
+ * "com.google.voice.commands.REQUEST_NUMBER_BAGS" to request the number of bags as part of
+ * airline check-in. (This is not an actual working example.)
+ */
public static class CommandRequest extends Request {
final String mCommand;
final Bundle mArgs;
/**
- * Execute a command using the trusted system VoiceInteractionService.
- * This allows an Activity to request additional information from the user needed to
- * complete an action (e.g. booking a table might have several possible times that the
- * user could select from or an app might need the user to agree to a terms of service).
- * The result of the confirmation will be returned through an asynchronous call to
- * either {@link #onCommandResult(boolean, android.os.Bundle)} or
- * {@link #onCancel()}.
- *
- * <p>The command is a string that describes the generic operation to be performed.
- * The command will determine how the properties in extras are interpreted and the set of
- * available commands is expected to grow over time. An example might be
- * "com.google.voice.commands.REQUEST_NUMBER_BAGS" to request the number of bags as part of
- * airline check-in. (This is not an actual working example.)
- *
+ * Create a new generic command request.
* @param command The desired command to perform.
* @param args Additional arguments to control execution of the command.
*/
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 2ed8c44ddc2f..f68547599719 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2790,6 +2790,31 @@ public class Intent implements Parcelable, Cloneable {
/** {@hide} */
public static final String ACTION_MASTER_CLEAR = "android.intent.action.MASTER_CLEAR";
+ /**
+ * Broadcast action: report that a settings element is being restored from backup. The intent
+ * contains three extras: EXTRA_SETTING_NAME is a string naming the restored setting,
+ * EXTRA_SETTING_NEW_VALUE is the value being restored, and EXTRA_SETTING_PREVIOUS_VALUE
+ * is the value of that settings entry prior to the restore operation. All of these values are
+ * represented as strings.
+ *
+ * <p>This broadcast is sent only for settings provider entries known to require special handling
+ * around restore time. These entries are found in the BROADCAST_ON_RESTORE table within
+ * the provider's backup agent implementation.
+ *
+ * @see #EXTRA_SETTING_NAME
+ * @see #EXTRA_SETTING_PREVIOUS_VALUE
+ * @see #EXTRA_SETTING_NEW_VALUE
+ * {@hide}
+ */
+ public static final String ACTION_SETTING_RESTORED = "android.os.action.SETTING_RESTORED";
+
+ /** {@hide} */
+ public static final String EXTRA_SETTING_NAME = "setting_name";
+ /** {@hide} */
+ public static final String EXTRA_SETTING_PREVIOUS_VALUE = "previous_value";
+ /** {@hide} */
+ public static final String EXTRA_SETTING_NEW_VALUE = "new_value";
+
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Standard intent categories (see addCategory()).
diff --git a/core/java/android/hardware/camera2/DngCreator.java b/core/java/android/hardware/camera2/DngCreator.java
index 33d539c25e73..f16d650c5e7e 100644
--- a/core/java/android/hardware/camera2/DngCreator.java
+++ b/core/java/android/hardware/camera2/DngCreator.java
@@ -453,7 +453,7 @@ public final class DngCreator implements AutoCloseable {
height + ") passed to write");
}
long capacity = pixels.capacity();
- long totalSize = rowStride * height + offset;
+ long totalSize = ((long) rowStride) * height + offset;
if (capacity < totalSize) {
throw new IllegalArgumentException("Image size " + capacity +
" is too small (must be larger than " + totalSize + ")");
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 3d5215b6f036..9d8a1bafb93e 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -1059,6 +1059,21 @@ public final class Parcel {
}
}
+ /**
+ * @hide
+ */
+ public final void writeCharSequenceList(ArrayList<CharSequence> val) {
+ if (val != null) {
+ int N = val.size();
+ writeInt(N);
+ for (int i=0; i<N; i++) {
+ writeCharSequence(val.get(i));
+ }
+ } else {
+ writeInt(-1);
+ }
+ }
+
public final IBinder[] createBinderArray() {
int N = readInt();
if (N >= 0) {
@@ -1828,6 +1843,25 @@ public final class Parcel {
}
/**
+ * Read and return an ArrayList&lt;CharSequence&gt; object from the parcel.
+ * {@hide}
+ */
+ public final ArrayList<CharSequence> readCharSequenceList() {
+ ArrayList<CharSequence> array = null;
+
+ int length = readInt();
+ if (length >= 0) {
+ array = new ArrayList<CharSequence>(length);
+
+ for (int i = 0 ; i < length ; i++) {
+ array.add(readCharSequence());
+ }
+ }
+
+ return array;
+ }
+
+ /**
* Read and return a new ArrayList object from the parcel at the current
* dataPosition(). Returns null if the previously written list object was
* null. The given class loader will be used to load any enclosed
diff --git a/core/java/android/preference/PreferenceFragment.java b/core/java/android/preference/PreferenceFragment.java
index 29f9ca13f61e..66642debc032 100644
--- a/core/java/android/preference/PreferenceFragment.java
+++ b/core/java/android/preference/PreferenceFragment.java
@@ -17,6 +17,7 @@
package android.preference;
import android.annotation.Nullable;
+import android.annotation.XmlRes;
import android.app.Activity;
import android.app.Fragment;
import android.content.Intent;
@@ -294,7 +295,7 @@ public abstract class PreferenceFragment extends Fragment implements
*
* @param preferencesResId The XML resource ID to inflate.
*/
- public void addPreferencesFromResource(int preferencesResId) {
+ public void addPreferencesFromResource(@XmlRes int preferencesResId) {
requirePreferenceManager();
setPreferenceScreen(mPreferenceManager.inflateFromResource(getActivity(),
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 0cc3255a0ec3..381327751636 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5374,6 +5374,7 @@ public final class Settings {
ACCESSIBILITY_SCRIPT_INJECTION,
BACKUP_AUTO_RESTORE,
ENABLED_ACCESSIBILITY_SERVICES,
+ ENABLED_NOTIFICATION_LISTENERS,
TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
TOUCH_EXPLORATION_ENABLED,
ACCESSIBILITY_ENABLED,
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index 4cf0e4ca8765..11eaa0678870 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -18,6 +18,7 @@ package android.service.voice;
import android.app.Dialog;
import android.app.Instrumentation;
+import android.app.VoiceInteractor;
import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray;
@@ -105,6 +106,17 @@ public abstract class VoiceInteractionSession implements KeyEvent.Callback {
}
@Override
+ public IVoiceInteractorRequest startPickOption(String callingPackage,
+ IVoiceInteractorCallback callback, CharSequence prompt,
+ VoiceInteractor.PickOptionRequest.Option[] options, Bundle extras) {
+ Request request = newRequest(callback);
+ mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageOOOOO(MSG_START_PICK_OPTION,
+ new Caller(callingPackage, Binder.getCallingUid()), request,
+ prompt, options, extras));
+ return request.mInterface;
+ }
+
+ @Override
public IVoiceInteractorRequest startCompleteVoice(String callingPackage,
IVoiceInteractorCallback callback, CharSequence message, Bundle extras) {
Request request = newRequest(callback);
@@ -232,6 +244,20 @@ public abstract class VoiceInteractionSession implements KeyEvent.Callback {
}
}
+ public void sendPickOptionResult(boolean finished,
+ VoiceInteractor.PickOptionRequest.Option[] selections, Bundle result) {
+ try {
+ if (DEBUG) Log.d(TAG, "sendPickOptionResult: req=" + mInterface
+ + " finished=" + finished + " selections=" + selections
+ + " result=" + result);
+ if (finished) {
+ finishRequest();
+ }
+ mCallback.deliverPickOptionResult(mInterface, finished, selections, result);
+ } catch (RemoteException e) {
+ }
+ }
+
public void sendCompleteVoiceResult(Bundle result) {
try {
if (DEBUG) Log.d(TAG, "sendCompleteVoiceResult: req=" + mInterface
@@ -252,12 +278,14 @@ public abstract class VoiceInteractionSession implements KeyEvent.Callback {
}
}
- public void sendCommandResult(boolean complete, Bundle result) {
+ public void sendCommandResult(boolean finished, Bundle result) {
try {
if (DEBUG) Log.d(TAG, "sendCommandResult: req=" + mInterface
+ " result=" + result);
- finishRequest();
- mCallback.deliverCommandResult(mInterface, complete, result);
+ if (finished) {
+ finishRequest();
+ }
+ mCallback.deliverCommandResult(mInterface, finished, result);
} catch (RemoteException e) {
}
}
@@ -283,11 +311,12 @@ public abstract class VoiceInteractionSession implements KeyEvent.Callback {
}
static final int MSG_START_CONFIRMATION = 1;
- static final int MSG_START_COMPLETE_VOICE = 2;
- static final int MSG_START_ABORT_VOICE = 3;
- static final int MSG_START_COMMAND = 4;
- static final int MSG_SUPPORTS_COMMANDS = 5;
- static final int MSG_CANCEL = 6;
+ static final int MSG_START_PICK_OPTION = 2;
+ static final int MSG_START_COMPLETE_VOICE = 3;
+ static final int MSG_START_ABORT_VOICE = 4;
+ static final int MSG_START_COMMAND = 5;
+ static final int MSG_SUPPORTS_COMMANDS = 6;
+ static final int MSG_CANCEL = 7;
static final int MSG_TASK_STARTED = 100;
static final int MSG_TASK_FINISHED = 101;
@@ -309,6 +338,15 @@ public abstract class VoiceInteractionSession implements KeyEvent.Callback {
onConfirm((Caller)args.arg1, (Request)args.arg2, (CharSequence)args.arg3,
(Bundle)args.arg4);
break;
+ case MSG_START_PICK_OPTION:
+ args = (SomeArgs)msg.obj;
+ if (DEBUG) Log.d(TAG, "onPickOption: req=" + ((Request) args.arg2).mInterface
+ + " prompt=" + args.arg3 + " options=" + args.arg4
+ + " extras=" + args.arg5);
+ onPickOption((Caller)args.arg1, (Request)args.arg2, (CharSequence)args.arg3,
+ (VoiceInteractor.PickOptionRequest.Option[])args.arg4,
+ (Bundle)args.arg5);
+ break;
case MSG_START_COMPLETE_VOICE:
args = (SomeArgs)msg.obj;
if (DEBUG) Log.d(TAG, "onCompleteVoice: req=" + ((Request) args.arg2).mInterface
@@ -614,6 +652,26 @@ public abstract class VoiceInteractionSession implements KeyEvent.Callback {
}
/**
+ * Set whether this session will keep the device awake while it is running a voice
+ * activity. By default, the system holds a wake lock for it while in this state,
+ * so that it can work even if the screen is off. Setting this to false removes that
+ * wake lock, allowing the CPU to go to sleep. This is typically used if the
+ * session decides it has been waiting too long for a response from the user and
+ * doesn't want to let this continue to drain the battery.
+ *
+ * <p>Passing false here will release the wake lock, and you can call later with
+ * true to re-acquire it. It will also be automatically re-acquired for you each
+ * time you start a new voice activity task -- that is when you call
+ * {@link #startVoiceActivity}.</p>
+ */
+ public void setKeepAwake(boolean keepAwake) {
+ try {
+ mSystemService.setKeepAwake(mToken, keepAwake);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
* Convenience for inflating views.
*/
public LayoutInflater getLayoutInflater() {
@@ -814,6 +872,22 @@ public abstract class VoiceInteractionSession implements KeyEvent.Callback {
Bundle extras);
/**
+ * Request for the user to pick one of N options, corresponding to a
+ * {@link android.app.VoiceInteractor.PickOptionRequest VoiceInteractor.PickOptionRequest}.
+ *
+ * @param caller Who is making the request.
+ * @param request The active request.
+ * @param prompt The prompt informing the user of what they are picking, as per
+ * {@link android.app.VoiceInteractor.PickOptionRequest VoiceInteractor.PickOptionRequest}.
+ * @param options The set of options the user is picking from, as per
+ * {@link android.app.VoiceInteractor.PickOptionRequest VoiceInteractor.PickOptionRequest}.
+ * @param extras Any additional information, as per
+ * {@link android.app.VoiceInteractor.PickOptionRequest VoiceInteractor.PickOptionRequest}.
+ */
+ public abstract void onPickOption(Caller caller, Request request, CharSequence prompt,
+ VoiceInteractor.PickOptionRequest.Option[] options, Bundle extras);
+
+ /**
* Request to complete the voice interaction session because the voice activity successfully
* completed its interaction using voice. Corresponds to
* {@link android.app.VoiceInteractor.CompleteVoiceRequest
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 668e028b7729..13fb657812c0 100644
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -918,7 +918,7 @@ public class TextToSpeech {
*
* @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
*/
- public int addSpeech(CharSequence text, String packagename, int resourceId) {
+ public int addSpeech(CharSequence text, String packagename, @RawRes int resourceId) {
synchronized (mStartLock) {
mUtterances.put(text, makeResourceUri(packagename, resourceId));
return SUCCESS;
diff --git a/core/java/android/transition/TransitionInflater.java b/core/java/android/transition/TransitionInflater.java
index 9009d6ab08d5..a7d9503a7718 100644
--- a/core/java/android/transition/TransitionInflater.java
+++ b/core/java/android/transition/TransitionInflater.java
@@ -16,6 +16,7 @@
package android.transition;
+import android.annotation.TransitionRes;
import com.android.internal.R;
import org.xmlpull.v1.XmlPullParser;
@@ -71,7 +72,8 @@ public class TransitionInflater {
* @throws android.content.res.Resources.NotFoundException when the
* transition cannot be loaded
*/
- public Transition inflateTransition(int resource) {
+ public Transition inflateTransition(@TransitionRes int resource) {
+ //noinspection ResourceType
XmlResourceParser parser = mContext.getResources().getXml(resource);
try {
return createTransitionFromXml(parser, Xml.asAttributeSet(parser), null);
@@ -98,7 +100,9 @@ public class TransitionInflater {
* @throws android.content.res.Resources.NotFoundException when the
* transition manager cannot be loaded
*/
- public TransitionManager inflateTransitionManager(int resource, ViewGroup sceneRoot) {
+ public TransitionManager inflateTransitionManager(@TransitionRes int resource,
+ ViewGroup sceneRoot) {
+ //noinspection ResourceType
XmlResourceParser parser = mContext.getResources().getXml(resource);
try {
return createTransitionManagerFromXml(parser, Xml.asAttributeSet(parser), sceneRoot);
diff --git a/core/java/android/view/ContextThemeWrapper.java b/core/java/android/view/ContextThemeWrapper.java
index d9f60541f2d2..9047b1dd73a2 100644
--- a/core/java/android/view/ContextThemeWrapper.java
+++ b/core/java/android/view/ContextThemeWrapper.java
@@ -16,6 +16,7 @@
package android.view;
+import android.annotation.StyleRes;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.res.Configuration;
@@ -36,7 +37,7 @@ public class ContextThemeWrapper extends ContextWrapper {
super(null);
}
- public ContextThemeWrapper(Context base, int themeResId) {
+ public ContextThemeWrapper(Context base, @StyleRes int themeResId) {
super(base);
mThemeResource = themeResId;
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 3927096a856b..d345bed0ec28 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -24,6 +24,7 @@ import android.annotation.DrawableRes;
import android.annotation.FloatRange;
import android.annotation.IdRes;
import android.annotation.IntDef;
+import android.annotation.LayoutRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Size;
@@ -18646,7 +18647,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* layout_* parameters.
* @see LayoutInflater
*/
- public static View inflate(Context context, int resource, ViewGroup root) {
+ public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
LayoutInflater factory = LayoutInflater.from(context);
return factory.inflate(resource, root);
}
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index f36fd5affbb7..9a929323f864 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -22,6 +22,7 @@ import android.annotation.IdRes;
import android.annotation.LayoutRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.StyleRes;
import android.annotation.SystemApi;
import android.content.Context;
import android.content.res.Configuration;
@@ -753,7 +754,7 @@ public abstract class Window {
* 0 here will override the animations the window would
* normally retrieve from its theme.
*/
- public void setWindowAnimations(int resId) {
+ public void setWindowAnimations(@StyleRes int resId) {
final WindowManager.LayoutParams attrs = getAttributes();
attrs.windowAnimations = resId;
dispatchWindowAttributesChanged(attrs);
diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java
index a5524d86b203..be439523b341 100644
--- a/core/java/android/view/animation/Animation.java
+++ b/core/java/android/view/animation/Animation.java
@@ -17,6 +17,7 @@
package android.view.animation;
import android.annotation.ColorInt;
+import android.annotation.InterpolatorRes;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.RectF;
@@ -388,7 +389,7 @@ public abstract class Animation implements Cloneable {
* @param resID The resource identifier of the interpolator to load
* @attr ref android.R.styleable#Animation_interpolator
*/
- public void setInterpolator(Context context, int resID) {
+ public void setInterpolator(Context context, @InterpolatorRes int resID) {
setInterpolator(AnimationUtils.loadInterpolator(context, resID));
}
diff --git a/core/java/android/view/animation/LayoutAnimationController.java b/core/java/android/view/animation/LayoutAnimationController.java
index 882e738eaa11..df2f18c21735 100644
--- a/core/java/android/view/animation/LayoutAnimationController.java
+++ b/core/java/android/view/animation/LayoutAnimationController.java
@@ -16,6 +16,8 @@
package android.view.animation;
+import android.annotation.AnimRes;
+import android.annotation.InterpolatorRes;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
@@ -180,7 +182,7 @@ public class LayoutAnimationController {
*
* @attr ref android.R.styleable#LayoutAnimation_animation
*/
- public void setAnimation(Context context, int resourceID) {
+ public void setAnimation(Context context, @AnimRes int resourceID) {
setAnimation(AnimationUtils.loadAnimation(context, resourceID));
}
@@ -225,7 +227,7 @@ public class LayoutAnimationController {
*
* @attr ref android.R.styleable#LayoutAnimation_interpolator
*/
- public void setInterpolator(Context context, int resourceID) {
+ public void setInterpolator(Context context, @InterpolatorRes int resourceID) {
setInterpolator(AnimationUtils.loadInterpolator(context, resourceID));
}
diff --git a/core/java/android/widget/ActionMenuView.java b/core/java/android/widget/ActionMenuView.java
index 9d3a5dc15756..d6f227615909 100644
--- a/core/java/android/widget/ActionMenuView.java
+++ b/core/java/android/widget/ActionMenuView.java
@@ -15,6 +15,7 @@
*/
package android.widget;
+import android.annotation.StyleRes;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
@@ -86,7 +87,7 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo
* @param resId theme used to inflate popup menus
* @see #getPopupTheme()
*/
- public void setPopupTheme(int resId) {
+ public void setPopupTheme(@StyleRes int resId) {
if (mPopupTheme != resId) {
mPopupTheme = resId;
if (resId == 0) {
diff --git a/core/java/android/widget/ArrayAdapter.java b/core/java/android/widget/ArrayAdapter.java
index 89e508fdb97b..ae94a10ff036 100644
--- a/core/java/android/widget/ArrayAdapter.java
+++ b/core/java/android/widget/ArrayAdapter.java
@@ -19,6 +19,7 @@ package android.widget;
import android.annotation.ArrayRes;
import android.annotation.IdRes;
import android.annotation.LayoutRes;
+import android.annotation.NonNull;
import android.content.Context;
import android.content.res.Resources;
import android.util.Log;
@@ -133,7 +134,7 @@ public class ArrayAdapter<T> extends BaseAdapter implements Filterable,
* instantiating views.
* @param objects The objects to represent in the ListView.
*/
- public ArrayAdapter(Context context, @LayoutRes int resource, T[] objects) {
+ public ArrayAdapter(Context context, @LayoutRes int resource, @NonNull T[] objects) {
this(context, resource, 0, Arrays.asList(objects));
}
@@ -146,7 +147,8 @@ public class ArrayAdapter<T> extends BaseAdapter implements Filterable,
* @param textViewResourceId The id of the TextView within the layout resource to be populated
* @param objects The objects to represent in the ListView.
*/
- public ArrayAdapter(Context context, @LayoutRes int resource, @IdRes int textViewResourceId, T[] objects) {
+ public ArrayAdapter(Context context, @LayoutRes int resource, @IdRes int textViewResourceId,
+ @NonNull T[] objects) {
this(context, resource, textViewResourceId, Arrays.asList(objects));
}
@@ -158,7 +160,7 @@ public class ArrayAdapter<T> extends BaseAdapter implements Filterable,
* instantiating views.
* @param objects The objects to represent in the ListView.
*/
- public ArrayAdapter(Context context, @LayoutRes int resource, List<T> objects) {
+ public ArrayAdapter(Context context, @LayoutRes int resource, @NonNull List<T> objects) {
this(context, resource, 0, objects);
}
@@ -171,7 +173,8 @@ public class ArrayAdapter<T> extends BaseAdapter implements Filterable,
* @param textViewResourceId The id of the TextView within the layout resource to be populated
* @param objects The objects to represent in the ListView.
*/
- public ArrayAdapter(Context context, int resource, int textViewResourceId, List<T> objects) {
+ public ArrayAdapter(Context context, @LayoutRes int resource, @IdRes int textViewResourceId,
+ @NonNull List<T> objects) {
mContext = context;
mInflater = LayoutInflater.from(context);
mResource = mDropDownResource = resource;
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index fe143dec8900..133e10250519 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -22,6 +22,7 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
+import android.annotation.StyleRes;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
@@ -326,7 +327,7 @@ class FastScroller {
refreshDrawablePressedState();
}
- public void setStyle(int resId) {
+ public void setStyle(@StyleRes int resId) {
final Context context = mList.getContext();
final TypedArray ta = context.obtainStyledAttributes(null,
com.android.internal.R.styleable.FastScroll, android.R.attr.fastScrollStyle, resId);
diff --git a/core/java/android/widget/SimpleAdapter.java b/core/java/android/widget/SimpleAdapter.java
index a65671283816..2008ba8f0d88 100644
--- a/core/java/android/widget/SimpleAdapter.java
+++ b/core/java/android/widget/SimpleAdapter.java
@@ -16,6 +16,8 @@
package android.widget;
+import android.annotation.IdRes;
+import android.annotation.LayoutRes;
import android.content.Context;
import android.content.res.Resources;
import android.view.ContextThemeWrapper;
@@ -82,7 +84,7 @@ public class SimpleAdapter extends BaseAdapter implements Filterable, Spinner.Th
* in the from parameter.
*/
public SimpleAdapter(Context context, List<? extends Map<String, ?>> data,
- int resource, String[] from, int[] to) {
+ @LayoutRes int resource, String[] from, @IdRes int[] to) {
mData = data;
mResource = mDropDownResource = resource;
mFrom = from;
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index d2430bc6b645..087406a35ca0 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -17,8 +17,12 @@
package android.widget;
import android.annotation.ColorInt;
+import android.annotation.DrawableRes;
+import android.annotation.MenuRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.StringRes;
+import android.annotation.StyleRes;
import android.app.ActionBar;
import android.content.Context;
import android.content.res.ColorStateList;
@@ -296,7 +300,7 @@ public class Toolbar extends ViewGroup {
* @param resId theme used to inflate popup menus
* @see #getPopupTheme()
*/
- public void setPopupTheme(int resId) {
+ public void setPopupTheme(@StyleRes int resId) {
if (mPopupTheme != resId) {
mPopupTheme = resId;
if (resId == 0) {
@@ -331,7 +335,7 @@ public class Toolbar extends ViewGroup {
*
* @param resId ID of a drawable resource
*/
- public void setLogo(int resId) {
+ public void setLogo(@DrawableRes int resId) {
setLogo(getContext().getDrawable(resId));
}
@@ -481,7 +485,7 @@ public class Toolbar extends ViewGroup {
*
* @param resId String resource id
*/
- public void setLogoDescription(int resId) {
+ public void setLogoDescription(@StringRes int resId) {
setLogoDescription(getContext().getText(resId));
}
@@ -566,7 +570,7 @@ public class Toolbar extends ViewGroup {
*
* @param resId Resource ID of a string to set as the title
*/
- public void setTitle(int resId) {
+ public void setTitle(@StringRes int resId) {
setTitle(getContext().getText(resId));
}
@@ -621,7 +625,7 @@ public class Toolbar extends ViewGroup {
*
* @param resId String resource ID
*/
- public void setSubtitle(int resId) {
+ public void setSubtitle(@StringRes int resId) {
setSubtitle(getContext().getText(resId));
}
@@ -663,7 +667,7 @@ public class Toolbar extends ViewGroup {
* Sets the text color, size, style, hint color, and highlight color
* from the specified TextAppearance resource.
*/
- public void setTitleTextAppearance(Context context, int resId) {
+ public void setTitleTextAppearance(Context context, @StyleRes int resId) {
mTitleTextAppearance = resId;
if (mTitleTextView != null) {
mTitleTextView.setTextAppearance(context, resId);
@@ -674,7 +678,7 @@ public class Toolbar extends ViewGroup {
* Sets the text color, size, style, hint color, and highlight color
* from the specified TextAppearance resource.
*/
- public void setSubtitleTextAppearance(Context context, int resId) {
+ public void setSubtitleTextAppearance(Context context, @StyleRes int resId) {
mSubtitleTextAppearance = resId;
if (mSubtitleTextView != null) {
mSubtitleTextView.setTextAppearance(context, resId);
@@ -729,7 +733,7 @@ public class Toolbar extends ViewGroup {
*
* @attr ref android.R.styleable#Toolbar_navigationContentDescription
*/
- public void setNavigationContentDescription(int resId) {
+ public void setNavigationContentDescription(@StringRes int resId) {
setNavigationContentDescription(resId != 0 ? getContext().getText(resId) : null);
}
@@ -766,7 +770,7 @@ public class Toolbar extends ViewGroup {
*
* @attr ref android.R.styleable#Toolbar_navigationIcon
*/
- public void setNavigationIcon(int resId) {
+ public void setNavigationIcon(@DrawableRes int resId) {
setNavigationIcon(getContext().getDrawable(resId));
}
@@ -972,7 +976,7 @@ public class Toolbar extends ViewGroup {
*
* @param resId ID of a menu resource to inflate
*/
- public void inflateMenu(int resId) {
+ public void inflateMenu(@MenuRes int resId) {
getMenuInflater().inflate(resId, getMenu());
}
diff --git a/core/java/android/widget/ViewAnimator.java b/core/java/android/widget/ViewAnimator.java
index f30fdd802b31..1580f515eee1 100644
--- a/core/java/android/widget/ViewAnimator.java
+++ b/core/java/android/widget/ViewAnimator.java
@@ -17,6 +17,7 @@
package android.widget;
+import android.annotation.AnimRes;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
@@ -309,7 +310,7 @@ public class ViewAnimator extends FrameLayout {
* @see #getInAnimation()
* @see #setInAnimation(android.view.animation.Animation)
*/
- public void setInAnimation(Context context, int resourceID) {
+ public void setInAnimation(Context context, @AnimRes int resourceID) {
setInAnimation(AnimationUtils.loadAnimation(context, resourceID));
}
@@ -322,7 +323,7 @@ public class ViewAnimator extends FrameLayout {
* @see #getOutAnimation()
* @see #setOutAnimation(android.view.animation.Animation)
*/
- public void setOutAnimation(Context context, int resourceID) {
+ public void setOutAnimation(Context context, @AnimRes int resourceID) {
setOutAnimation(AnimationUtils.loadAnimation(context, resourceID));
}
diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
index 8f549a6b5fc0..6450d5255b13 100644
--- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
+++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
@@ -32,6 +32,7 @@ interface IVoiceInteractionManagerService {
boolean showSessionFromSession(IBinder token, in Bundle sessionArgs, int flags);
boolean hideSessionFromSession(IBinder token);
int startVoiceActivity(IBinder token, in Intent intent, String resolvedType);
+ void setKeepAwake(IBinder token, boolean keepAwake);
void finish(IBinder token);
/**
diff --git a/core/java/com/android/internal/app/IVoiceInteractor.aidl b/core/java/com/android/internal/app/IVoiceInteractor.aidl
index 3e0b02167cca..84e9cf027096 100644
--- a/core/java/com/android/internal/app/IVoiceInteractor.aidl
+++ b/core/java/com/android/internal/app/IVoiceInteractor.aidl
@@ -16,6 +16,7 @@
package com.android.internal.app;
+import android.app.VoiceInteractor;
import android.os.Bundle;
import com.android.internal.app.IVoiceInteractorCallback;
@@ -27,6 +28,9 @@ import com.android.internal.app.IVoiceInteractorRequest;
interface IVoiceInteractor {
IVoiceInteractorRequest startConfirmation(String callingPackage,
IVoiceInteractorCallback callback, CharSequence prompt, in Bundle extras);
+ IVoiceInteractorRequest startPickOption(String callingPackage,
+ IVoiceInteractorCallback callback, CharSequence prompt,
+ in VoiceInteractor.PickOptionRequest.Option[] options, in Bundle extras);
IVoiceInteractorRequest startCompleteVoice(String callingPackage,
IVoiceInteractorCallback callback, CharSequence message, in Bundle extras);
IVoiceInteractorRequest startAbortVoice(String callingPackage,
diff --git a/core/java/com/android/internal/app/IVoiceInteractorCallback.aidl b/core/java/com/android/internal/app/IVoiceInteractorCallback.aidl
index dcd57593c2ca..1331e744cdf0 100644
--- a/core/java/com/android/internal/app/IVoiceInteractorCallback.aidl
+++ b/core/java/com/android/internal/app/IVoiceInteractorCallback.aidl
@@ -16,6 +16,7 @@
package com.android.internal.app;
+import android.app.VoiceInteractor;
import android.os.Bundle;
import com.android.internal.app.IVoiceInteractorRequest;
@@ -26,8 +27,10 @@ import com.android.internal.app.IVoiceInteractorRequest;
oneway interface IVoiceInteractorCallback {
void deliverConfirmationResult(IVoiceInteractorRequest request, boolean confirmed,
in Bundle result);
+ void deliverPickOptionResult(IVoiceInteractorRequest request, boolean finished,
+ in VoiceInteractor.PickOptionRequest.Option[] selections, in Bundle result);
void deliverCompleteVoiceResult(IVoiceInteractorRequest request, in Bundle result);
void deliverAbortVoiceResult(IVoiceInteractorRequest request, in Bundle result);
- void deliverCommandResult(IVoiceInteractorRequest request, boolean complete, in Bundle result);
+ void deliverCommandResult(IVoiceInteractorRequest request, boolean finished, in Bundle result);
void deliverCancel(IVoiceInteractorRequest request);
}
diff --git a/core/java/com/android/internal/os/HandlerCaller.java b/core/java/com/android/internal/os/HandlerCaller.java
index 99286cba3d87..113768ecd4eb 100644
--- a/core/java/com/android/internal/os/HandlerCaller.java
+++ b/core/java/com/android/internal/os/HandlerCaller.java
@@ -164,6 +164,15 @@ public class HandlerCaller {
return mH.obtainMessage(what, arg1, 0, args);
}
+ public Message obtainMessageIIOOO(int what, int arg1, int arg2, Object arg3, Object arg4,
+ Object arg5) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = arg3;
+ args.arg2 = arg4;
+ args.arg3 = arg5;
+ return mH.obtainMessage(what, arg1, arg2, args);
+ }
+
public Message obtainMessageOO(int what, Object arg1, Object arg2) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = arg1;
diff --git a/core/jni/android_database_SQLiteGlobal.cpp b/core/jni/android_database_SQLiteGlobal.cpp
index d0c592e1461c..0a1c9f75edec 100644
--- a/core/jni/android_database_SQLiteGlobal.cpp
+++ b/core/jni/android_database_SQLiteGlobal.cpp
@@ -35,14 +35,18 @@ static const int SOFT_HEAP_LIMIT = 8 * 1024 * 1024;
// Called each time a message is logged.
-static void sqliteLogCallback(void* data, int iErrCode, const char* zMsg) {
+static void sqliteLogCallback(void* data, int err, const char* msg) {
bool verboseLog = !!data;
- if (iErrCode == 0 || iErrCode == SQLITE_CONSTRAINT || iErrCode == SQLITE_SCHEMA) {
+ int errType = err & 255;
+ if (errType == 0 || errType == SQLITE_CONSTRAINT || errType == SQLITE_SCHEMA
+ || errType == SQLITE_NOTICE || err == SQLITE_WARNING_AUTOINDEX) {
if (verboseLog) {
- ALOG(LOG_VERBOSE, SQLITE_LOG_TAG, "(%d) %s\n", iErrCode, zMsg);
+ ALOG(LOG_VERBOSE, SQLITE_LOG_TAG, "(%d) %s\n", err, msg);
}
+ } else if (errType == SQLITE_WARNING) {
+ ALOG(LOG_WARN, SQLITE_LOG_TAG, "(%d) %s\n", err, msg);
} else {
- ALOG(LOG_ERROR, SQLITE_LOG_TAG, "(%d) %s\n", iErrCode, zMsg);
+ ALOG(LOG_ERROR, SQLITE_LOG_TAG, "(%d) %s\n", err, msg);
}
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index ed4776bab525..4d6b5f68aa77 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -90,6 +90,8 @@
<protected-broadcast android:name="android.appwidget.action.APPWIDGET_HOST_RESTORED" />
<protected-broadcast android:name="android.appwidget.action.APPWIDGET_RESTORED" />
+ <protected-broadcast android:name="android.os.action.SETTING_RESTORED" />
+
<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/graphics/java/android/graphics/PorterDuffColorFilter.java b/graphics/java/android/graphics/PorterDuffColorFilter.java
index bddd224aba9a..69d68910c8b5 100644
--- a/graphics/java/android/graphics/PorterDuffColorFilter.java
+++ b/graphics/java/android/graphics/PorterDuffColorFilter.java
@@ -16,6 +16,7 @@
package android.graphics;
+import android.annotation.ColorInt;
import android.annotation.NonNull;
/**
@@ -36,7 +37,7 @@ public class PorterDuffColorFilter extends ColorFilter {
* @see #setColor(int)
* @see #setMode(android.graphics.PorterDuff.Mode)
*/
- public PorterDuffColorFilter(int color, @NonNull PorterDuff.Mode mode) {
+ public PorterDuffColorFilter(@ColorInt int color, @NonNull PorterDuff.Mode mode) {
mColor = color;
mMode = mode;
update();
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 16760c7e5769..56876e94af82 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -521,7 +521,7 @@ public abstract class Drawable {
* {@link #setTintList(ColorStateList) tint}.
* </p>
*/
- public void setColorFilter(int color, @NonNull PorterDuff.Mode mode) {
+ public void setColorFilter(@ColorInt int color, @NonNull PorterDuff.Mode mode) {
setColorFilter(new PorterDuffColorFilter(color, mode));
}
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 3c9ca4e78823..ebf73da0b82f 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -1972,7 +1972,7 @@ public final class MediaCodecInfo {
(Integer)map.get(MediaFormat.KEY_FLAC_COMPRESSION_LEVEL);
if (complexity == null) {
complexity = flacComplexity;
- } else if (flacComplexity != null && complexity != flacComplexity) {
+ } else if (flacComplexity != null && !complexity.equals(flacComplexity)) {
throw new IllegalArgumentException(
"conflicting values for complexity and " +
"flac-compression-level");
@@ -1985,7 +1985,7 @@ public final class MediaCodecInfo {
Integer aacProfile = (Integer)map.get(MediaFormat.KEY_AAC_PROFILE);
if (profile == null) {
profile = aacProfile;
- } else if (aacProfile != null && aacProfile != profile) {
+ } else if (aacProfile != null && !aacProfile.equals(profile)) {
throw new IllegalArgumentException(
"conflicting values for profile and aac-profile");
}
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index c44fbe6d6500..0c1c7e9b0c19 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -606,14 +606,14 @@ public final class MediaFormat {
* Sets the value of an integer key.
*/
public final void setInteger(String name, int value) {
- mMap.put(name, new Integer(value));
+ mMap.put(name, Integer.valueOf(value));
}
/**
* Sets the value of a long key.
*/
public final void setLong(String name, long value) {
- mMap.put(name, new Long(value));
+ mMap.put(name, Long.valueOf(value));
}
/**
diff --git a/media/java/android/media/WebVttRenderer.java b/media/java/android/media/WebVttRenderer.java
index 69e0ea639705..91c53fac1799 100644
--- a/media/java/android/media/WebVttRenderer.java
+++ b/media/java/android/media/WebVttRenderer.java
@@ -433,7 +433,9 @@ class TextTrackCue extends SubtitleTrack.Cue {
mRegionId.equals(cue.mRegionId) &&
mSnapToLines == cue.mSnapToLines &&
mAutoLinePosition == cue.mAutoLinePosition &&
- (mAutoLinePosition || mLinePosition == cue.mLinePosition) &&
+ (mAutoLinePosition ||
+ ((mLinePosition != null && mLinePosition.equals(cue.mLinePosition)) ||
+ (mLinePosition == null && cue.mLinePosition == null))) &&
mTextPosition == cue.mTextPosition &&
mSize == cue.mSize &&
mAlignment == cue.mAlignment &&
diff --git a/media/java/android/media/midi/MidiDeviceInfo.java b/media/java/android/media/midi/MidiDeviceInfo.java
index f7fad3d2a85d..93e0939f0d84 100644
--- a/media/java/android/media/midi/MidiDeviceInfo.java
+++ b/media/java/android/media/midi/MidiDeviceInfo.java
@@ -173,8 +173,16 @@ public final class MidiDeviceInfo implements Parcelable {
mId = id;
mInputPortCount = numInputPorts;
mOutputPortCount = numOutputPorts;
- mInputPortNames = inputPortNames;
- mOutputPortNames = outputPortNames;
+ if (inputPortNames == null) {
+ mInputPortNames = new String[numInputPorts];
+ } else {
+ mInputPortNames = inputPortNames;
+ }
+ if (outputPortNames == null) {
+ mOutputPortNames = new String[numOutputPorts];
+ } else {
+ mOutputPortNames = outputPortNames;
+ }
mProperties = properties;
mIsPrivate = isPrivate;
}
diff --git a/media/java/android/media/tv/TvTrackInfo.java b/media/java/android/media/tv/TvTrackInfo.java
index e0aacd65f01a..0284171d0501 100644
--- a/media/java/android/media/tv/TvTrackInfo.java
+++ b/media/java/android/media/tv/TvTrackInfo.java
@@ -42,6 +42,7 @@ public final class TvTrackInfo implements Parcelable {
private final int mType;
private final String mId;
private final String mLanguage;
+ private final String mDescription;
private final int mAudioChannelCount;
private final int mAudioSampleRate;
private final int mVideoWidth;
@@ -49,12 +50,13 @@ public final class TvTrackInfo implements Parcelable {
private final float mVideoFrameRate;
private final Bundle mExtra;
- private TvTrackInfo(int type, String id, String language, int audioChannelCount,
- int audioSampleRate, int videoWidth, int videoHeight, float videoFrameRate,
- Bundle extra) {
+ private TvTrackInfo(int type, String id, String language, String description,
+ int audioChannelCount, int audioSampleRate, int videoWidth, int videoHeight,
+ float videoFrameRate, Bundle extra) {
mType = type;
mId = id;
mLanguage = language;
+ mDescription = description;
mAudioChannelCount = audioChannelCount;
mAudioSampleRate = audioSampleRate;
mVideoWidth = videoWidth;
@@ -67,6 +69,7 @@ public final class TvTrackInfo implements Parcelable {
mType = in.readInt();
mId = in.readString();
mLanguage = in.readString();
+ mDescription = in.readString();
mAudioChannelCount = in.readInt();
mAudioSampleRate = in.readInt();
mVideoWidth = in.readInt();
@@ -99,6 +102,13 @@ public final class TvTrackInfo implements Parcelable {
}
/**
+ * Returns a user readable description for the current track.
+ */
+ public final String getDescription() {
+ return mDescription;
+ }
+
+ /**
* Returns the audio channel count. Valid only for {@link #TYPE_AUDIO} tracks.
*/
public final int getAudioChannelCount() {
@@ -174,6 +184,7 @@ public final class TvTrackInfo implements Parcelable {
dest.writeInt(mType);
dest.writeString(mId);
dest.writeString(mLanguage);
+ dest.writeString(mDescription);
dest.writeInt(mAudioChannelCount);
dest.writeInt(mAudioSampleRate);
dest.writeInt(mVideoWidth);
@@ -202,6 +213,7 @@ public final class TvTrackInfo implements Parcelable {
private final String mId;
private final int mType;
private String mLanguage;
+ private String mDescription;
private int mAudioChannelCount;
private int mAudioSampleRate;
private int mVideoWidth;
@@ -241,6 +253,16 @@ public final class TvTrackInfo implements Parcelable {
}
/**
+ * Sets a user readable description for the current track.
+ *
+ * @param description The user readable description.
+ */
+ public final Builder setDescription(String description) {
+ mDescription = description;
+ return this;
+ }
+
+ /**
* Sets the audio channel count. Valid only for {@link #TYPE_AUDIO} tracks.
*
* @param audioChannelCount The audio channel count.
@@ -325,8 +347,8 @@ public final class TvTrackInfo implements Parcelable {
* @return The new {@link TvTrackInfo} instance
*/
public TvTrackInfo build() {
- return new TvTrackInfo(mType, mId, mLanguage, mAudioChannelCount, mAudioSampleRate,
- mVideoWidth, mVideoHeight, mVideoFrameRate, mExtra);
+ return new TvTrackInfo(mType, mId, mLanguage, mDescription, mAudioChannelCount,
+ mAudioSampleRate, mVideoWidth, mVideoHeight, mVideoFrameRate, mExtra);
}
}
-} \ No newline at end of file
+}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index eac83d8e2563..7f826ef961db 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -793,7 +793,7 @@ public class SettingsBackupAgent extends BackupAgentHelper {
}
// Figure out the white list and redirects to the global table.
- String[] whitelist = null;
+ final String[] whitelist;
if (contentUri.equals(Settings.Secure.CONTENT_URI)) {
whitelist = Settings.Secure.SETTINGS_TO_BACKUP;
} else if (contentUri.equals(Settings.System.CONTENT_URI)) {
@@ -809,6 +809,7 @@ public class SettingsBackupAgent extends BackupAgentHelper {
Map<String, String> cachedEntries = new HashMap<String, String>();
ContentValues contentValues = new ContentValues(2);
SettingsHelper settingsHelper = mSettingsHelper;
+ ContentResolver cr = getContentResolver();
final int whiteListSize = whitelist.length;
for (int i = 0; i < whiteListSize; i++) {
@@ -841,14 +842,7 @@ public class SettingsBackupAgent extends BackupAgentHelper {
final Uri destination = (movedToGlobal != null && movedToGlobal.contains(key))
? Settings.Global.CONTENT_URI
: contentUri;
-
- // The helper doesn't care what namespace the keys are in
- if (settingsHelper.restoreValue(key, value)) {
- contentValues.clear();
- contentValues.put(Settings.NameValueTable.NAME, key);
- contentValues.put(Settings.NameValueTable.VALUE, value);
- getContentResolver().insert(destination, contentValues);
- }
+ settingsHelper.restoreValue(this, cr, contentValues, destination, key, value);
if (DEBUG) {
Log.d(TAG, "Restored setting: " + destination + " : "+ key + "=" + value);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index 4144c803dbd3..30786f057fbf 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -19,7 +19,10 @@ package com.android.providers.settings;
import android.app.ActivityManagerNative;
import android.app.IActivityManager;
import android.app.backup.IBackupManager;
+import android.content.ContentResolver;
+import android.content.ContentValues;
import android.content.Context;
+import android.content.Intent;
import android.content.res.Configuration;
import android.location.LocationManager;
import android.media.AudioManager;
@@ -28,10 +31,12 @@ import android.net.Uri;
import android.os.IPowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
+import android.util.ArraySet;
import java.util.Locale;
@@ -41,6 +46,49 @@ public class SettingsHelper {
private AudioManager mAudioManager;
private TelephonyManager mTelephonyManager;
+ /**
+ * A few settings elements are special in that a restore of those values needs to
+ * be post-processed by relevant parts of the OS. A restore of any settings element
+ * mentioned in this table will therefore cause the system to send a broadcast with
+ * the {@link Intent#ACTION_SETTING_RESTORED} action, with extras naming the
+ * affected setting and supplying its pre-restore value for comparison.
+ *
+ * @see Intent#ACTION_SETTING_RESTORED
+ * @see System#SETTINGS_TO_BACKUP
+ * @see Secure#SETTINGS_TO_BACKUP
+ * @see Global#SETTINGS_TO_BACKUP
+ *
+ * {@hide}
+ */
+ private static final ArraySet<String> sBroadcastOnRestore;
+ static {
+ sBroadcastOnRestore = new ArraySet<String>(2);
+ sBroadcastOnRestore.add(Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
+ sBroadcastOnRestore.add(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
+ }
+
+ private interface SettingsLookup {
+ public String lookup(ContentResolver resolver, String name, int userHandle);
+ }
+
+ private static SettingsLookup sSystemLookup = new SettingsLookup() {
+ public String lookup(ContentResolver resolver, String name, int userHandle) {
+ return Settings.System.getStringForUser(resolver, name, userHandle);
+ }
+ };
+
+ private static SettingsLookup sSecureLookup = new SettingsLookup() {
+ public String lookup(ContentResolver resolver, String name, int userHandle) {
+ return Settings.Secure.getStringForUser(resolver, name, userHandle);
+ }
+ };
+
+ private static SettingsLookup sGlobalLookup = new SettingsLookup() {
+ public String lookup(ContentResolver resolver, String name, int userHandle) {
+ return Settings.Global.getStringForUser(resolver, name, userHandle);
+ }
+ };
+
public SettingsHelper(Context context) {
mContext = context;
mAudioManager = (AudioManager) context
@@ -58,24 +106,67 @@ public class SettingsHelper {
* some cases the data will be written by the call to the appropriate API,
* and in some cases the property value needs to be modified before setting.
*/
- public boolean restoreValue(String name, String value) {
- if (Settings.System.SCREEN_BRIGHTNESS.equals(name)) {
- setBrightness(Integer.parseInt(value));
- } else if (Settings.System.SOUND_EFFECTS_ENABLED.equals(name)) {
- setSoundEffects(Integer.parseInt(value) == 1);
- } else if (Settings.Secure.LOCATION_PROVIDERS_ALLOWED.equals(name)) {
- setGpsLocation(value);
- return false;
- } else if (Settings.Secure.BACKUP_AUTO_RESTORE.equals(name)) {
- setAutoRestore(Integer.parseInt(value) == 1);
- } else if (isAlreadyConfiguredCriticalAccessibilitySetting(name)) {
- return false;
- } else if (Settings.System.RINGTONE.equals(name)
- || Settings.System.NOTIFICATION_SOUND.equals(name)) {
- setRingtone(name, value);
- return false;
+ public void restoreValue(Context context, ContentResolver cr, ContentValues contentValues,
+ Uri destination, String name, String value) {
+ // Will we need a post-restore broadcast for this element?
+ String oldValue = null;
+ boolean sendBroadcast = false;
+ final SettingsLookup table;
+
+ if (destination.equals(Settings.Secure.CONTENT_URI)) {
+ table = sSecureLookup;
+ } else if (destination.equals(Settings.System.CONTENT_URI)) {
+ table = sSystemLookup;
+ } else { /* must be GLOBAL; this was preflighted by the caller */
+ table = sGlobalLookup;
+ }
+
+ if (sBroadcastOnRestore.contains(name)) {
+ oldValue = table.lookup(cr, name, UserHandle.USER_OWNER);
+ sendBroadcast = true;
+ }
+
+ try {
+ if (Settings.System.SCREEN_BRIGHTNESS.equals(name)) {
+ setBrightness(Integer.parseInt(value));
+ // fall through to the ordinary write to settings
+ } else if (Settings.System.SOUND_EFFECTS_ENABLED.equals(name)) {
+ setSoundEffects(Integer.parseInt(value) == 1);
+ // fall through to the ordinary write to settings
+ } else if (Settings.Secure.LOCATION_PROVIDERS_ALLOWED.equals(name)) {
+ setGpsLocation(value);
+ return;
+ } else if (Settings.Secure.BACKUP_AUTO_RESTORE.equals(name)) {
+ setAutoRestore(Integer.parseInt(value) == 1);
+ } else if (isAlreadyConfiguredCriticalAccessibilitySetting(name)) {
+ return;
+ } else if (Settings.System.RINGTONE.equals(name)
+ || Settings.System.NOTIFICATION_SOUND.equals(name)) {
+ setRingtone(name, value);
+ return;
+ }
+
+ // Default case: write the restored value to settings
+ contentValues.clear();
+ contentValues.put(Settings.NameValueTable.NAME, name);
+ contentValues.put(Settings.NameValueTable.VALUE, value);
+ cr.insert(destination, contentValues);
+ } catch (Exception e) {
+ // If we fail to apply the setting, by definition nothing happened
+ sendBroadcast = false;
+ } finally {
+ // If this was an element of interest, send the "we just restored it"
+ // broadcast with the historical value now that the new value has
+ // been committed and observers kicked off.
+ if (sendBroadcast) {
+ Intent intent = new Intent(Intent.ACTION_SETTING_RESTORED)
+ .setPackage("android").addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)
+ .putExtra(Intent.EXTRA_SETTING_NAME, name)
+ .putExtra(Intent.EXTRA_SETTING_NEW_VALUE, value)
+ .putExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE, oldValue);
+ context.sendBroadcastAsUser(intent, UserHandle.OWNER, null);
+ }
}
- return true;
}
public String onBackupValue(String name, String value) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
index 6c1cdcd2e940..1e40babbda5d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
@@ -162,11 +162,6 @@ public class HeadsUpNotificationView extends FrameLayout implements SwipeHelper.
public void updateNotification(NotificationData.Entry headsUp, boolean alert) {
if (DEBUG) Log.v(TAG, "updateNotification");
- if (alert) {
- mBar.scheduleHeadsUpDecay(mHeadsUpNotificationDecay);
- }
- invalidate();
-
if (mHeadsUp == headsUp) {
resetViewForHeadsup();
// This is an in-place update. Noting more to do.
@@ -197,9 +192,11 @@ public class HeadsUpNotificationView extends FrameLayout implements SwipeHelper.
}
mHeadsUp.setInterruption();
-
+ }
+ if (alert) {
// Make sure the heads up window is open.
mBar.scheduleHeadsUpOpen();
+ mBar.scheduleHeadsUpDecay(mHeadsUpNotificationDecay);
}
}
diff --git a/rs/java/android/renderscript/Script.java b/rs/java/android/renderscript/Script.java
index d35213057eef..83aeedd9540e 100644
--- a/rs/java/android/renderscript/Script.java
+++ b/rs/java/android/renderscript/Script.java
@@ -239,8 +239,10 @@ public class Script extends BaseObj {
FieldPacker v, LaunchOptions sc) {
// TODO: Is this necessary if nScriptForEach calls validate as well?
mRS.validate();
- for (Allocation ain : ains) {
- mRS.validateObject(ain);
+ if (ains != null) {
+ for (Allocation ain : ains) {
+ mRS.validateObject(ain);
+ }
}
mRS.validateObject(aout);
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index a712d789946c..bb5ff1b09bd7 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -352,6 +352,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
intentFilter.addAction(Intent.ACTION_USER_REMOVED);
intentFilter.addAction(Intent.ACTION_USER_PRESENT);
+ intentFilter.addAction(Intent.ACTION_SETTING_RESTORED);
mContext.registerReceiverAsUser(new BroadcastReceiver() {
@Override
@@ -369,6 +370,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
onUserStateChangedLocked(userState);
}
}
+ } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) {
+ final String which = intent.getStringExtra(Intent.EXTRA_SETTING_NAME);
+ if (Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES.equals(which)) {
+ synchronized (mLock) {
+ restoreEnabledAccessibilityServicesLocked(
+ intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE),
+ intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE));
+ }
+ }
}
}
}, UserHandle.ALL, intentFilter, null, null);
@@ -857,6 +867,21 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
}
+ // Called only during settings restore; currently supports only the owner user
+ void restoreEnabledAccessibilityServicesLocked(String oldSetting, String newSetting) {
+ readComponentNamesFromStringLocked(oldSetting, mTempComponentNameSet, false);
+ readComponentNamesFromStringLocked(newSetting, mTempComponentNameSet, true);
+
+ UserState userState = getUserStateLocked(UserHandle.USER_OWNER);
+ userState.mEnabledServices.clear();
+ userState.mEnabledServices.addAll(mTempComponentNameSet);
+ persistComponentNamesToSettingLocked(
+ Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+ userState.mEnabledServices,
+ UserHandle.USER_OWNER);
+ onUserStateChangedLocked(userState);
+ }
+
private InteractionBridge getInteractionBridgeLocked() {
if (mInteractionBridge == null) {
mInteractionBridge = new InteractionBridge();
@@ -1129,10 +1154,27 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
Set<ComponentName> outComponentNames) {
String settingValue = Settings.Secure.getStringForUser(mContext.getContentResolver(),
settingName, userId);
- outComponentNames.clear();
- if (settingValue != null) {
+ readComponentNamesFromStringLocked(settingValue, outComponentNames, false);
+ }
+
+ /**
+ * Populates a set with the {@link ComponentName}s contained in a colon-delimited string.
+ *
+ * @param names The colon-delimited string to parse.
+ * @param outComponentNames The set of component names to be populated based on
+ * the contents of the <code>names</code> string.
+ * @param doMerge If true, the parsed component names will be merged into the output
+ * set, rather than replacing the set's existing contents entirely.
+ */
+ private void readComponentNamesFromStringLocked(String names,
+ Set<ComponentName> outComponentNames,
+ boolean doMerge) {
+ if (!doMerge) {
+ outComponentNames.clear();
+ }
+ if (names != null) {
TextUtils.SimpleStringSplitter splitter = mStringColonSplitter;
- splitter.setString(settingValue);
+ splitter.setString(names);
while (splitter.hasNext()) {
String str = splitter.next();
if (str == null || str.length() <= 0) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index e7952c1a9b60..a366c7bb9003 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -51,6 +51,8 @@ import android.graphics.Point;
import android.graphics.Rect;
import android.os.BatteryStats;
import android.os.PersistableBundle;
+import android.os.PowerManager;
+import android.os.WorkSource;
import android.os.storage.IMountService;
import android.os.storage.StorageManager;
import android.service.voice.IVoiceInteractionSession;
@@ -991,7 +993,14 @@ public final class ActivityManagerService extends ActivityManagerNative
* Set while we are running a voice interaction. This overrides
* sleeping while it is active.
*/
- private boolean mRunningVoice = false;
+ private IVoiceInteractionSession mRunningVoice;
+
+ /**
+ * We want to hold a wake lock while running a voice interaction session, since
+ * this may happen with the screen off and we need to keep the CPU running to
+ * be able to continue to interact with the user.
+ */
+ PowerManager.WakeLock mVoiceWakeLock;
/**
* State of external calls telling us if the device is awake or asleep.
@@ -2269,6 +2278,9 @@ public final class ActivityManagerService extends ActivityManagerNative
public void initPowerManagement() {
mStackSupervisor.initPowerManagement();
mBatteryStatsService.initPowerManagement();
+ PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
+ mVoiceWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*voice*");
+ mVoiceWakeLock.setReferenceCounted(false);
}
@Override
@@ -2472,7 +2484,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (DEBUG_FOCUS) Slog.d(TAG, "setFocusedActivityLocked: r=" + r);
mFocusedActivity = r;
if (r.task != null && r.task.voiceInteractor != null) {
- startRunningVoiceLocked();
+ startRunningVoiceLocked(r.task.voiceSession, r.info.applicationInfo.uid);
} else {
finishRunningVoiceLocked();
}
@@ -3628,6 +3640,19 @@ public final class ActivityManagerService extends ActivityManagerNative
}
@Override
+ public void setVoiceKeepAwake(IVoiceInteractionSession session, boolean keepAwake) {
+ synchronized (this) {
+ if (mRunningVoice != null && mRunningVoice.asBinder() == session.asBinder()) {
+ if (keepAwake) {
+ mVoiceWakeLock.acquire();
+ } else {
+ mVoiceWakeLock.release();
+ }
+ }
+ }
+ }
+
+ @Override
public boolean startNextMatchingActivity(IBinder callingActivity,
Intent intent, Bundle options) {
// Refuse possible leaked file descriptors
@@ -9685,8 +9710,8 @@ public final class ActivityManagerService extends ActivityManagerNative
}
void finishRunningVoiceLocked() {
- if (mRunningVoice) {
- mRunningVoice = false;
+ if (mRunningVoice != null) {
+ mRunningVoice = null;
updateSleepIfNeededLocked();
}
}
@@ -9709,7 +9734,7 @@ public final class ActivityManagerService extends ActivityManagerNative
private boolean shouldSleepLocked() {
// Resume applications while running a voice interactor.
- if (mRunningVoice) {
+ if (mRunningVoice != null) {
return false;
}
@@ -9810,10 +9835,14 @@ public final class ActivityManagerService extends ActivityManagerNative
+ " mSleeping=" + mSleeping);
}
- void startRunningVoiceLocked() {
- if (!mRunningVoice) {
- mRunningVoice = true;
- updateSleepIfNeededLocked();
+ void startRunningVoiceLocked(IVoiceInteractionSession session, int targetUid) {
+ mVoiceWakeLock.setWorkSource(new WorkSource(targetUid));
+ if (mRunningVoice == null || mRunningVoice.asBinder() != session.asBinder()) {
+ if (mRunningVoice == null) {
+ mVoiceWakeLock.acquire();
+ updateSleepIfNeededLocked();
+ }
+ mRunningVoice = session;
}
}
@@ -12813,8 +12842,11 @@ public final class ActivityManagerService extends ActivityManagerNative
+ PowerManagerInternal.wakefulnessToString(mWakefulness));
pw.println(" mSleeping=" + mSleeping + " mLockScreenShown="
+ lockScreenShownToString());
- pw.println(" mShuttingDown=" + mShuttingDown + " mRunningVoice=" + mRunningVoice
- + " mTestPssMode=" + mTestPssMode);
+ pw.println(" mShuttingDown=" + mShuttingDown + " mTestPssMode=" + mTestPssMode);
+ if (mRunningVoice != null) {
+ pw.println(" mRunningVoice=" + mRunningVoice);
+ pw.println(" mVoiceWakeLock" + mVoiceWakeLock);
+ }
}
if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
|| mOrigWaitForDebugger) {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index be9526868107..456ed3330eac 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -869,7 +869,7 @@ final class ActivityStack {
// If we are not going to sleep, we want to ensure the device is
// awake until the next activity is started.
- if (!mService.isSleepingOrShuttingDown()) {
+ if (!uiSleeping && !mService.isSleepingOrShuttingDown()) {
mStackSupervisor.acquireLaunchWakelock();
}
@@ -1671,6 +1671,8 @@ final class ActivityStack {
}
}
+ mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);
+
// We need to start pausing the current activity so the top one
// can be resumed...
boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0;
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index cbbb11a8dfb3..f56f65fa8ec9 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -84,6 +84,7 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.os.WorkSource;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.service.voice.IVoiceInteractionSession;
@@ -316,8 +317,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
void initPowerManagement() {
PowerManager pm = (PowerManager)mService.mContext.getSystemService(Context.POWER_SERVICE);
mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
- mLaunchingActivity =
- pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
+ mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*launch*");
mLaunchingActivity.setReferenceCounted(false);
}
@@ -2273,6 +2273,10 @@ public final class ActivityStackSupervisor implements DisplayListener {
}
}
+ void setLaunchSource(int uid) {
+ mLaunchingActivity.setWorkSource(new WorkSource(uid));
+ }
+
void acquireLaunchWakelock() {
if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
throw new IllegalStateException("Calling must be system uid");
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 0c7d71b1d0e7..9ccb2eaf1fb3 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -18,10 +18,12 @@ package com.android.server.notification;
import android.app.ActivityManager;
import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -51,6 +53,7 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
/**
@@ -74,6 +77,7 @@ abstract public class ManagedServices {
private final UserProfiles mUserProfiles;
private final SettingsObserver mSettingsObserver;
private final Config mConfig;
+ private ArraySet<String> mRestored;
// contains connections to all connected services, including app services
// and system services
@@ -91,6 +95,8 @@ abstract public class ManagedServices {
// user change).
private int[] mLastSeenProfileIds;
+ private final BroadcastReceiver mRestoreReceiver;
+
public ManagedServices(Context context, Handler handler, Object mutex,
UserProfiles userProfiles) {
mContext = context;
@@ -98,6 +104,24 @@ abstract public class ManagedServices {
mUserProfiles = userProfiles;
mConfig = getConfig();
mSettingsObserver = new SettingsObserver(handler);
+
+ mRestoreReceiver = new SettingRestoredReceiver();
+ IntentFilter filter = new IntentFilter(Intent.ACTION_SETTING_RESTORED);
+ context.registerReceiver(mRestoreReceiver, filter);
+ }
+
+ class SettingRestoredReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_SETTING_RESTORED.equals(intent.getAction())) {
+ String element = intent.getStringExtra(Intent.EXTRA_SETTING_NAME);
+ if (Objects.equals(element, mConfig.secureSettingName)) {
+ String prevValue = intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE);
+ String newValue = intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE);
+ settingRestored(element, prevValue, newValue, getSendingUserId());
+ }
+ }
+ }
}
abstract protected Config getConfig();
@@ -140,6 +164,31 @@ abstract public class ManagedServices {
}
}
+ // By convention, restored settings are replicated to another settings
+ // entry, named similarly but with a disambiguation suffix.
+ public static final String restoredSettingName(Config config) {
+ return config.secureSettingName + ":restored";
+ }
+
+ // The OS has done a restore of this service's saved state. We clone it to the
+ // 'restored' reserve, and then once we return and the actual write to settings is
+ // performed, our observer will do the work of maintaining the restored vs live
+ // settings data.
+ public void settingRestored(String element, String oldValue, String newValue, int userid) {
+ if (DEBUG) Slog.d(TAG, "Restored managed service setting: " + element
+ + " ovalue=" + oldValue + " nvalue=" + newValue);
+ if (mConfig.secureSettingName.equals(element)) {
+ if (element != null) {
+ mRestored = null;
+ Settings.Secure.putStringForUser(mContext.getContentResolver(),
+ restoredSettingName(mConfig),
+ newValue,
+ userid);
+ disableNonexistentServices(userid);
+ }
+ }
+ }
+
public void onPackagesChanged(boolean queryReplace, String[] pkgList) {
if (DEBUG) Slog.d(TAG, "onPackagesChanged queryReplace=" + queryReplace
+ " pkgList=" + (pkgList == null ? null : Arrays.asList(pkgList))
@@ -211,8 +260,23 @@ abstract public class ManagedServices {
}
private void disableNonexistentServices(int userId) {
+ final ContentResolver cr = mContext.getContentResolver();
+ boolean restoredChanged = false;
+ if (mRestored == null) {
+ String restoredSetting = Settings.Secure.getStringForUser(
+ cr,
+ restoredSettingName(mConfig),
+ userId);
+ if (!TextUtils.isEmpty(restoredSetting)) {
+ if (DEBUG) Slog.d(TAG, "restored: " + restoredSetting);
+ String[] restored = restoredSetting.split(ENABLED_SERVICES_SEPARATOR);
+ mRestored = new ArraySet<String>(Arrays.asList(restored));
+ } else {
+ mRestored = new ArraySet<String>();
+ }
+ }
String flatIn = Settings.Secure.getStringForUser(
- mContext.getContentResolver(),
+ cr,
mConfig.secureSettingName,
userId);
if (!TextUtils.isEmpty(flatIn)) {
@@ -228,14 +292,16 @@ abstract public class ManagedServices {
ResolveInfo resolveInfo = installedServices.get(i);
ServiceInfo info = resolveInfo.serviceInfo;
+ ComponentName component = new ComponentName(info.packageName, info.name);
if (!mConfig.bindPermission.equals(info.permission)) {
Slog.w(TAG, "Skipping " + getCaption() + " service "
+ info.packageName + "/" + info.name
+ ": it does not require the permission "
+ mConfig.bindPermission);
+ restoredChanged |= mRestored.remove(component.flattenToString());
continue;
}
- installed.add(new ComponentName(info.packageName, info.name));
+ installed.add(component);
}
String flatOut = "";
@@ -246,16 +312,27 @@ abstract public class ManagedServices {
ComponentName enabledComponent = ComponentName.unflattenFromString(enabled[i]);
if (installed.contains(enabledComponent)) {
remaining.add(enabled[i]);
+ restoredChanged |= mRestored.remove(enabled[i]);
}
}
+ remaining.addAll(mRestored);
flatOut = TextUtils.join(ENABLED_SERVICES_SEPARATOR, remaining);
}
if (DEBUG) Slog.v(TAG, "flat after: " + flatOut);
if (!flatIn.equals(flatOut)) {
- Settings.Secure.putStringForUser(mContext.getContentResolver(),
+ Settings.Secure.putStringForUser(cr,
mConfig.secureSettingName,
flatOut, userId);
}
+ if (restoredChanged) {
+ if (DEBUG) Slog.d(TAG, "restored changed; rewriting");
+ final String flatRestored = TextUtils.join(ENABLED_SERVICES_SEPARATOR,
+ mRestored.toArray());
+ Settings.Secure.putStringForUser(cr,
+ restoredSettingName(mConfig),
+ flatRestored,
+ userId);
+ }
}
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 6b8c49cc82fc..f032ccfba9c3 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -479,6 +479,24 @@ public class VoiceInteractionManagerService extends SystemService {
}
@Override
+ public void setKeepAwake(IBinder token, boolean keepAwake) {
+ synchronized (this) {
+ if (mImpl == null) {
+ Slog.w(TAG, "setKeepAwake without running voice interaction service");
+ return;
+ }
+ final int callingPid = Binder.getCallingPid();
+ final int callingUid = Binder.getCallingUid();
+ final long caller = Binder.clearCallingIdentity();
+ try {
+ mImpl.setKeepAwakeLocked(callingPid, callingUid, token, keepAwake);
+ } finally {
+ Binder.restoreCallingIdentity(caller);
+ }
+ }
+ }
+
+ @Override
public void finish(IBinder token) {
synchronized (this) {
if (mImpl == null) {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 9e92867349ce..5a91b88f147b 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -174,6 +174,18 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
}
}
+ public void setKeepAwakeLocked(int callingPid, int callingUid, IBinder token,
+ boolean keepAwake) {
+ try {
+ if (mActiveSession == null || token != mActiveSession.mToken) {
+ Slog.w(TAG, "setKeepAwake does not match active session");
+ return;
+ }
+ mAm.setVoiceKeepAwake(mActiveSession.mSession, keepAwake);
+ } catch (RemoteException e) {
+ throw new IllegalStateException("Unexpected remote error", e);
+ }
+ }
public void finishLocked(int callingPid, int callingUid, IBinder token) {
if (mActiveSession == null || token != mActiveSession.mToken) {
diff --git a/tests/VoiceInteraction/res/layout/test_interaction.xml b/tests/VoiceInteraction/res/layout/test_interaction.xml
index f4648b57dfab..8c8151d59ca0 100644
--- a/tests/VoiceInteraction/res/layout/test_interaction.xml
+++ b/tests/VoiceInteraction/res/layout/test_interaction.xml
@@ -41,6 +41,13 @@
android:text="@string/completeVoice"
/>
+ <Button android:id="@+id/pick"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:text="@string/pickVoice"
+ />
+
<Button android:id="@+id/abort"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/tests/VoiceInteraction/res/values/strings.xml b/tests/VoiceInteraction/res/values/strings.xml
index 9f99c97bbb69..5331457e22b1 100644
--- a/tests/VoiceInteraction/res/values/strings.xml
+++ b/tests/VoiceInteraction/res/values/strings.xml
@@ -22,7 +22,7 @@
<string name="complete">Complete</string>
<string name="abortVoice">Abort Voice</string>
<string name="completeVoice">Complete Voice</string>
+ <string name="pickVoice">Pick Voice</string>
<string name="cancelVoice">Cancel</string>
</resources>
-
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
index bcfc6f436bfa..ad339befdd00 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
@@ -18,6 +18,7 @@ package com.android.test.voiceinteraction;
import android.app.AssistContent;
import android.app.AssistStructure;
+import android.app.VoiceInteractor;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
@@ -47,12 +48,15 @@ public class MainInteractionSession extends VoiceInteractionSession
static final int STATE_IDLE = 0;
static final int STATE_LAUNCHING = 1;
static final int STATE_CONFIRM = 2;
- static final int STATE_COMMAND = 3;
- static final int STATE_ABORT_VOICE = 4;
- static final int STATE_COMPLETE_VOICE = 5;
- static final int STATE_DONE=6;
+ static final int STATE_PICK_OPTION = 3;
+ static final int STATE_COMMAND = 4;
+ static final int STATE_ABORT_VOICE = 5;
+ static final int STATE_COMPLETE_VOICE = 6;
+ static final int STATE_DONE=7;
int mState = STATE_IDLE;
+ VoiceInteractor.PickOptionRequest.Option[] mPendingOptions;
+ CharSequence mPendingPrompt;
Request mPendingRequest;
MainInteractionSession(Context context) {
@@ -154,7 +158,8 @@ public class MainInteractionSession extends VoiceInteractionSession
mAssistVisualizer.setVisibility(View.GONE);
}
mStartButton.setEnabled(mState == STATE_IDLE);
- mConfirmButton.setEnabled(mState == STATE_CONFIRM || mState == STATE_COMMAND);
+ mConfirmButton.setEnabled(mState == STATE_CONFIRM || mState == STATE_PICK_OPTION
+ || mState == STATE_COMMAND);
mAbortButton.setEnabled(mState == STATE_ABORT_VOICE);
mCompleteButton.setEnabled(mState == STATE_COMPLETE_VOICE);
}
@@ -167,10 +172,32 @@ public class MainInteractionSession extends VoiceInteractionSession
} else if (v == mConfirmButton) {
if (mState == STATE_CONFIRM) {
mPendingRequest.sendConfirmResult(true, null);
- } else {
+ mPendingRequest = null;
+ mState = STATE_LAUNCHING;
+ } else if (mState == STATE_PICK_OPTION) {
+ int numReturn = mPendingOptions.length/2;
+ if (numReturn <= 0) {
+ numReturn = 1;
+ }
+ VoiceInteractor.PickOptionRequest.Option[] picked
+ = new VoiceInteractor.PickOptionRequest.Option[numReturn];
+ for (int i=0; i<picked.length; i++) {
+ picked[i] = mPendingOptions[i*2];
+ }
+ mPendingOptions = picked;
+ if (picked.length <= 1) {
+ mPendingRequest.sendPickOptionResult(true, picked, null);
+ mPendingRequest = null;
+ mState = STATE_LAUNCHING;
+ } else {
+ mPendingRequest.sendPickOptionResult(false, picked, null);
+ updatePickText();
+ }
+ } else if (mPendingRequest != null) {
mPendingRequest.sendCommandResult(true, null);
+ mPendingRequest = null;
+ mState = STATE_LAUNCHING;
}
- mPendingRequest = null;
} else if (v == mAbortButton) {
mPendingRequest.sendAbortVoiceResult(null);
mPendingRequest = null;
@@ -178,6 +205,7 @@ public class MainInteractionSession extends VoiceInteractionSession
mPendingRequest.sendCompleteVoiceResult(null);
mPendingRequest = null;
}
+ updateState();
}
@Override
@@ -198,13 +226,40 @@ public class MainInteractionSession extends VoiceInteractionSession
public void onConfirm(Caller caller, Request request, CharSequence prompt, Bundle extras) {
Log.i(TAG, "onConfirm: prompt=" + prompt + " extras=" + extras);
mText.setText(prompt);
- mStartButton.setText("Confirm");
+ mConfirmButton.setText("Confirm");
mPendingRequest = request;
+ mPendingPrompt = prompt;
mState = STATE_CONFIRM;
updateState();
}
@Override
+ public void onPickOption(Caller caller, Request request, CharSequence prompt,
+ VoiceInteractor.PickOptionRequest.Option[] options, Bundle extras) {
+ Log.i(TAG, "onPickOption: prompt=" + prompt + " options=" + options + " extras=" + extras);
+ mConfirmButton.setText("Pick Option");
+ mPendingRequest = request;
+ mPendingPrompt = prompt;
+ mPendingOptions = options;
+ mState = STATE_PICK_OPTION;
+ updatePickText();
+ updateState();
+ }
+
+ void updatePickText() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(mPendingPrompt);
+ sb.append(": ");
+ for (int i=0; i<mPendingOptions.length; i++) {
+ if (i > 0) {
+ sb.append(", ");
+ }
+ sb.append(mPendingOptions[i].getLabel());
+ }
+ mText.setText(sb.toString());
+ }
+
+ @Override
public void onCompleteVoice(Caller caller, Request request, CharSequence message, Bundle extras) {
Log.i(TAG, "onCompleteVoice: message=" + message + " extras=" + extras);
mText.setText(message);
@@ -226,7 +281,7 @@ public class MainInteractionSession extends VoiceInteractionSession
public void onCommand(Caller caller, Request request, String command, Bundle extras) {
Log.i(TAG, "onCommand: command=" + command + " extras=" + extras);
mText.setText("Command: " + command);
- mStartButton.setText("Finish Command");
+ mConfirmButton.setText("Finish Command");
mPendingRequest = request;
mState = STATE_COMMAND;
updateState();
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java
index 023e0ec79315..e195c30c1f7b 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java
@@ -26,14 +26,17 @@ import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
+import android.widget.TextView;
public class TestInteractionActivity extends Activity implements View.OnClickListener {
static final String TAG = "TestInteractionActivity";
VoiceInteractor mInteractor;
VoiceInteractor.Request mCurrentRequest = null;
+ TextView mLog;
Button mAbortButton;
Button mCompleteButton;
+ Button mPickButton;
Button mCancelButton;
@Override
@@ -54,10 +57,13 @@ public class TestInteractionActivity extends Activity implements View.OnClickLis
}
setContentView(R.layout.test_interaction);
+ mLog = (TextView)findViewById(R.id.log);
mAbortButton = (Button)findViewById(R.id.abort);
mAbortButton.setOnClickListener(this);
mCompleteButton = (Button)findViewById(R.id.complete);
mCompleteButton.setOnClickListener(this);
+ mPickButton = (Button)findViewById(R.id.pick);
+ mPickButton.setOnClickListener(this);
mCancelButton = (Button)findViewById(R.id.cancel);
mCancelButton.setOnClickListener(this);
@@ -92,11 +98,13 @@ public class TestInteractionActivity extends Activity implements View.OnClickLis
@Override
public void onCancel() {
Log.i(TAG, "Canceled!");
+ mLog.append("Canceled abort\n");
}
@Override
public void onAbortResult(Bundle result) {
Log.i(TAG, "Abort result: result=" + result);
+ mLog.append("Abort: result=" + result + "\n");
getActivity().finish();
}
};
@@ -107,15 +115,56 @@ public class TestInteractionActivity extends Activity implements View.OnClickLis
@Override
public void onCancel() {
Log.i(TAG, "Canceled!");
+ mLog.append("Canceled complete\n");
}
@Override
public void onCompleteResult(Bundle result) {
Log.i(TAG, "Complete result: result=" + result);
+ mLog.append("Complete: result=" + result + "\n");
getActivity().finish();
}
};
mInteractor.submitRequest(req);
+ } else if (v == mPickButton) {
+ VoiceInteractor.PickOptionRequest.Option[] options =
+ new VoiceInteractor.PickOptionRequest.Option[5];
+ options[0] = new VoiceInteractor.PickOptionRequest.Option("One");
+ options[1] = new VoiceInteractor.PickOptionRequest.Option("Two");
+ options[2] = new VoiceInteractor.PickOptionRequest.Option("Three");
+ options[3] = new VoiceInteractor.PickOptionRequest.Option("Four");
+ options[4] = new VoiceInteractor.PickOptionRequest.Option("Five");
+ VoiceInteractor.PickOptionRequest req = new VoiceInteractor.PickOptionRequest(
+ "Need to pick something", options, null) {
+ @Override
+ public void onCancel() {
+ Log.i(TAG, "Canceled!");
+ mLog.append("Canceled pick\n");
+ }
+
+ @Override
+ public void onPickOptionResult(boolean finished, Option[] selections, Bundle result) {
+ Log.i(TAG, "Pick result: finished=" + finished + " selections=" + selections
+ + " result=" + result);
+ StringBuilder sb = new StringBuilder();
+ if (finished) {
+ sb.append("Pick final result: ");
+ } else {
+ sb.append("Pick intermediate result: ");
+ }
+ for (int i=0; i<selections.length; i++) {
+ if (i >= 1) {
+ sb.append(", ");
+ }
+ sb.append(selections[i].getLabel());
+ }
+ mLog.append(sb.toString());
+ if (finished) {
+ getActivity().finish();
+ }
+ }
+ };
+ mInteractor.submitRequest(req);
} else if (v == mCancelButton && mCurrentRequest != null) {
Log.i(TAG, "Cancel request");
mCurrentRequest.cancel();
diff --git a/tools/aapt/XMLNode.cpp b/tools/aapt/XMLNode.cpp
index b38b2eda4f73..d2cd2d64246c 100644
--- a/tools/aapt/XMLNode.cpp
+++ b/tools/aapt/XMLNode.cpp
@@ -466,7 +466,7 @@ void printXMLBlock(ResXMLTree* block)
block->restart();
Vector<namespace_entry> namespaces;
-
+
ResXMLTree::event_code_t code;
int depth = 0;
while ((code=block->next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
@@ -520,7 +520,12 @@ void printXMLBlock(ResXMLTree* block)
printf("\n");
}
} else if (code == ResXMLTree::END_TAG) {
- depth--;
+ // Invalid tag nesting can be misused to break the parsing
+ // code below. Break if detected.
+ if (--depth < 0) {
+ printf("***BAD DEPTH in XMLBlock: %d\n", depth);
+ break;
+ }
} else if (code == ResXMLTree::START_NAMESPACE) {
namespace_entry ns;
size_t len;
@@ -536,7 +541,10 @@ void printXMLBlock(ResXMLTree* block)
ns.uri.string());
depth++;
} else if (code == ResXMLTree::END_NAMESPACE) {
- depth--;
+ if (--depth < 0) {
+ printf("***BAD DEPTH in XMLBlock: %d\n", depth);
+ break;
+ }
const namespace_entry& ns = namespaces.top();
size_t len;
const char16_t* prefix16 = block->getNamespacePrefix(&len);
@@ -714,7 +722,7 @@ const String8& XMLNode::getFilename() const
{
return mFilename;
}
-
+
const Vector<XMLNode::attribute_entry>&
XMLNode::getAttributes() const
{
@@ -730,7 +738,7 @@ const XMLNode::attribute_entry* XMLNode::getAttribute(const String16& ns,
return &ae;
}
}
-
+
return NULL;
}
@@ -774,14 +782,14 @@ sp<XMLNode> XMLNode::searchElement(const String16& tagNamespace, const String16&
&& mElementName == tagName) {
return this;
}
-
+
for (size_t i=0; i<mChildren.size(); i++) {
sp<XMLNode> found = mChildren.itemAt(i)->searchElement(tagNamespace, tagName);
if (found != NULL) {
return found;
}
}
-
+
return NULL;
}
@@ -795,7 +803,7 @@ sp<XMLNode> XMLNode::getChildElement(const String16& tagNamespace, const String1
return child;
}
}
-
+
return NULL;
}
@@ -977,7 +985,7 @@ status_t XMLNode::parseValues(const sp<AaptAssets>& assets,
ResourceTable* table)
{
bool hasErrors = false;
-
+
if (getType() == TYPE_ELEMENT) {
const size_t N = mAttributes.size();
String16 defPackage(assets->getPackage());
@@ -1013,7 +1021,7 @@ status_t XMLNode::assignResourceIds(const sp<AaptAssets>& assets,
const ResourceTable* table)
{
bool hasErrors = false;
-
+
if (getType() == TYPE_ELEMENT) {
String16 attr("attr");
const char* errorMsg;
@@ -1093,7 +1101,7 @@ status_t XMLNode::flatten(const sp<AaptFile>& dest,
{
StringPool strings(mUTF8);
Vector<uint32_t> resids;
-
+
// First collect just the strings for attribute names that have a
// resource ID assigned to them. This ensures that the resource ID
// array is compact, and makes it easier to deal with attribute names
@@ -1141,7 +1149,7 @@ status_t XMLNode::flatten(const sp<AaptFile>& dest,
dest->getSize(), (stringPool->getSize()*100)/dest->getSize(),
dest->getPath().string());
}
-
+
return NO_ERROR;
}
@@ -1217,7 +1225,7 @@ XMLNode::startNamespace(void *userData, const char *prefix, const char *uri)
printf("Start Namespace: %s %s\n", prefix, uri);
}
ParseState* st = (ParseState*)userData;
- sp<XMLNode> node = XMLNode::newNamespace(st->filename,
+ sp<XMLNode> node = XMLNode::newNamespace(st->filename,
String16(prefix != NULL ? prefix : ""), String16(uri));
node->setStartLineNumber(XML_GetCurrentLineNumber(st->parser));
if (st->stack.size() > 0) {
@@ -1338,7 +1346,7 @@ status_t XMLNode::collect_strings(StringPool* dest, Vector<uint32_t>* outResIds,
bool stripComments, bool stripRawValues) const
{
collect_attr_strings(dest, outResIds, true);
-
+
int i;
if (RESOURCES_TOOLS_NAMESPACE != mNamespaceUri) {
if (mNamespacePrefix.size() > 0) {