Merge "Reject request when any unknown flag is speficied" into lmp-dev
diff --git a/api/current.txt b/api/current.txt
index 6fbd40b..686d6ab 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -905,6 +905,8 @@
field public static final int multiprocess = 16842771; // 0x1010013
field public static final int name = 16842755; // 0x1010003
field public static final int navigationBarColor = 16843858; // 0x1010452
+ field public static final int navigationContentDescription = 16843970; // 0x10104c2
+ field public static final int navigationIcon = 16843969; // 0x10104c1
field public static final int navigationMode = 16843471; // 0x10102cf
field public static final int negativeButtonText = 16843254; // 0x10101f6
field public static final int nestedScrollingEnabled = 16843830; // 0x1010436
@@ -27196,16 +27198,14 @@
package android.service.voice {
public class AlwaysOnHotwordDetector {
- method public android.content.Intent getManageIntent(int);
+ method public android.content.Intent createIntentToEnroll();
+ method public android.content.Intent createIntentToReEnroll();
+ method public android.content.Intent createIntentToUnEnroll();
method public int getSupportedRecognitionModes();
method public boolean startRecognition(int);
method public boolean stopRecognition();
- field public static final int MANAGE_ACTION_ENROLL = 0; // 0x0
- field public static final int MANAGE_ACTION_RE_ENROLL = 1; // 0x1
- field public static final int MANAGE_ACTION_UN_ENROLL = 2; // 0x2
field public static final int RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS = 2; // 0x2
field public static final int RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO = 1; // 0x1
- field public static final int RECOGNITION_FLAG_NONE = 0; // 0x0
field public static final int RECOGNITION_MODE_USER_IDENTIFICATION = 2; // 0x2
field public static final int RECOGNITION_MODE_VOICE_TRIGGER = 1; // 0x1
field public static final int STATE_HARDWARE_UNAVAILABLE = -2; // 0xfffffffe
@@ -27214,7 +27214,8 @@
field public static final int STATE_KEYPHRASE_UNSUPPORTED = -1; // 0xffffffff
}
- public static abstract interface AlwaysOnHotwordDetector.Callback {
+ public static abstract class AlwaysOnHotwordDetector.Callback {
+ ctor public AlwaysOnHotwordDetector.Callback();
method public abstract void onAvailabilityChanged(int);
method public abstract void onDetected(android.service.voice.AlwaysOnHotwordDetector.EventPayload);
method public abstract void onError();
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index c928a18..44e24b1 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -623,7 +623,7 @@
try {
final ParcelFileDescriptor clientSocket = mSession.openWrite(name,
offsetBytes, lengthBytes);
- return new FileBridge.FileBridgeOutputStream(clientSocket.getFileDescriptor());
+ return new FileBridge.FileBridgeOutputStream(clientSocket);
} catch (RuntimeException e) {
ExceptionUtils.maybeUnwrapIOException(e);
throw e;
diff --git a/core/java/android/hardware/hdmi/HdmiPortInfo.java b/core/java/android/hardware/hdmi/HdmiPortInfo.java
index 85e7531..2ec6126 100644
--- a/core/java/android/hardware/hdmi/HdmiPortInfo.java
+++ b/core/java/android/hardware/hdmi/HdmiPortInfo.java
@@ -166,7 +166,7 @@
public String toString() {
StringBuffer s = new StringBuffer();
s.append("port_id: ").append(mId).append(", ");
- s.append("address: ").append(mAddress).append(", ");
+ s.append("address: ").append(String.format("0x%04x", mAddress)).append(", ");
s.append("cec: ").append(mCecSupported).append(", ");
s.append("arc: ").append(mArcSupported).append(", ");
s.append("mhl: ").append(mMhlSupported);
diff --git a/core/java/android/os/FileBridge.java b/core/java/android/os/FileBridge.java
index bf8d15c..022a106 100644
--- a/core/java/android/os/FileBridge.java
+++ b/core/java/android/os/FileBridge.java
@@ -131,10 +131,17 @@
}
public static class FileBridgeOutputStream extends OutputStream {
+ private final ParcelFileDescriptor mClientPfd;
private final FileDescriptor mClient;
private final byte[] mTemp = new byte[MSG_LENGTH];
+ public FileBridgeOutputStream(ParcelFileDescriptor clientPfd) {
+ mClientPfd = clientPfd;
+ mClient = clientPfd.getFileDescriptor();
+ }
+
public FileBridgeOutputStream(FileDescriptor client) {
+ mClientPfd = null;
mClient = client;
}
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index 2095773..519bc28 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.Activity;
import android.content.Intent;
import android.hardware.soundtrigger.IRecognitionStatusCallback;
import android.hardware.soundtrigger.KeyphraseEnrollmentInfo;
@@ -84,20 +85,31 @@
private static final int STATE_NOT_READY = 0;
// Keyphrase management actions. Used in getManageIntent() ----//
- /** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(value = {
MANAGE_ACTION_ENROLL,
MANAGE_ACTION_RE_ENROLL,
MANAGE_ACTION_UN_ENROLL
})
- public @interface ManageActions {}
+ private @interface ManageActions {}
- /** Indicates that we need to enroll. */
+ /**
+ * Indicates that we need to enroll.
+ *
+ * @hide
+ */
public static final int MANAGE_ACTION_ENROLL = 0;
- /** Indicates that we need to re-enroll. */
+ /**
+ * Indicates that we need to re-enroll.
+ *
+ * @hide
+ */
public static final int MANAGE_ACTION_RE_ENROLL = 1;
- /** Indicates that we need to un-enroll. */
+ /**
+ * Indicates that we need to un-enroll.
+ *
+ * @hide
+ */
public static final int MANAGE_ACTION_UN_ENROLL = 2;
//-- Flags for startRecognition ----//
@@ -111,7 +123,11 @@
})
public @interface RecognitionFlags {}
- /** Empty flag for {@link #startRecognition(int)}. */
+ /**
+ * Empty flag for {@link #startRecognition(int)}.
+ *
+ * @hide
+ */
public static final int RECOGNITION_FLAG_NONE = 0;
/**
* Recognition flag for {@link #startRecognition(int)} that indicates
@@ -264,7 +280,7 @@
/**
* Callbacks for always-on hotword detection.
*/
- public interface Callback {
+ public static abstract class Callback {
/**
* Called when the hotword availability changes.
* This indicates a change in the availability of recognition for the given keyphrase.
@@ -278,7 +294,7 @@
* @see AlwaysOnHotwordDetector#STATE_KEYPHRASE_UNENROLLED
* @see AlwaysOnHotwordDetector#STATE_KEYPHRASE_ENROLLED
*/
- void onAvailabilityChanged(int status);
+ public abstract void onAvailabilityChanged(int status);
/**
* Called when the keyphrase is spoken.
* This implicitly stops listening for the keyphrase once it's detected.
@@ -289,23 +305,23 @@
* This may contain the trigger audio, if requested when calling
* {@link AlwaysOnHotwordDetector#startRecognition(int)}.
*/
- void onDetected(@NonNull EventPayload eventPayload);
+ public abstract void onDetected(@NonNull EventPayload eventPayload);
/**
* Called when the detection fails due to an error.
*/
- void onError();
+ public abstract void onError();
/**
* Called when the recognition is paused temporarily for some reason.
* This is an informational callback, and the clients shouldn't be doing anything here
* except showing an indication on their UI if they have to.
*/
- void onRecognitionPaused();
+ public abstract void onRecognitionPaused();
/**
* Called when the recognition is resumed after it was temporarily paused.
* This is an informational callback, and the clients shouldn't be doing anything here
* except showing an indication on their UI if they have to.
*/
- void onRecognitionResumed();
+ public abstract void onRecognitionResumed();
}
/**
@@ -372,10 +388,10 @@
/**
* Starts recognition for the associated keyphrase.
*
+ * @see #RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO
+ * @see #RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS
+ *
* @param recognitionFlags The flags to control the recognition properties.
- * The allowed flags are {@link #RECOGNITION_FLAG_NONE},
- * {@link #RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO} and
- * {@link #RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS}.
* @return Indicates whether the call succeeded or not.
* @throws UnsupportedOperationException if the recognition isn't supported.
* Callers should only call this method after a supported state callback on
@@ -430,12 +446,13 @@
}
/**
- * Gets an intent to manage the associated keyphrase.
+ * Creates an intent to start the enrollment for the associated keyphrase.
+ * This intent must be invoked using {@link Activity#startActivityForResult(Intent, int)}.
+ * Starting re-enrollment is only valid if the keyphrase is un-enrolled,
+ * i.e. {@link #STATE_KEYPHRASE_UNENROLLED},
+ * otherwise {@link #createIntentToReEnroll()} should be preferred.
*
- * @param action The manage action that needs to be performed.
- * One of {@link #MANAGE_ACTION_ENROLL}, {@link #MANAGE_ACTION_RE_ENROLL} or
- * {@link #MANAGE_ACTION_UN_ENROLL}.
- * @return An {@link Intent} to manage the given keyphrase.
+ * @return An {@link Intent} to start enrollment for the given keyphrase.
* @throws UnsupportedOperationException if managing they keyphrase isn't supported.
* Callers should only call this method after a supported state callback on
* {@link Callback#onAvailabilityChanged(int)} to avoid this exception.
@@ -443,10 +460,52 @@
* This may happen if another detector has been instantiated or the
* {@link VoiceInteractionService} hosting this detector has been shut down.
*/
- public Intent getManageIntent(@ManageActions int action) {
- if (DBG) Slog.d(TAG, "getManageIntent(" + action + ")");
+ public Intent createIntentToEnroll() {
+ if (DBG) Slog.d(TAG, "createIntentToEnroll");
synchronized (mLock) {
- return getManageIntentLocked(action);
+ return getManageIntentLocked(MANAGE_ACTION_ENROLL);
+ }
+ }
+
+ /**
+ * Creates an intent to start the un-enrollment for the associated keyphrase.
+ * This intent must be invoked using {@link Activity#startActivityForResult(Intent, int)}.
+ * Starting re-enrollment is only valid if the keyphrase is already enrolled,
+ * i.e. {@link #STATE_KEYPHRASE_ENROLLED}, otherwise invoking this may result in an error.
+ *
+ * @return An {@link Intent} to start un-enrollment for the given keyphrase.
+ * @throws UnsupportedOperationException if managing they keyphrase isn't supported.
+ * Callers should only call this method after a supported state callback on
+ * {@link Callback#onAvailabilityChanged(int)} to avoid this exception.
+ * @throws IllegalStateException if the detector is in an invalid state.
+ * This may happen if another detector has been instantiated or the
+ * {@link VoiceInteractionService} hosting this detector has been shut down.
+ */
+ public Intent createIntentToUnEnroll() {
+ if (DBG) Slog.d(TAG, "createIntentToUnEnroll");
+ synchronized (mLock) {
+ return getManageIntentLocked(MANAGE_ACTION_UN_ENROLL);
+ }
+ }
+
+ /**
+ * Creates an intent to start the re-enrollment for the associated keyphrase.
+ * This intent must be invoked using {@link Activity#startActivityForResult(Intent, int)}.
+ * Starting re-enrollment is only valid if the keyphrase is already enrolled,
+ * i.e. {@link #STATE_KEYPHRASE_ENROLLED}, otherwise invoking this may result in an error.
+ *
+ * @return An {@link Intent} to start re-enrollment for the given keyphrase.
+ * @throws UnsupportedOperationException if managing they keyphrase isn't supported.
+ * Callers should only call this method after a supported state callback on
+ * {@link Callback#onAvailabilityChanged(int)} to avoid this exception.
+ * @throws IllegalStateException if the detector is in an invalid state.
+ * This may happen if another detector has been instantiated or the
+ * {@link VoiceInteractionService} hosting this detector has been shut down.
+ */
+ public Intent createIntentToReEnroll() {
+ if (DBG) Slog.d(TAG, "createIntentToReEnroll");
+ synchronized (mLock) {
+ return getManageIntentLocked(MANAGE_ACTION_RE_ENROLL);
}
}
@@ -462,12 +521,6 @@
"Managing the given keyphrase is not supported");
}
- if (action != MANAGE_ACTION_ENROLL
- && action != MANAGE_ACTION_RE_ENROLL
- && action != MANAGE_ACTION_UN_ENROLL) {
- throw new IllegalArgumentException("Invalid action specified " + action);
- }
-
return mKeyphraseEnrollmentInfo.getManageKeyphraseIntent(action, mText, mLocale);
}
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index 818efaa..ece8aa4 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -244,6 +244,16 @@
// Set the default context, since setPopupTheme() may be a no-op.
mPopupContext = mContext;
setPopupTheme(a.getResourceId(R.styleable.Toolbar_popupTheme, 0));
+
+ final Drawable navIcon = a.getDrawable(R.styleable.Toolbar_navigationIcon);
+ if (navIcon != null) {
+ setNavigationIcon(navIcon);
+ final CharSequence navDesc = a.getText(
+ R.styleable.Toolbar_navigationContentDescription);
+ if (!TextUtils.isEmpty(navDesc)) {
+ setNavigationContentDescription(navDesc);
+ }
+ }
a.recycle();
}
@@ -669,6 +679,8 @@
* as screen readers or tooltips.
*
* @return The navigation button's content description
+ *
+ * @attr ref android.R.styleable#Toolbar_navigationContentDescription
*/
@Nullable
public CharSequence getNavigationContentDescription() {
@@ -682,6 +694,8 @@
*
* @param resId Resource ID of a content description string to set, or 0 to
* clear the description
+ *
+ * @attr ref android.R.styleable#Toolbar_navigationContentDescription
*/
public void setNavigationContentDescription(int resId) {
setNavigationContentDescription(resId != 0 ? getContext().getText(resId) : null);
@@ -694,6 +708,8 @@
*
* @param description Content description to set, or <code>null</code> to
* clear the content description
+ *
+ * @attr ref android.R.styleable#Toolbar_navigationContentDescription
*/
public void setNavigationContentDescription(@Nullable CharSequence description) {
if (!TextUtils.isEmpty(description)) {
@@ -715,6 +731,8 @@
* tooltips.</p>
*
* @param resId Resource ID of a drawable to set
+ *
+ * @attr ref android.R.styleable#Toolbar_navigationIcon
*/
public void setNavigationIcon(int resId) {
setNavigationIcon(getContext().getDrawable(resId));
@@ -731,6 +749,8 @@
* tooltips.</p>
*
* @param icon Drawable to set, may be null to clear the icon
+ *
+ * @attr ref android.R.styleable#Toolbar_navigationIcon
*/
public void setNavigationIcon(@Nullable Drawable icon) {
if (icon != null) {
@@ -751,6 +771,8 @@
* Return the current drawable used as the navigation icon.
*
* @return The navigation icon drawable
+ *
+ * @attr ref android.R.styleable#Toolbar_navigationIcon
*/
@Nullable
public Drawable getNavigationIcon() {
@@ -1316,6 +1338,8 @@
final View bottomChild = layoutSubtitle ? mSubtitleTextView : mTitleTextView;
final LayoutParams toplp = (LayoutParams) topChild.getLayoutParams();
final LayoutParams bottomlp = (LayoutParams) bottomChild.getLayoutParams();
+ final boolean titleHasWidth = layoutTitle && mTitleTextView.getMeasuredWidth() > 0
+ || layoutSubtitle && mSubtitleTextView.getMeasuredWidth() > 0;
switch (mGravity & Gravity.VERTICAL_GRAVITY_MASK) {
case Gravity.TOP:
@@ -1343,7 +1367,7 @@
break;
}
if (isRtl) {
- final int rd = mTitleMarginStart - collapsingMargins[1];
+ final int rd = (titleHasWidth ? mTitleMarginStart : 0) - collapsingMargins[1];
right -= Math.max(0, rd);
collapsingMargins[1] = Math.max(0, -rd);
int titleRight = right;
@@ -1366,9 +1390,11 @@
subtitleRight = subtitleRight - mTitleMarginEnd;
titleTop = subtitleBottom + lp.bottomMargin;
}
- right = Math.min(titleRight, subtitleRight);
+ if (titleHasWidth) {
+ right = Math.min(titleRight, subtitleRight);
+ }
} else {
- final int ld = mTitleMarginStart - collapsingMargins[0];
+ final int ld = (titleHasWidth ? mTitleMarginStart : 0) - collapsingMargins[0];
left += Math.max(0, ld);
collapsingMargins[0] = Math.max(0, -ld);
int titleLeft = left;
@@ -1391,7 +1417,9 @@
subtitleLeft = subtitleRight + mTitleMarginEnd;
titleTop = subtitleBottom + lp.bottomMargin;
}
- left = Math.max(titleLeft, subtitleLeft);
+ if (titleHasWidth) {
+ left = Math.max(titleLeft, subtitleLeft);
+ }
}
}
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 9da116a..a798d2e 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -7318,6 +7318,12 @@
<!-- Reference to a theme that should be used to inflate popups
shown by widgets in the toolbar. -->
<attr name="popupTheme" format="reference" />
+ <!-- Icon drawable to use for the navigation button located at
+ the start of the toolbar. -->
+ <attr name="navigationIcon" format="reference" />
+ <!-- Text to set as the content description for the navigation button
+ located at the start of the toolbar. -->
+ <attr name="navigationContentDescription" format="string" />
</declare-styleable>
<declare-styleable name="Toolbar_LayoutParams">
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 3b49bed..d452739 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2280,6 +2280,8 @@
<public type="attr" name="reparentWithOverlay" />
<public type="attr" name="ambientShadowAlpha" />
<public type="attr" name="spotShadowAlpha" />
+ <public type="attr" name="navigationIcon" />
+ <public type="attr" name="navigationContentDescription" />
<public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 90879dd..690b1d6 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -2939,7 +2939,7 @@
for (size_t i = 0; i < bags->size(); i++) {
TABLE_NOISY(printf("type=%d\n", i));
const TypeList& typeList = types[i];
- if (typeList.isEmpty()) {
+ if (!typeList.isEmpty()) {
bag_set** typeBags = bags->get(i);
TABLE_NOISY(printf("typeBags=%p\n", typeBags));
if (typeBags) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index 827b3ed..bb22b4d 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -23,6 +23,7 @@
import android.util.Slog;
import android.util.SparseArray;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Predicate;
import com.android.server.hdmi.HdmiAnnotations.IoThreadOnly;
import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
@@ -30,6 +31,8 @@
import libcore.util.EmptyArray;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
@@ -446,7 +449,7 @@
allocated.add(address);
}
}
- mIoThreadLogger.debug("DevicePollingResult:" + allocated);
+ mIoThreadLogger.debug("[P]:Allocated Address=" + allocated);
if (callback != null) {
runOnServiceThread(new Runnable() {
@Override
@@ -548,7 +551,7 @@
runOnIoThread(new Runnable() {
@Override
public void run() {
- mIoThreadLogger.debug("SendCommand:" + cecMessage);
+ mIoThreadLogger.debug("[S]:" + cecMessage);
byte[] body = buildBody(cecMessage.getOpcode(), cecMessage.getParams());
int i = 0;
int errorCode = Constants.SEND_RESULT_SUCCESS;
@@ -583,7 +586,7 @@
private void handleIncomingCecCommand(int srcAddress, int dstAddress, byte[] body) {
assertRunOnServiceThread();
HdmiCecMessage command = HdmiCecMessageBuilder.of(srcAddress, dstAddress, body);
- mServiceThreadLogger.debug("ReceiveCommand:" + command);
+ mServiceThreadLogger.debug("[R]:" + command);
onReceiveCommand(command);
}
@@ -598,6 +601,15 @@
mService.onHotplug(port, connected);
}
+ void dump(final IndentingPrintWriter pw) {
+ for (int i = 0; i < mLocalDevices.size(); ++i) {
+ pw.println("HdmiCecLocalDevice #" + i + ":");
+ pw.increaseIndent();
+ mLocalDevices.valueAt(i).dump(pw);
+ pw.decreaseIndent();
+ }
+ }
+
private static native long nativeInit(HdmiCecController handler, MessageQueue messageQueue);
private static native int nativeSendCecCommand(long controllerPtr, int srcAddress,
int dstAddress, byte[] body);
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java b/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java
index 26d2cde..85f5be2 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java
@@ -43,6 +43,9 @@
*/
abstract class HdmiCecFeatureAction {
private static final String TAG = "HdmiCecFeatureAction";
+ // As all actions run in the same thread (service thread), it's fine to have single logger.
+ // TODO: create global logger for each threads and use them.
+ protected static final HdmiLogger DLOGGER = new HdmiLogger(TAG);
// Timer handler message used for timeout event
protected static final int MSG_TIMEOUT = 100;
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index a12e4fc..38addba 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -28,6 +28,7 @@
import android.view.KeyEvent;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
import java.util.ArrayList;
@@ -97,6 +98,17 @@
public int hashCode() {
return logicalAddress * 29 + physicalAddress;
}
+ @Override
+ public String toString() {
+ StringBuffer s = new StringBuffer();
+ String logicalAddressString = (logicalAddress == Constants.ADDR_INVALID)
+ ? "invalid" : String.format("0x%02x", logicalAddress);
+ s.append("logical_address: ").append(logicalAddressString);
+ String physicalAddressString = (physicalAddress == Constants.INVALID_PHYSICAL_ADDRESS)
+ ? "invalid" : String.format("0x%04x", physicalAddress);
+ s.append(", physical_address: ").append(physicalAddressString);
+ return s.toString();
+ }
}
// Logical address of the active source.
@GuardedBy("mLock")
@@ -793,4 +805,16 @@
protected void sendKeyEvent(int keyCode, boolean isPressed) {
Slog.w(TAG, "sendKeyEvent not implemented");
}
+
+ /**
+ * Dump internal status of HdmiCecLocalDevice object.
+ */
+ protected void dump(final IndentingPrintWriter pw) {
+ pw.println("mDeviceType: " + mDeviceType);
+ pw.println("mAddress: " + mAddress);
+ pw.println("mPreferredAddress: " + mPreferredAddress);
+ pw.println("mDeviceInfo: " + mDeviceInfo);
+ pw.println("mActiveSource: " + mActiveSource);
+ pw.println(String.format("mActiveRoutingPath: 0x%04x", mActiveRoutingPath));
+ }
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index 5a2fa9c..6603a71 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -23,6 +23,7 @@
import android.os.SystemProperties;
import android.util.Slog;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
/**
@@ -219,4 +220,10 @@
mIsActiveSource = false;
checkIfPendingActionsCleared();
}
+
+ @Override
+ protected void dump(final IndentingPrintWriter pw) {
+ super.dump(pw);
+ pw.println("mIsActiveSource: " + mIsActiveSource);
+ }
}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index cd56cfc..1ab8069 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -45,6 +45,7 @@
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.server.hdmi.DeviceDiscoveryAction.DeviceDiscoveryCallback;
import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
import com.android.server.hdmi.HdmiControlService.SendMessageCallback;
@@ -1610,4 +1611,16 @@
invokeDeviceEventListener(newInfo, HdmiControlManager.DEVICE_EVENT_UPDATE_DEVICE);
}
+
+ @Override
+ protected void dump(final IndentingPrintWriter pw) {
+ super.dump(pw);
+ pw.println("mArcEstablished: " + mArcEstablished);
+ pw.println("mArcFeatureEnabled: " + mArcFeatureEnabled);
+ pw.println("mSystemAudioActivated: " + mSystemAudioActivated);
+ pw.println("mSystemAudioMute: " + mSystemAudioMute);
+ pw.println("mAutoDeviceOff: " + mAutoDeviceOff);
+ pw.println("mAutoWakeup: " + mAutoWakeup);
+ pw.println("mSkipRoutingControl: " + mSkipRoutingControl);
+ }
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index e7b920a..d13e1de 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -67,6 +67,7 @@
import android.util.SparseIntArray;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.server.SystemService;
import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
import com.android.server.hdmi.HdmiCecController.AllocateAddressCallback;
@@ -75,6 +76,8 @@
import libcore.util.EmptyArray;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -1395,6 +1398,28 @@
enforceAccessPermission();
HdmiControlService.this.addHdmiMhlScratchpadCommandListener(listener);
}
+
+ @Override
+ protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) {
+ getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+ final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
+
+ pw.println("mHdmiControlEnabled: " + mHdmiControlEnabled);
+ pw.println("mProhibitMode: " + mProhibitMode);
+ if (mCecController != null) {
+ pw.println("mCecController: ");
+ pw.increaseIndent();
+ mCecController.dump(pw);
+ pw.decreaseIndent();
+ }
+ pw.println("mPortInfo: ");
+ pw.increaseIndent();
+ for (HdmiPortInfo hdmiPortInfo : mPortInfo) {
+ pw.println("- " + hdmiPortInfo);
+ }
+ pw.decreaseIndent();
+ pw.println("mPowerStatus: " + mPowerStatus);
+ }
}
@ServiceThreadOnly
diff --git a/services/core/java/com/android/server/hdmi/HdmiLogger.java b/services/core/java/com/android/server/hdmi/HdmiLogger.java
index ee9379d..c7add75 100644
--- a/services/core/java/com/android/server/hdmi/HdmiLogger.java
+++ b/services/core/java/com/android/server/hdmi/HdmiLogger.java
@@ -42,7 +42,7 @@
private final String mTag;
HdmiLogger(String tag) {
- mTag = tag;
+ mTag = "HDMI:" + tag;
}
void warning(String logMessage) {
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioAction.java b/services/core/java/com/android/server/hdmi/SystemAudioAction.java
index ac2c7b9..d15ffb0 100644
--- a/services/core/java/com/android/server/hdmi/SystemAudioAction.java
+++ b/services/core/java/com/android/server/hdmi/SystemAudioAction.java
@@ -73,9 +73,9 @@
// Seq #27
protected void sendSystemAudioModeRequest() {
- mState = STATE_CHECK_ROUTING_IN_PRGRESS;
List<RoutingControlAction> routingActions = getActions(RoutingControlAction.class);
if (!routingActions.isEmpty()) {
+ mState = STATE_CHECK_ROUTING_IN_PRGRESS;
// Should have only one Routing Control Action
RoutingControlAction routingAction = routingActions.get(0);
routingAction.addOnFinishedCallback(this, new Runnable() {
@@ -97,20 +97,21 @@
sendCommand(command, new HdmiControlService.SendMessageCallback() {
@Override
public void onSendCompleted(int error) {
- if (error == Constants.SEND_RESULT_SUCCESS) {
- mState = STATE_WAIT_FOR_SET_SYSTEM_AUDIO_MODE;
- addTimer(mState, mTargetAudioStatus ? ON_TIMEOUT_MS : OFF_TIMEOUT_MS);
- } else {
+ if (error != Constants.SEND_RESULT_SUCCESS) {
+ DLOGGER.debug("Failed to send <System Audio Mode Request>:" + error);
setSystemAudioMode(false);
finishWithCallback(HdmiControlManager.RESULT_COMMUNICATION_FAILED);
}
}
});
+ mState = STATE_WAIT_FOR_SET_SYSTEM_AUDIO_MODE;
+ addTimer(mState, mTargetAudioStatus ? ON_TIMEOUT_MS : OFF_TIMEOUT_MS);
}
private void handleSendSystemAudioModeRequestTimeout() {
if (!mTargetAudioStatus // Don't retry for Off case.
|| mSendRetryCount++ >= MAX_SEND_RETRY_COUNT) {
+ DLOGGER.debug("[T]:wait for <Set System Audio Mode>.");
setSystemAudioMode(false);
finishWithCallback(HdmiControlManager.RESULT_TIMEOUT);
return;
@@ -129,6 +130,7 @@
if (cmd.getOpcode() == Constants.MESSAGE_FEATURE_ABORT
&& (cmd.getParams()[0] & 0xFF)
== Constants.MESSAGE_SYSTEM_AUDIO_MODE_REQUEST) {
+ DLOGGER.debug("Failed to start system audio mode request.");
setSystemAudioMode(false);
finishWithCallback(HdmiControlManager.RESULT_EXCEPTION);
return true;
@@ -143,6 +145,7 @@
startAudioStatusAction();
return true;
} else {
+ DLOGGER.debug("Unexpected system audio mode request:" + receivedStatus);
// Unexpected response, consider the request is newly initiated by AVR.
// To return 'false' will initiate new SystemAudioActionFromAvr by the control
// service.
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
index e1a579c..1f01461 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
@@ -92,8 +92,7 @@
break;
case AlwaysOnHotwordDetector.STATE_KEYPHRASE_UNENROLLED:
Log.i(TAG, "STATE_KEYPHRASE_UNENROLLED");
- Intent enroll = mHotwordDetector.getManageIntent(
- AlwaysOnHotwordDetector.MANAGE_ACTION_ENROLL);
+ Intent enroll = mHotwordDetector.createIntentToEnroll();
Log.i(TAG, "Need to enroll with " + enroll);
break;
case AlwaysOnHotwordDetector.STATE_KEYPHRASE_ENROLLED: