1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 18 package android.filterfw.core; 19 20 import android.annotation.UnsupportedAppUsage; 21 import android.filterfw.core.FilterContext; 22 import android.filterfw.core.FilterPort; 23 import android.filterfw.core.KeyValueMap; 24 import android.filterfw.io.TextGraphReader; 25 import android.filterfw.io.GraphIOException; 26 import android.filterfw.format.ObjectFormat; 27 import android.util.Log; 28 29 import java.io.Serializable; 30 import java.lang.annotation.Annotation; 31 import java.lang.reflect.Field; 32 import java.lang.Thread; 33 import java.util.Collection; 34 import java.util.HashMap; 35 import java.util.HashSet; 36 import java.util.Map.Entry; 37 import java.util.Set; 38 39 /** 40 * @hide 41 */ 42 public abstract class Filter { 43 44 static final int STATUS_PREINIT = 0; 45 static final int STATUS_UNPREPARED = 1; 46 static final int STATUS_PREPARED = 2; 47 static final int STATUS_PROCESSING = 3; 48 static final int STATUS_SLEEPING = 4; 49 static final int STATUS_FINISHED = 5; 50 static final int STATUS_ERROR = 6; 51 static final int STATUS_RELEASED = 7; 52 53 private String mName; 54 55 private int mInputCount = -1; 56 private int mOutputCount = -1; 57 58 private HashMap<String, InputPort> mInputPorts; 59 private HashMap<String, OutputPort> mOutputPorts; 60 61 private HashSet<Frame> mFramesToRelease; 62 private HashMap<String, Frame> mFramesToSet; 63 64 private int mStatus = 0; 65 private boolean mIsOpen = false; 66 private int mSleepDelay; 67 68 private long mCurrentTimestamp; 69 70 private boolean mLogVerbose; 71 private static final String TAG = "Filter"; 72 73 @UnsupportedAppUsage Filter(String name)74 public Filter(String name) { 75 mName = name; 76 mFramesToRelease = new HashSet<Frame>(); 77 mFramesToSet = new HashMap<String, Frame>(); 78 mStatus = STATUS_PREINIT; 79 80 mLogVerbose = Log.isLoggable(TAG, Log.VERBOSE); 81 } 82 83 /** Tests to see if a given filter is installed on the system. Requires 84 * full filter package name, including filterpack. 85 */ 86 @UnsupportedAppUsage isAvailable(String filterName)87 public static final boolean isAvailable(String filterName) { 88 ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); 89 Class filterClass; 90 // First see if a class of that name exists 91 try { 92 filterClass = contextClassLoader.loadClass(filterName); 93 } catch (ClassNotFoundException e) { 94 return false; 95 } 96 // Then make sure it's a subclass of Filter. 97 try { 98 filterClass.asSubclass(Filter.class); 99 } catch (ClassCastException e) { 100 return false; 101 } 102 return true; 103 } 104 initWithValueMap(KeyValueMap valueMap)105 public final void initWithValueMap(KeyValueMap valueMap) { 106 // Initialization 107 initFinalPorts(valueMap); 108 109 // Setup remaining ports 110 initRemainingPorts(valueMap); 111 112 // This indicates that final ports can no longer be set 113 mStatus = STATUS_UNPREPARED; 114 } 115 initWithAssignmentString(String assignments)116 public final void initWithAssignmentString(String assignments) { 117 try { 118 KeyValueMap valueMap = new TextGraphReader().readKeyValueAssignments(assignments); 119 initWithValueMap(valueMap); 120 } catch (GraphIOException e) { 121 throw new IllegalArgumentException(e.getMessage()); 122 } 123 } 124 initWithAssignmentList(Object... keyValues)125 public final void initWithAssignmentList(Object... keyValues) { 126 KeyValueMap valueMap = new KeyValueMap(); 127 valueMap.setKeyValues(keyValues); 128 initWithValueMap(valueMap); 129 } 130 init()131 public final void init() throws ProtocolException { 132 KeyValueMap valueMap = new KeyValueMap(); 133 initWithValueMap(valueMap); 134 } 135 getFilterClassName()136 public String getFilterClassName() { 137 return getClass().getSimpleName(); 138 } 139 getName()140 public final String getName() { 141 return mName; 142 } 143 isOpen()144 public boolean isOpen() { 145 return mIsOpen; 146 } 147 setInputFrame(String inputName, Frame frame)148 public void setInputFrame(String inputName, Frame frame) { 149 FilterPort port = getInputPort(inputName); 150 if (!port.isOpen()) { 151 port.open(); 152 } 153 port.setFrame(frame); 154 } 155 156 @UnsupportedAppUsage setInputValue(String inputName, Object value)157 public final void setInputValue(String inputName, Object value) { 158 setInputFrame(inputName, wrapInputValue(inputName, value)); 159 } 160 prepare(FilterContext context)161 protected void prepare(FilterContext context) { 162 } 163 parametersUpdated(Set<String> updated)164 protected void parametersUpdated(Set<String> updated) { 165 } 166 delayNextProcess(int millisecs)167 protected void delayNextProcess(int millisecs) { 168 mSleepDelay = millisecs; 169 mStatus = STATUS_SLEEPING; 170 } 171 setupPorts()172 public abstract void setupPorts(); 173 getOutputFormat(String portName, FrameFormat inputFormat)174 public FrameFormat getOutputFormat(String portName, FrameFormat inputFormat) { 175 return null; 176 } 177 getInputFormat(String portName)178 public final FrameFormat getInputFormat(String portName) { 179 InputPort inputPort = getInputPort(portName); 180 return inputPort.getSourceFormat(); 181 } 182 open(FilterContext context)183 public void open(FilterContext context) { 184 } 185 process(FilterContext context)186 public abstract void process(FilterContext context); 187 getSleepDelay()188 public final int getSleepDelay() { 189 return 250; 190 } 191 close(FilterContext context)192 public void close(FilterContext context) { 193 } 194 tearDown(FilterContext context)195 public void tearDown(FilterContext context) { 196 } 197 getNumberOfConnectedInputs()198 public final int getNumberOfConnectedInputs() { 199 int c = 0; 200 for (InputPort inputPort : mInputPorts.values()) { 201 if (inputPort.isConnected()) { 202 ++c; 203 } 204 } 205 return c; 206 } 207 getNumberOfConnectedOutputs()208 public final int getNumberOfConnectedOutputs() { 209 int c = 0; 210 for (OutputPort outputPort : mOutputPorts.values()) { 211 if (outputPort.isConnected()) { 212 ++c; 213 } 214 } 215 return c; 216 } 217 getNumberOfInputs()218 public final int getNumberOfInputs() { 219 return mOutputPorts == null ? 0 : mInputPorts.size(); 220 } 221 getNumberOfOutputs()222 public final int getNumberOfOutputs() { 223 return mInputPorts == null ? 0 : mOutputPorts.size(); 224 } 225 getInputPort(String portName)226 public final InputPort getInputPort(String portName) { 227 if (mInputPorts == null) { 228 throw new NullPointerException("Attempting to access input port '" + portName 229 + "' of " + this + " before Filter has been initialized!"); 230 } 231 InputPort result = mInputPorts.get(portName); 232 if (result == null) { 233 throw new IllegalArgumentException("Unknown input port '" + portName + "' on filter " 234 + this + "!"); 235 } 236 return result; 237 } 238 getOutputPort(String portName)239 public final OutputPort getOutputPort(String portName) { 240 if (mInputPorts == null) { 241 throw new NullPointerException("Attempting to access output port '" + portName 242 + "' of " + this + " before Filter has been initialized!"); 243 } 244 OutputPort result = mOutputPorts.get(portName); 245 if (result == null) { 246 throw new IllegalArgumentException("Unknown output port '" + portName + "' on filter " 247 + this + "!"); 248 } 249 return result; 250 } 251 pushOutput(String name, Frame frame)252 protected final void pushOutput(String name, Frame frame) { 253 if (frame.getTimestamp() == Frame.TIMESTAMP_NOT_SET) { 254 if (mLogVerbose) Log.v(TAG, "Default-setting output Frame timestamp on port " + name + " to " + mCurrentTimestamp); 255 frame.setTimestamp(mCurrentTimestamp); 256 } 257 getOutputPort(name).pushFrame(frame); 258 } 259 pullInput(String name)260 protected final Frame pullInput(String name) { 261 Frame result = getInputPort(name).pullFrame(); 262 if (mCurrentTimestamp == Frame.TIMESTAMP_UNKNOWN) { 263 mCurrentTimestamp = result.getTimestamp(); 264 if (mLogVerbose) Log.v(TAG, "Default-setting current timestamp from input port " + name + " to " + mCurrentTimestamp); 265 } 266 // As result is retained, we add it to the release pool here 267 mFramesToRelease.add(result); 268 269 return result; 270 } 271 fieldPortValueUpdated(String name, FilterContext context)272 public void fieldPortValueUpdated(String name, FilterContext context) { 273 } 274 275 /** 276 * Transfers any frame from an input port to its destination. This is useful to force a 277 * transfer from a FieldPort or ProgramPort to its connected target (field or program variable). 278 */ transferInputPortFrame(String name, FilterContext context)279 protected void transferInputPortFrame(String name, FilterContext context) { 280 getInputPort(name).transfer(context); 281 } 282 283 /** 284 * Assigns all program variables to the ports they are connected to. Call this after 285 * constructing a Program instance with attached ProgramPorts. 286 */ initProgramInputs(Program program, FilterContext context)287 protected void initProgramInputs(Program program, FilterContext context) { 288 if (program != null) { 289 for (InputPort inputPort : mInputPorts.values()) { 290 if (inputPort.getTarget() == program) { 291 inputPort.transfer(context); 292 } 293 } 294 } 295 } 296 297 /** 298 * Adds an input port to the filter. You should call this from within setupPorts, if your 299 * filter has input ports. No type-checking is performed on the input. If you would like to 300 * check against a type mask, use 301 * {@link #addMaskedInputPort(String, FrameFormat) addMaskedInputPort} instead. 302 * 303 * @param name the name of the input port 304 */ addInputPort(String name)305 protected void addInputPort(String name) { 306 addMaskedInputPort(name, null); 307 } 308 309 /** 310 * Adds an input port to the filter. You should call this from within setupPorts, if your 311 * filter has input ports. When type-checking is performed, the input format is 312 * checked against the provided format mask. An exception is thrown in case of a conflict. 313 * 314 * @param name the name of the input port 315 * @param formatMask a format mask, which filters the allowable input types 316 */ addMaskedInputPort(String name, FrameFormat formatMask)317 protected void addMaskedInputPort(String name, FrameFormat formatMask) { 318 InputPort port = new StreamPort(this, name); 319 if (mLogVerbose) Log.v(TAG, "Filter " + this + " adding " + port); 320 mInputPorts.put(name, port); 321 port.setPortFormat(formatMask); 322 } 323 324 /** 325 * Adds an output port to the filter with a fixed output format. You should call this from 326 * within setupPorts, if your filter has output ports. You cannot use this method, if your 327 * output format depends on the input format (e.g. in a pass-through filter). In this case, use 328 * {@link #addOutputBasedOnInput(String, String) addOutputBasedOnInput} instead. 329 * 330 * @param name the name of the output port 331 * @param format the fixed output format of this port 332 */ addOutputPort(String name, FrameFormat format)333 protected void addOutputPort(String name, FrameFormat format) { 334 OutputPort port = new OutputPort(this, name); 335 if (mLogVerbose) Log.v(TAG, "Filter " + this + " adding " + port); 336 port.setPortFormat(format); 337 mOutputPorts.put(name, port); 338 } 339 340 /** 341 * Adds an output port to the filter. You should call this from within setupPorts, if your 342 * filter has output ports. Using this method indicates that the output format for this 343 * particular port, depends on the format of an input port. You MUST also override 344 * {@link #getOutputFormat(String, FrameFormat) getOutputFormat} to specify what format your 345 * filter will output for a given input. If the output format of your filter port does not 346 * depend on the input, use {@link #addOutputPort(String, FrameFormat) addOutputPort} instead. 347 * 348 * @param outputName the name of the output port 349 * @param inputName the name of the input port, that this output depends on 350 */ addOutputBasedOnInput(String outputName, String inputName)351 protected void addOutputBasedOnInput(String outputName, String inputName) { 352 OutputPort port = new OutputPort(this, outputName); 353 if (mLogVerbose) Log.v(TAG, "Filter " + this + " adding " + port); 354 port.setBasePort(getInputPort(inputName)); 355 mOutputPorts.put(outputName, port); 356 } 357 addFieldPort(String name, Field field, boolean hasDefault, boolean isFinal)358 protected void addFieldPort(String name, 359 Field field, 360 boolean hasDefault, 361 boolean isFinal) { 362 // Make sure field is accessible 363 field.setAccessible(true); 364 365 // Create port for this input 366 InputPort fieldPort = isFinal 367 ? new FinalPort(this, name, field, hasDefault) 368 : new FieldPort(this, name, field, hasDefault); 369 370 // Create format for this input 371 if (mLogVerbose) Log.v(TAG, "Filter " + this + " adding " + fieldPort); 372 MutableFrameFormat format = ObjectFormat.fromClass(field.getType(), 373 FrameFormat.TARGET_SIMPLE); 374 fieldPort.setPortFormat(format); 375 376 // Add port 377 mInputPorts.put(name, fieldPort); 378 } 379 addProgramPort(String name, String varName, Field field, Class varType, boolean hasDefault)380 protected void addProgramPort(String name, 381 String varName, 382 Field field, 383 Class varType, 384 boolean hasDefault) { 385 // Make sure field is accessible 386 field.setAccessible(true); 387 388 // Create port for this input 389 InputPort programPort = new ProgramPort(this, name, varName, field, hasDefault); 390 391 // Create format for this input 392 if (mLogVerbose) Log.v(TAG, "Filter " + this + " adding " + programPort); 393 MutableFrameFormat format = ObjectFormat.fromClass(varType, 394 FrameFormat.TARGET_SIMPLE); 395 programPort.setPortFormat(format); 396 397 // Add port 398 mInputPorts.put(name, programPort); 399 } 400 closeOutputPort(String name)401 protected void closeOutputPort(String name) { 402 getOutputPort(name).close(); 403 } 404 405 /** 406 * Specifies whether the filter should not be scheduled until a frame is available on that 407 * input port. Note, that setting this to false, does not block a new frame from coming in 408 * (though there is no necessity to pull that frame for processing). 409 * @param portName the name of the input port. 410 * @param waits true, if the filter should wait for a frame on this port. 411 */ setWaitsOnInputPort(String portName, boolean waits)412 protected void setWaitsOnInputPort(String portName, boolean waits) { 413 getInputPort(portName).setBlocking(waits); 414 } 415 416 /** 417 * Specifies whether the filter should not be scheduled until the output port is free, i.e. 418 * there is no frame waiting on that output. 419 * @param portName the name of the output port. 420 * @param waits true, if the filter should wait for the port to become free. 421 */ setWaitsOnOutputPort(String portName, boolean waits)422 protected void setWaitsOnOutputPort(String portName, boolean waits) { 423 getOutputPort(portName).setBlocking(waits); 424 } 425 toString()426 public String toString() { 427 return "'" + getName() + "' (" + getFilterClassName() + ")"; 428 } 429 430 // Core internal methods /////////////////////////////////////////////////////////////////////// getInputPorts()431 final Collection<InputPort> getInputPorts() { 432 return mInputPorts.values(); 433 } 434 getOutputPorts()435 final Collection<OutputPort> getOutputPorts() { 436 return mOutputPorts.values(); 437 } 438 getStatus()439 final synchronized int getStatus() { 440 return mStatus; 441 } 442 unsetStatus(int flag)443 final synchronized void unsetStatus(int flag) { 444 mStatus &= ~flag; 445 } 446 performOpen(FilterContext context)447 final synchronized void performOpen(FilterContext context) { 448 if (!mIsOpen) { 449 if (mStatus == STATUS_UNPREPARED) { 450 if (mLogVerbose) Log.v(TAG, "Preparing " + this); 451 prepare(context); 452 mStatus = STATUS_PREPARED; 453 } 454 if (mStatus == STATUS_PREPARED) { 455 if (mLogVerbose) Log.v(TAG, "Opening " + this); 456 open(context); 457 mStatus = STATUS_PROCESSING; 458 } 459 if (mStatus != STATUS_PROCESSING) { 460 throw new RuntimeException("Filter " + this + " was brought into invalid state during " 461 + "opening (state: " + mStatus + ")!"); 462 } 463 mIsOpen = true; 464 } 465 } 466 performProcess(FilterContext context)467 final synchronized void performProcess(FilterContext context) { 468 if (mStatus == STATUS_RELEASED) { 469 throw new RuntimeException("Filter " + this + " is already torn down!"); 470 } 471 transferInputFrames(context); 472 if (mStatus < STATUS_PROCESSING) { 473 performOpen(context); 474 } 475 if (mLogVerbose) Log.v(TAG, "Processing " + this); 476 mCurrentTimestamp = Frame.TIMESTAMP_UNKNOWN; 477 process(context); 478 releasePulledFrames(context); 479 if (filterMustClose()) { 480 performClose(context); 481 } 482 } 483 performClose(FilterContext context)484 final synchronized void performClose(FilterContext context) { 485 if (mIsOpen) { 486 if (mLogVerbose) Log.v(TAG, "Closing " + this); 487 mIsOpen = false; 488 mStatus = STATUS_PREPARED; 489 close(context); 490 closePorts(); 491 } 492 } 493 performTearDown(FilterContext context)494 final synchronized void performTearDown(FilterContext context) { 495 performClose(context); 496 if (mStatus != STATUS_RELEASED) { 497 tearDown(context); 498 mStatus = STATUS_RELEASED; 499 } 500 } 501 canProcess()502 synchronized final boolean canProcess() { 503 if (mLogVerbose) Log.v(TAG, "Checking if can process: " + this + " (" + mStatus + ")."); 504 if (mStatus <= STATUS_PROCESSING) { 505 return inputConditionsMet() && outputConditionsMet(); 506 } else { 507 return false; 508 } 509 } 510 openOutputs()511 final void openOutputs() { 512 if (mLogVerbose) Log.v(TAG, "Opening all output ports on " + this + "!"); 513 for (OutputPort outputPort : mOutputPorts.values()) { 514 if (!outputPort.isOpen()) { 515 outputPort.open(); 516 } 517 } 518 } 519 clearInputs()520 final void clearInputs() { 521 for (InputPort inputPort : mInputPorts.values()) { 522 inputPort.clear(); 523 } 524 } 525 clearOutputs()526 final void clearOutputs() { 527 for (OutputPort outputPort : mOutputPorts.values()) { 528 outputPort.clear(); 529 } 530 } 531 notifyFieldPortValueUpdated(String name, FilterContext context)532 final void notifyFieldPortValueUpdated(String name, FilterContext context) { 533 if (mStatus == STATUS_PROCESSING || mStatus == STATUS_PREPARED) { 534 fieldPortValueUpdated(name, context); 535 } 536 } 537 pushInputFrame(String inputName, Frame frame)538 final synchronized void pushInputFrame(String inputName, Frame frame) { 539 FilterPort port = getInputPort(inputName); 540 if (!port.isOpen()) { 541 port.open(); 542 } 543 port.pushFrame(frame); 544 } 545 pushInputValue(String inputName, Object value)546 final synchronized void pushInputValue(String inputName, Object value) { 547 pushInputFrame(inputName, wrapInputValue(inputName, value)); 548 } 549 550 // Filter internal methods ///////////////////////////////////////////////////////////////////// initFinalPorts(KeyValueMap values)551 private final void initFinalPorts(KeyValueMap values) { 552 mInputPorts = new HashMap<String, InputPort>(); 553 mOutputPorts = new HashMap<String, OutputPort>(); 554 addAndSetFinalPorts(values); 555 } 556 initRemainingPorts(KeyValueMap values)557 private final void initRemainingPorts(KeyValueMap values) { 558 addAnnotatedPorts(); 559 setupPorts(); // TODO: rename to addFilterPorts() ? 560 setInitialInputValues(values); 561 } 562 addAndSetFinalPorts(KeyValueMap values)563 private final void addAndSetFinalPorts(KeyValueMap values) { 564 Class filterClass = getClass(); 565 Annotation annotation; 566 for (Field field : filterClass.getDeclaredFields()) { 567 if ((annotation = field.getAnnotation(GenerateFinalPort.class)) != null) { 568 GenerateFinalPort generator = (GenerateFinalPort)annotation; 569 String name = generator.name().isEmpty() ? field.getName() : generator.name(); 570 boolean hasDefault = generator.hasDefault(); 571 addFieldPort(name, field, hasDefault, true); 572 if (values.containsKey(name)) { 573 setImmediateInputValue(name, values.get(name)); 574 values.remove(name); 575 } else if (!generator.hasDefault()) { 576 throw new RuntimeException("No value specified for final input port '" 577 + name + "' of filter " + this + "!"); 578 } 579 } 580 } 581 } 582 addAnnotatedPorts()583 private final void addAnnotatedPorts() { 584 Class filterClass = getClass(); 585 Annotation annotation; 586 for (Field field : filterClass.getDeclaredFields()) { 587 if ((annotation = field.getAnnotation(GenerateFieldPort.class)) != null) { 588 GenerateFieldPort generator = (GenerateFieldPort)annotation; 589 addFieldGenerator(generator, field); 590 } else if ((annotation = field.getAnnotation(GenerateProgramPort.class)) != null) { 591 GenerateProgramPort generator = (GenerateProgramPort)annotation; 592 addProgramGenerator(generator, field); 593 } else if ((annotation = field.getAnnotation(GenerateProgramPorts.class)) != null) { 594 GenerateProgramPorts generators = (GenerateProgramPorts)annotation; 595 for (GenerateProgramPort generator : generators.value()) { 596 addProgramGenerator(generator, field); 597 } 598 } 599 } 600 } 601 addFieldGenerator(GenerateFieldPort generator, Field field)602 private final void addFieldGenerator(GenerateFieldPort generator, Field field) { 603 String name = generator.name().isEmpty() ? field.getName() : generator.name(); 604 boolean hasDefault = generator.hasDefault(); 605 addFieldPort(name, field, hasDefault, false); 606 } 607 addProgramGenerator(GenerateProgramPort generator, Field field)608 private final void addProgramGenerator(GenerateProgramPort generator, Field field) { 609 String name = generator.name(); 610 String varName = generator.variableName().isEmpty() ? name 611 : generator.variableName(); 612 Class varType = generator.type(); 613 boolean hasDefault = generator.hasDefault(); 614 addProgramPort(name, varName, field, varType, hasDefault); 615 } 616 setInitialInputValues(KeyValueMap values)617 private final void setInitialInputValues(KeyValueMap values) { 618 for (Entry<String, Object> entry : values.entrySet()) { 619 setInputValue(entry.getKey(), entry.getValue()); 620 } 621 } 622 setImmediateInputValue(String name, Object value)623 private final void setImmediateInputValue(String name, Object value) { 624 if (mLogVerbose) Log.v(TAG, "Setting immediate value " + value + " for port " + name + "!"); 625 FilterPort port = getInputPort(name); 626 port.open(); 627 port.setFrame(SimpleFrame.wrapObject(value, null)); 628 } 629 transferInputFrames(FilterContext context)630 private final void transferInputFrames(FilterContext context) { 631 for (InputPort inputPort : mInputPorts.values()) { 632 inputPort.transfer(context); 633 } 634 } 635 wrapInputValue(String inputName, Object value)636 private final Frame wrapInputValue(String inputName, Object value) { 637 MutableFrameFormat inputFormat = ObjectFormat.fromObject(value, FrameFormat.TARGET_SIMPLE); 638 if (value == null) { 639 // If the value is null, the format cannot guess the class, so we adjust it to the 640 // class of the input port here 641 FrameFormat portFormat = getInputPort(inputName).getPortFormat(); 642 Class portClass = (portFormat == null) ? null : portFormat.getObjectClass(); 643 inputFormat.setObjectClass(portClass); 644 } 645 646 // Serialize if serializable, and type is not an immutable primitive. 647 boolean shouldSerialize = !(value instanceof Number) 648 && !(value instanceof Boolean) 649 && !(value instanceof String) 650 && value instanceof Serializable; 651 652 // Create frame wrapper 653 Frame frame = shouldSerialize 654 ? new SerializedFrame(inputFormat, null) 655 : new SimpleFrame(inputFormat, null); 656 frame.setObjectValue(value); 657 return frame; 658 } 659 releasePulledFrames(FilterContext context)660 private final void releasePulledFrames(FilterContext context) { 661 for (Frame frame : mFramesToRelease) { 662 context.getFrameManager().releaseFrame(frame); 663 } 664 mFramesToRelease.clear(); 665 } 666 inputConditionsMet()667 private final boolean inputConditionsMet() { 668 for (FilterPort port : mInputPorts.values()) { 669 if (!port.isReady()) { 670 if (mLogVerbose) Log.v(TAG, "Input condition not met: " + port + "!"); 671 return false; 672 } 673 } 674 return true; 675 } 676 outputConditionsMet()677 private final boolean outputConditionsMet() { 678 for (FilterPort port : mOutputPorts.values()) { 679 if (!port.isReady()) { 680 if (mLogVerbose) Log.v(TAG, "Output condition not met: " + port + "!"); 681 return false; 682 } 683 } 684 return true; 685 } 686 closePorts()687 private final void closePorts() { 688 if (mLogVerbose) Log.v(TAG, "Closing all ports on " + this + "!"); 689 for (InputPort inputPort : mInputPorts.values()) { 690 inputPort.close(); 691 } 692 for (OutputPort outputPort : mOutputPorts.values()) { 693 outputPort.close(); 694 } 695 } 696 filterMustClose()697 private final boolean filterMustClose() { 698 for (InputPort inputPort : mInputPorts.values()) { 699 if (inputPort.filterMustClose()) { 700 if (mLogVerbose) Log.v(TAG, "Filter " + this + " must close due to port " + inputPort); 701 return true; 702 } 703 } 704 for (OutputPort outputPort : mOutputPorts.values()) { 705 if (outputPort.filterMustClose()) { 706 if (mLogVerbose) Log.v(TAG, "Filter " + this + " must close due to port " + outputPort); 707 return true; 708 } 709 } 710 return false; 711 } 712 } 713