blob: fb1a90252328e592f5461b74517ac76c91898d48 [file] [log] [blame]
/*
* Copyright (C) 2009 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.polo.pairing.message;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* Object implementing the internal representation of the protocol message
* 'OPTIONS'.
*/
public class OptionsMessage extends PoloMessage {
/**
* Representation of a specific role type. The numeric values
* should be kept synchronized with the constants defined by
* Options.Encoding.EncodingType in polo.proto.
*/
public static enum ProtocolRole {
UNKNOWN(0),
INPUT_DEVICE(1),
DISPLAY_DEVICE(2);
private final int mIntVal;
private ProtocolRole(int intVal) {
mIntVal = intVal;
}
public static ProtocolRole fromIntVal(int intVal) {
for (ProtocolRole role : ProtocolRole.values()) {
if (role.getAsInt() == intVal) {
return role;
}
}
return ProtocolRole.UNKNOWN;
}
public int getAsInt() {
return mIntVal;
}
}
/**
* The preferred protocol role of the sender.
*/
private ProtocolRole mProtocolRolePreference;
/**
* Sender's supported input encodings.
*/
private Set<EncodingOption> mInputEncodings;
/**
* Sender's supported output encodings.
*/
private Set<EncodingOption> mOutputEncodings;
public OptionsMessage() {
super(PoloMessage.PoloMessageType.OPTIONS);
mProtocolRolePreference = ProtocolRole.UNKNOWN;
mInputEncodings = new HashSet<EncodingOption>();
mOutputEncodings = new HashSet<EncodingOption>();
}
public void setProtocolRolePreference(ProtocolRole pref) {
mProtocolRolePreference = pref;
}
public ProtocolRole getProtocolRolePreference() {
return mProtocolRolePreference;
}
public void addInputEncoding(EncodingOption encoding) {
mInputEncodings.add(encoding);
}
public void addOutputEncoding(EncodingOption encoding) {
mOutputEncodings.add(encoding);
}
public boolean supportsInputEncoding(EncodingOption encoding) {
return mInputEncodings.contains(encoding);
}
public boolean supportsOutputEncoding(EncodingOption encoding) {
return mOutputEncodings.contains(encoding);
}
public Set<EncodingOption> getInputEncodingSet() {
return new HashSet<EncodingOption>(mInputEncodings);
}
public Set<EncodingOption> getOutputEncodingSet() {
return new HashSet<EncodingOption>(mOutputEncodings);
}
/**
* Generates a ConfigurationMessage, or {@code null}, by intersecting the
* local message with another message.
*/
public ConfigurationMessage getBestConfiguration(
OptionsMessage otherOptions) {
Set<EncodingOption> peerOutputs = otherOptions.getOutputEncodingSet();
peerOutputs.retainAll(mInputEncodings);
Set<EncodingOption> peerInputs = otherOptions.getInputEncodingSet();
peerInputs.retainAll(mOutputEncodings);
if (peerOutputs.isEmpty() && peerInputs.isEmpty()) {
// No configuration possible: no common encodings.
return null;
}
EncodingOption encoding;
ProtocolRole role;
EncodingOption bestInput = null;
if (!peerInputs.isEmpty()) {
bestInput = peerInputs.iterator().next();
}
EncodingOption bestOutput = null;
if (!peerOutputs.isEmpty()) {
bestOutput = peerOutputs.iterator().next();
}
if (mProtocolRolePreference == ProtocolRole.DISPLAY_DEVICE) {
// We prefer to be the display device
if (bestInput != null) {
encoding = bestInput;
role = ProtocolRole.DISPLAY_DEVICE;
} else {
encoding = bestOutput;
role = ProtocolRole.INPUT_DEVICE;
}
} else {
// We prefer to be the input device, or have no preference
if (!peerOutputs.isEmpty()) {
encoding = bestOutput;
role = ProtocolRole.INPUT_DEVICE;
} else {
encoding = bestInput;
role = ProtocolRole.DISPLAY_DEVICE;
}
}
return new ConfigurationMessage(encoding, role);
}
@Override
public String toString() {
StringBuilder ret = new StringBuilder();
ret.append("[" + getType() + " ");
ret.append("inputs=");
Iterator<EncodingOption> inputIterator = mInputEncodings.iterator();
while (inputIterator.hasNext()) {
ret.append(inputIterator.next());
if (inputIterator.hasNext()) {
ret.append(",");
}
}
ret.append(" outputs=");
Iterator<EncodingOption> outputIterator = mOutputEncodings.iterator();
while (outputIterator.hasNext()) {
ret.append(outputIterator.next());
if (outputIterator.hasNext()) {
ret.append(",");
}
}
ret.append(" pref=" + mProtocolRolePreference);
ret.append("]");
return ret.toString();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof OptionsMessage)) {
return false;
}
OptionsMessage other = (OptionsMessage) obj;
if (mProtocolRolePreference == null) {
if (other.mProtocolRolePreference != null) {
return false;
}
} else if (!mProtocolRolePreference.equals(other.mProtocolRolePreference)) {
return false;
}
return mInputEncodings.equals(other.mInputEncodings) &&
mOutputEncodings.equals(other.mOutputEncodings);
}
}