| /* |
| * 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); |
| } |
| |
| } |