changeset 41909:7cdc6dfe9c9b

Merge
author ddehaven
date Thu, 03 Nov 2016 13:44:56 -0700
parents 92539b6985a5 a97f27c928d3
children 1383904abbd0
files jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/NSPrintInfo.java
diffstat 141 files changed, 18047 insertions(+), 258 deletions(-) [+]
line wrap: on
line diff
--- a/jdk/src/java.desktop/macosx/classes/sun/java2d/OSXSurfaceData.java	Thu Nov 03 13:06:24 2016 -0700
+++ b/jdk/src/java.desktop/macosx/classes/sun/java2d/OSXSurfaceData.java	Thu Nov 03 13:44:56 2016 -0700
@@ -74,8 +74,13 @@
         this.fGraphicsStatesInt = this.fGraphicsStates.asIntBuffer();
         this.fGraphicsStatesFloat = this.fGraphicsStates.asFloatBuffer();
         this.fGraphicsStatesLong = this.fGraphicsStates.asLongBuffer();
-        this.fGraphicsStatesObject = new Object[6]; // clip coordinates + clip types + texture paint image + stroke dash
-                                                    // array + font + font paint
+        this.fGraphicsStatesObject = new Object[8]; // clip coordinates +
+                                                    // clip types +
+                                                    // texture paint image +
+                                                    // stroke dash array +
+                                                    // font + font paint +
+                                                    // linear/radial gradient color +
+                                                    // linear/radial gradient fractions
 
         // NOTE: All access to the DrawingQueue comes through this OSXSurfaceData instance. Therefore
         // every instance method of OSXSurfaceData that accesses the fDrawingQueue is synchronized.
@@ -292,10 +297,10 @@
     @Native static final int kHintsFractionalMetricsIndex = 46;
     @Native static final int kHintsRenderingIndex = 47;
     @Native static final int kHintsInterpolationIndex = 48;
-    // live resizing info
-    @Native static final int kCanDrawDuringLiveResizeIndex = 49;
+    //gradient info
+    @Native static final int kRadiusIndex = 49;
 
-    @Native static final int kSizeOfParameters = kCanDrawDuringLiveResizeIndex + 1;
+    @Native static final int kSizeOfParameters = kRadiusIndex + 1;
 
     // for objectParameters
     @Native static final int kClipCoordinatesIndex = 0;
@@ -304,6 +309,8 @@
     @Native static final int kStrokeDashArrayIndex = 3;
     @Native static final int kFontIndex = 4;
     @Native static final int kFontPaintIndex = 5;
+    @Native static final int kColorArrayIndex = 6;
+    @Native static final int kFractionsArrayIndex = 7;
 
     // possible state changes
     @Native static final int kBoundsChangedBit = 1 << 0;
@@ -329,6 +336,8 @@
     @Native static final int kColorSystem = 1;
     @Native static final int kColorGradient = 2;
     @Native static final int kColorTexture = 3;
+    @Native static final int kColorLinearGradient = 4;
+    @Native static final int kColorRadialGradient = 5;
 
     // possible gradient color states
     @Native static final int kColorNonCyclic = 0;
@@ -522,6 +531,28 @@
     int lastPaintIndex = 0;
     BufferedImage texturePaintImage = null;
 
+    void setGradientViaRasterPath(SunGraphics2D sg2d) {
+        if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorTexture) || (lastPaint != sg2d.paint) || ((this.fChangeFlag & kBoundsChangedBit) != 0)) {
+            PaintContext context = sg2d.paint.createContext(sg2d.getDeviceColorModel(), userBounds, userBounds, sIdentityMatrix, sg2d.getRenderingHints());
+            WritableRaster raster = (WritableRaster) (context.getRaster(userBounds.x, userBounds.y, userBounds.width, userBounds.height));
+            ColorModel cm = context.getColorModel();
+            texturePaintImage = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
+
+            this.fGraphicsStatesInt.put(kColorStateIndex, kColorTexture);
+            this.fGraphicsStatesInt.put(kColorWidthIndex, texturePaintImage.getWidth());
+            this.fGraphicsStatesInt.put(kColorHeightIndex, texturePaintImage.getHeight());
+            this.fGraphicsStatesFloat.put(kColortxIndex, (float) userBounds.getX());
+            this.fGraphicsStatesFloat.put(kColortyIndex, (float) userBounds.getY());
+            this.fGraphicsStatesFloat.put(kColorsxIndex, 1.0f);
+            this.fGraphicsStatesFloat.put(kColorsyIndex, 1.0f);
+            this.fGraphicsStatesObject[kTextureImageIndex] = OSXOffScreenSurfaceData.createNewSurface(texturePaintImage);
+
+            this.fChangeFlag = (this.fChangeFlag | kColorChangedBit);
+        } else {
+            this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);
+        }
+    }
+
     void setupPaint(SunGraphics2D sg2d, int x, int y, int w, int h) {
         if (sg2d.paint instanceof SystemColor) {
             SystemColor color = (SystemColor) sg2d.paint;
@@ -567,6 +598,75 @@
             } else {
                 this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);
             }
+        } else if (sg2d.paint instanceof LinearGradientPaint) {
+            LinearGradientPaint color = (LinearGradientPaint) sg2d.paint;
+            if (color.getCycleMethod() == LinearGradientPaint.CycleMethod.NO_CYCLE) {
+                if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorLinearGradient) || (lastPaint != sg2d.paint)) {
+
+                    this.fGraphicsStatesInt.put(kColorStateIndex, kColorLinearGradient);
+                    int numColor = color.getColors().length;
+                    int colorArray[] = new int[numColor];
+                    for (int i = 0; i < numColor; i++) {
+                        colorArray[i] = color.getColors()[i].getRGB();
+                    }
+                    this.fGraphicsStatesObject[kColorArrayIndex] = colorArray;
+
+                    int numFractions = color.getFractions().length;
+                    float fractionArray[] = new float[numFractions];
+                    for (int i = 0; i < numFractions; i++) {
+                        fractionArray[i] = color.getFractions()[i];
+                    }
+                    this.fGraphicsStatesObject[kFractionsArrayIndex] = color.getFractions();
+
+                    Point2D p = color.getStartPoint();
+                    this.fGraphicsStatesFloat.put(kColorx1Index, (float) p.getX());
+                    this.fGraphicsStatesFloat.put(kColory1Index, (float) p.getY());
+                    p = color.getEndPoint();
+                    this.fGraphicsStatesFloat.put(kColorx2Index, (float) p.getX());
+                    this.fGraphicsStatesFloat.put(kColory2Index, (float) p.getY());
+
+                    this.fChangeFlag = (this.fChangeFlag | kColorChangedBit);
+                } else {
+                    this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);
+                }
+            } else {
+                setGradientViaRasterPath(sg2d);
+            }
+        } else if (sg2d.paint instanceof RadialGradientPaint) {
+            RadialGradientPaint color = (RadialGradientPaint) sg2d.paint;
+            if (color.getCycleMethod() == RadialGradientPaint.CycleMethod.NO_CYCLE) {
+                if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorRadialGradient) || (lastPaint != sg2d.paint)) {
+
+                    this.fGraphicsStatesInt.put(kColorStateIndex, kColorRadialGradient);
+                    int numColor = color.getColors().length;
+                    int colorArray[] = new int[numColor];
+                    for (int i = 0; i < numColor; i++) {
+                        colorArray[i] = color.getColors()[i].getRGB();
+                    }
+                    this.fGraphicsStatesObject[kColorArrayIndex] = colorArray;
+
+                    int numStops = color.getFractions().length;
+                    float stopsArray[] = new float[numStops];
+                    for (int i = 0; i < numStops; i++) {
+                        stopsArray[i] = color.getFractions()[i];
+                    }
+                    this.fGraphicsStatesObject[kFractionsArrayIndex] = color.getFractions();
+
+                    Point2D p = color.getFocusPoint();
+                    this.fGraphicsStatesFloat.put(kColorx1Index, (float) p.getX());
+                    this.fGraphicsStatesFloat.put(kColory1Index, (float) p.getY());
+                    p = color.getCenterPoint();
+                    this.fGraphicsStatesFloat.put(kColorx2Index, (float) p.getX());
+                    this.fGraphicsStatesFloat.put(kColory2Index, (float) p.getY());
+                    this.fGraphicsStatesFloat.put(kRadiusIndex,     color.getRadius());
+
+                    this.fChangeFlag = (this.fChangeFlag | kColorChangedBit);
+                } else {
+                    this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);
+                }
+            } else {
+                setGradientViaRasterPath(sg2d);
+            }
         } else if (sg2d.paint instanceof TexturePaint) {
             if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorTexture) || (lastPaint != sg2d.paint)) {
                 TexturePaint color = (TexturePaint) sg2d.paint;
@@ -587,27 +687,7 @@
                 this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);
             }
         } else {
-            if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorTexture) || (lastPaint != sg2d.paint) || ((this.fChangeFlag & kBoundsChangedBit) != 0)) {
-                PaintContext context = sg2d.paint.createContext(sg2d.getDeviceColorModel(), userBounds, userBounds, sIdentityMatrix, sg2d.getRenderingHints());
-                WritableRaster raster = (WritableRaster) (context.getRaster(userBounds.x, userBounds.y, userBounds.width, userBounds.height));
-                ColorModel cm = context.getColorModel();
-                texturePaintImage = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
-
-                this.fGraphicsStatesInt.put(kColorStateIndex, kColorTexture);
-                this.fGraphicsStatesInt.put(kColorWidthIndex, texturePaintImage.getWidth());
-                this.fGraphicsStatesInt.put(kColorHeightIndex, texturePaintImage.getHeight());
-                this.fGraphicsStatesFloat.put(kColortxIndex, (float) userBounds.getX());
-                this.fGraphicsStatesFloat.put(kColortyIndex, (float) userBounds.getY());
-                this.fGraphicsStatesFloat.put(kColorsxIndex, 1.0f);
-                this.fGraphicsStatesFloat.put(kColorsyIndex, 1.0f);
-                this.fGraphicsStatesObject[kTextureImageIndex] = sun.awt.image.BufImgSurfaceData.createData(texturePaintImage);
-
-                context.dispose();
-
-                this.fChangeFlag = (this.fChangeFlag | kColorChangedBit);
-            } else {
-                this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);
-            }
+            setGradientViaRasterPath(sg2d);
         }
         lastPaint = sg2d.paint;
     }
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java	Thu Nov 03 13:06:24 2016 -0700
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java	Thu Nov 03 13:44:56 2016 -0700
@@ -178,12 +178,6 @@
             return;
         }
 
-        // See if this has an NSPrintInfo in it.
-        NSPrintInfo nsPrintInfo = (NSPrintInfo)attributes.get(NSPrintInfo.class);
-        if (nsPrintInfo != null) {
-            fNSPrintInfo = nsPrintInfo.getValue();
-        }
-
         PageRanges pageRangesAttr =  (PageRanges)attributes.get(PageRanges.class);
         if (isSupportedValue(pageRangesAttr, attributes)) {
             SunPageSelection rangeSelect = (SunPageSelection)attributes.get(SunPageSelection.class);
@@ -563,8 +557,11 @@
 
     @Override
     protected void finalize() {
-        if (fNSPrintInfo != -1) {
-            dispose(fNSPrintInfo);
+        synchronized (fNSPrintInfoLock) {
+            if (fNSPrintInfo != -1) {
+                dispose(fNSPrintInfo);
+            }
+            fNSPrintInfo = -1;
         }
     }
 
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/NSPrintInfo.java	Thu Nov 03 13:06:24 2016 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.lwawt.macosx;
-
-
-import java.io.*;
-import javax.print.attribute.*;
-
-@SuppressWarnings("serial") // JDK implementation class
-public final class NSPrintInfo implements PrintJobAttribute, PrintRequestAttribute, Serializable, Cloneable {
-
-    private long fNSPrintInfo;
-
-    public NSPrintInfo(long nsPrintInfo) {
-        fNSPrintInfo = nsPrintInfo;
-    }
-
-    public long getValue() {
-        return fNSPrintInfo;
-    }
-
-    public boolean equals(Object object) {
-        return (object != null && object instanceof NSPrintInfo && fNSPrintInfo == ((NSPrintInfo)object).fNSPrintInfo);
-    }
-
-    public int hashCode() {
-        return (int)fNSPrintInfo;
-    }
-
-    public String toString() {
-        return "" + fNSPrintInfo;
-    }
-
-    public Class<? extends Attribute> getCategory() {
-        return NSPrintInfo.class;
-    }
-
-    public String getName() {
-        return "nsPrintInfo";
-    }
-}
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/QuartzSurfaceData.h	Thu Nov 03 13:06:24 2016 -0700
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/QuartzSurfaceData.h	Thu Nov 03 13:44:56 2016 -0700
@@ -44,6 +44,8 @@
     SD_Fill,
     SD_EOFill,
     SD_Shade,
+    SD_LinearGradient,
+    SD_RadialGradient,
     SD_Pattern,
     SD_Image,
     SD_Text,
@@ -65,6 +67,17 @@
 };
 typedef struct _stateShadingInfo StateShadingInfo;
 
+struct _stateGradientInfo
+{
+    CGPoint    start;
+    CGPoint    end;
+    CGFloat  radius;
+    CGFloat* colordata;
+    CGFloat* fractionsdata;
+    jint     fractionsLength;
+};
+typedef struct _stateGradientInfo StateGradientInfo;
+
 struct _statePatternInfo
 {
     CGFloat    tx;
@@ -122,6 +135,7 @@
                                                 // its callees.
 
     StateShadingInfo*        shadingInfo;        // tracks shading and its parameters
+    StateGradientInfo*       gradientInfo;       // tracks gradient and its parameters
     StatePatternInfo*        patternInfo;        // tracks pattern and its parameters
     StateGraphicsInfo        graphicsStateInfo;    // tracks other graphics state
 
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/QuartzSurfaceData.m	Thu Nov 03 13:06:24 2016 -0700
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/QuartzSurfaceData.m	Thu Nov 03 13:44:56 2016 -0700
@@ -268,9 +268,105 @@
     free(info);
 }
 
+static inline void contextQuartzLinearGradientPath(QuartzSDOps* qsdo)
+{
+
+PRINT("    contextQuartzLinearGradientPath");
+
+    CGContextRef cgRef = qsdo->cgRef;
+    StateGradientInfo *gradientInfo = qsdo->gradientInfo;
+   
+    CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+    size_t num_locations = gradientInfo->fractionsLength;
+    CGFloat *locations = (CGFloat *) malloc(sizeof(CGFloat) * num_locations);
+    int i = 0;
+    size_t component_size = num_locations * 4;
+    CGFloat components[component_size];
+    CGGradientRef gradient = NULL;
+
+    for (int i = 0; i < num_locations; i++) {
+        locations[i] = gradientInfo->fractionsdata[i];
+//fprintf(stderr, "locations[%d] %f\n", i, locations[i]);
+    }
+    for (i = 0; i < component_size; i++) {
+        components[i] = gradientInfo->colordata[i];
+//fprintf(stderr, "components[%d] %f, gradientInfo->colordata[%d] %f\n",
+//                  i, components[i], i, gradientInfo->colordata[i]);
+    } 
+    CGContextSaveGState(cgRef);
+    gradient = CGGradientCreateWithColorComponents(colorspace, components, locations, num_locations);
+//fprintf(stderr, "gradientInfo->start.x %f, gradientInfo->start.y %f\n", 
+//                 gradientInfo->start.x, gradientInfo->start.y);
+//fprintf(stderr, "gradientInfo->end.x %f, gradientInfo->end.y %f\n", 
+//                 gradientInfo->end.x, gradientInfo->end.y);
+    if (qsdo->isEvenOddFill) {
+        CGContextEOClip(cgRef);
+    } else {
+        CGContextClip(cgRef);
+    }
+    CGContextDrawLinearGradient(cgRef, gradient, gradientInfo->start, gradientInfo->end, kCGGradientDrawsAfterEndLocation);    
+    
+    CGContextRestoreGState(cgRef);
+    CGColorSpaceRelease(colorspace);
+    CGGradientRelease(gradient);
+    free(locations);
+    free(gradientInfo->colordata);
+    free(gradientInfo->fractionsdata);
+}
+
+static inline void contextQuartzRadialGradientPath(QuartzSDOps* qsdo)
+{
+
+PRINT("    contextQuartzRadialGradientPath");
+
+    CGContextRef cgRef = qsdo->cgRef;
+    StateGradientInfo *gradientInfo = qsdo->gradientInfo;
+   
+    CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+    size_t num_locations = gradientInfo->fractionsLength;
+    CGFloat *locations = (CGFloat *) malloc(sizeof(CGFloat) * num_locations);
+    int i = 0;
+    size_t component_size = num_locations * 4;
+    CGFloat components[component_size];
+    CGGradientRef gradient = NULL;
+    CGFloat startRadius = gradientInfo->radius;
+    CGFloat endRadius = gradientInfo->radius;
+
+    for (int i = 0; i < num_locations; i++) {
+        locations[i] = gradientInfo->fractionsdata[i];
+//fprintf(stderr, "locations[%d] %f\n", i, locations[i]);
+    }
+    for (i = 0; i < component_size; i++) {
+        components[i] = gradientInfo->colordata[i];
+//fprintf(stderr, "components[%d] %f, gradientInfo->colordata[%d] %f\n",
+//                  i, components[i], i, gradientInfo->colordata[i]);
+    } 
+    CGContextSaveGState(cgRef);
+    gradient = CGGradientCreateWithColorComponents(colorspace, components, locations, num_locations);
+//fprintf(stderr, "gradientInfo->start.x %f, gradientInfo->start.y %f\n", 
+//                 gradientInfo->start.x, gradientInfo->start.y);
+//fprintf(stderr, "gradientInfo->end.x %f, gradientInfo->end.y %f\n", 
+//                 gradientInfo->end.x, gradientInfo->end.y);
+    if (qsdo->isEvenOddFill) {
+        CGContextEOClip(cgRef);
+    } else {
+        CGContextClip(cgRef);
+    }
+//fprintf(stderr, "gradientInfo->startRadius %f, gradientInfo->endRadius %f\n",startRadius,endRadius);
+    CGContextDrawRadialGradient(cgRef, gradient, gradientInfo->start, 0, gradientInfo->end, endRadius, kCGGradientDrawsAfterEndLocation);    
+    
+    CGContextRestoreGState(cgRef);
+    CGColorSpaceRelease(colorspace);
+    CGGradientRelease(gradient);
+    free(locations);
+    free(gradientInfo->colordata);
+    free(gradientInfo->fractionsdata);
+}
+
 static inline void contextGradientPath(QuartzSDOps* qsdo)
 {
 PRINT("    ContextGradientPath")
+ 
     CGContextRef cgRef = qsdo->cgRef;
     StateShadingInfo* shadingInfo = qsdo->shadingInfo;
 
@@ -827,6 +923,81 @@
     qsdo->renderType = renderType;
 }
 
+void setupGradient(JNIEnv *env, QuartzSDOps* qsdo, jfloat* javaFloatGraphicsStates)
+{
+    static const CGFloat kColorConversionMultiplier = 1.0f/255.0f;
+    qsdo->gradientInfo = (StateGradientInfo*)malloc(sizeof(StateGradientInfo));
+    if (qsdo->gradientInfo == NULL)
+    {
+        [JNFException raise:env as:kOutOfMemoryError reason:"Failed to malloc memory for gradient paint"];
+    }
+
+    qsdo->graphicsStateInfo.simpleStroke = NO;
+    qsdo->graphicsStateInfo.simpleColor = NO;
+
+    qsdo->gradientInfo->start.x    = javaFloatGraphicsStates[sun_java2d_OSXSurfaceData_kColorx1Index];
+    qsdo->gradientInfo->start.y    = javaFloatGraphicsStates[sun_java2d_OSXSurfaceData_kColory1Index];
+    qsdo->gradientInfo->end.x    = javaFloatGraphicsStates[sun_java2d_OSXSurfaceData_kColorx2Index];
+    qsdo->gradientInfo->end.y    = javaFloatGraphicsStates[sun_java2d_OSXSurfaceData_kColory2Index];
+
+    jobject colorArray  = ((*env)->GetObjectArrayElement(env, qsdo->javaGraphicsStatesObjects, sun_java2d_OSXSurfaceData_kColorArrayIndex)); 
+    if (colorArray != NULL)
+    {
+        jint length = (*env)->GetArrayLength(env, colorArray);
+//fprintf(stderr, "length %d\n", length);
+
+        jint* jcolorData = (jint*)(*env)->GetPrimitiveArrayCritical(env, colorArray, NULL);
+        CGFloat* colors= (CGFloat*)calloc(0, sizeof(CGFloat)*length);
+        if (jcolorData != NULL)
+        {
+            jint i;
+            for (i=0; i<length; i++)
+            {
+                colors[i] = (CGFloat)jcolorData[i];
+            }
+        }
+        (*env)->ReleasePrimitiveArrayCritical(env, colorArray, jcolorData, 0);
+        qsdo->gradientInfo->colordata = (CGFloat*)calloc(0, sizeof(CGFloat)*4*length);
+        for (int i = 0; i < length; i++) 
+        {
+            jint c1 = colors[i];
+//fprintf(stderr, "c1 %x\n", c1);
+            qsdo->gradientInfo->colordata[i*4] = ((c1>>16)&0xff)*kColorConversionMultiplier;
+//fprintf(stderr, "qsdo->gradientInfo->colordata[%d] %f\n", i*4, qsdo->gradientInfo->colordata[i*4]);
+
+            qsdo->gradientInfo->colordata[i*4+1] = ((c1>>8)&0xff)*kColorConversionMultiplier;
+//fprintf(stderr, "qsdo->gradientInfo->colordata[%d] %f\n", i*4+1, qsdo->gradientInfo->colordata[i*4+1]);
+
+            qsdo->gradientInfo->colordata[i*4+2] = ((c1>>0)&0xff)*kColorConversionMultiplier;
+//fprintf(stderr, "qsdo->gradientInfo->colordata[%d] %f\n", i*4+2, qsdo->gradientInfo->colordata[i*4+2]);
+
+            qsdo->gradientInfo->colordata[i*4+3] = ((c1>>24)&0xff)*kColorConversionMultiplier;
+//fprintf(stderr, "qsdo->gradientInfo->colordata[%d] %f\n", i*4+3, qsdo->gradientInfo->colordata[i*4+3]);
+        }
+        free(colors);
+    }
+    jobject fractionsArray  = ((*env)->GetObjectArrayElement(env, qsdo->javaGraphicsStatesObjects, sun_java2d_OSXSurfaceData_kFractionsArrayIndex)); 
+    if (fractionsArray != NULL)
+    {
+        jint length = (*env)->GetArrayLength(env, fractionsArray);
+//fprintf(stderr, "fractions length %d\n", length);
+        qsdo->gradientInfo->fractionsLength = length;
+
+        jfloat* jfractionsData = (jfloat*)(*env)->GetPrimitiveArrayCritical(env, fractionsArray, NULL);
+        if (jfractionsData != NULL)
+        {
+            qsdo->gradientInfo->fractionsdata = (CGFloat *)malloc(sizeof(CGFloat) *length);
+            jint i;
+            for (i=0; i<length; i++)
+            {
+                qsdo->gradientInfo->fractionsdata[i] = jfractionsData[i];
+//fprintf(stderr, "jfrationsData[%d] %f, qsdo->gradientInfo->fractionsdata[%d] = %f\n", i, jfractionsData[i], i, qsdo->gradientInfo->fractionsdata[i]);
+            }
+            (*env)->ReleasePrimitiveArrayCritical(env, fractionsArray, jfractionsData, 0);
+        }
+    }    
+}
+
 SDRenderType SetUpPaint(JNIEnv *env, QuartzSDOps *qsdo, SDRenderType renderType)
 {
     CGContextRef cgRef = qsdo->cgRef;
@@ -898,6 +1069,21 @@
 
             break;
         }
+        case sun_java2d_OSXSurfaceData_kColorLinearGradient:
+        {
+            renderType = SD_LinearGradient;
+            setupGradient(env, qsdo, javaFloatGraphicsStates);
+            break;
+        }
+
+        case sun_java2d_OSXSurfaceData_kColorRadialGradient:
+        {
+            renderType = SD_RadialGradient;
+            setupGradient(env, qsdo, javaFloatGraphicsStates);
+            qsdo->gradientInfo->radius = javaFloatGraphicsStates[sun_java2d_OSXSurfaceData_kRadiusIndex];
+            break;
+        }
+
         case sun_java2d_OSXSurfaceData_kColorTexture:
         {
             qsdo->patternInfo = (StatePatternInfo*)malloc(sizeof(StatePatternInfo));
@@ -1076,11 +1262,24 @@
             }
             break;
 
+        case SD_LinearGradient:
+            if (CGContextIsPathEmpty(qsdo->cgRef) == 0)
+            {
+                contextQuartzLinearGradientPath(qsdo);
+            }
+            break;
+
+        case SD_RadialGradient:
+            if (CGContextIsPathEmpty(qsdo->cgRef) == 0)
+            {
+                contextQuartzRadialGradientPath(qsdo);
+            }
+            break;
+
         case SD_Pattern:
             if (CGContextIsPathEmpty(qsdo->cgRef) == 0)
             {
-                //TODO:BG
-                //contextTexturePath(env, qsdo);
+                contextTexturePath(env, qsdo);
             }
             break;
 
@@ -1111,4 +1310,8 @@
         gradientPaintReleaseFunction(qsdo->shadingInfo);
         qsdo->shadingInfo = NULL;
     }
+    if (qsdo->gradientInfo != NULL) {
+        gradientPaintReleaseFunction(qsdo->gradientInfo);
+        qsdo->gradientInfo = NULL;
+    }
 }
--- a/jdk/src/java.desktop/share/classes/javax/imageio/package.html	Thu Nov 03 13:06:24 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/javax/imageio/package.html	Thu Nov 03 13:44:56 2016 -0700
@@ -2,7 +2,7 @@
 <html>
 <head>
 <!--
-Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved.
+Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
 DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 
 This code is free software; you can redistribute it and/or modify it
@@ -58,6 +58,25 @@
     <th>&nbsp;</th> <th>Reading</th> <th>Writing</th>
     <th>Notes</th> <th>Metadata</th>
 </tr>
+<!-- BMP plugin -->
+<tr>
+    <td><a href="https://msdn.microsoft.com/en-us/library/dd183391.aspx">BMP</a></td>
+    <td align='center'>yes</td>
+    <td align='center'>yes</td>
+    <td align='center'>none</td>
+    <td align='center'><a href='metadata/doc-files/bmp_metadata.html'>
+    BMP metadata format</a></td>
+</tr>
+<!-- GIF plugin -->
+<tr>
+    <td><a href="http://www.w3.org/Graphics/GIF/spec-gif89a.txt">GIF</a></td>
+    <td align='center'>yes</td>
+    <td align='center'>yes</td>
+    <td align='center'><a href="#gif_plugin_notes">
+    GIF plug-in notes</a></td>
+    <td align='center'><a href='metadata/doc-files/gif_metadata.html'>
+    GIF metadata format</a></td>
+</tr>
 <!-- JPEG plugin -->
 <tr>
     <td> <a href="http://www.jpeg.org">JPEG</a></td>
@@ -76,14 +95,15 @@
     <td align='center'><a href='metadata/doc-files/png_metadata.html'>
     PNG metadata format</a></td>
 </tr>
-<!-- BMP plugin -->
+<!-- TIFF plugin -->
 <tr>
-    <td>BMP</td>
+    <td><a href="https://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf">TIFF</a></td>
     <td align='center'>yes</td>
     <td align='center'>yes</td>
-    <td align='center'>none</td>
-    <td align='center'><a href='metadata/doc-files/bmp_metadata.html'>
-    BMP metadata format</a></td>
+    <td align='center'><a href='metadata/doc-files/tiff_metadata.html#Reading'>
+    TIFF plug-in notes</td>
+    <td align='center'><a href='metadata/doc-files/tiff_metadata.html#StreamMetadata'>
+    TIFF metadata format</a></td>
 </tr>
 <!-- WBMP plugin -->
 <tr>
@@ -94,16 +114,6 @@
     <td align='center'><a href='metadata/doc-files/wbmp_metadata.html'>
     WBMP metadata format</a></td>
 </tr>
-<!-- GIF plugin -->
-<tr>
-    <td><a href="http://www.w3.org/Graphics/GIF/spec-gif89a.txt">GIF</a></td>
-    <td align='center'>yes</td>
-    <td align='center'>yes</td>
-    <td align='center'><a href="#gif_plugin_notes">
-    GIF plug-in notes</a></td>
-    <td align='center'><a href='metadata/doc-files/gif_metadata.html'>
-    GIF metadata format</a></td>
-</tr>
 </table>
 </div>
 <BR>
--- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifGPSTagSet.java	Thu Nov 03 13:06:24 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifGPSTagSet.java	Thu Nov 03 13:44:56 2016 -0700
@@ -55,9 +55,7 @@
      *
      * @see #TAG_GPS_VERSION_ID
      */
-    public static final String GPS_VERSION_2_2 =
-        new String(new byte[] { '2', '2', '0', '0' },
-        StandardCharsets.US_ASCII);
+    public static final String GPS_VERSION_2_2 = "2200";
 
     /**
      * A tag indicating the North or South latitude (type ASCII, count = 2).
--- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifTIFFTagSet.java	Thu Nov 03 13:06:24 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifTIFFTagSet.java	Thu Nov 03 13:44:56 2016 -0700
@@ -71,9 +71,7 @@
      *
      * @see #TAG_EXIF_VERSION
      */
-    public static final String EXIF_VERSION_2_1 =
-        new String(new byte[] { '0', '2', '1', '0' },
-        StandardCharsets.US_ASCII);
+    public static final String EXIF_VERSION_2_1 = "0210";
 
     /**
      * A value to be used with the "ExifVersion" tag to indicate Exif version
@@ -82,9 +80,7 @@
      *
      * @see #TAG_EXIF_VERSION
      */
-    public static final String EXIF_VERSION_2_2 =
-        new String(new byte[] { '0', '2', '2', '0' },
-        StandardCharsets.US_ASCII);
+    public static final String EXIF_VERSION_2_2 = "0220";
 
     /**
      * A tag indicating the FlashPix version number (type UNDEFINED,
--- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFField.java	Thu Nov 03 13:06:24 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFField.java	Thu Nov 03 13:44:56 2016 -0700
@@ -261,7 +261,7 @@
  * @see   TIFFDirectory
  * @see   TIFFTag
  */
-public class TIFFField implements Cloneable {
+public final class TIFFField implements Cloneable {
 
     private static final String[] typeNames = {
         null,
--- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFImageReadParam.java	Thu Nov 03 13:06:24 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFImageReadParam.java	Thu Nov 03 13:44:56 2016 -0700
@@ -48,7 +48,7 @@
  *
  * @since 9
  */
-public class TIFFImageReadParam extends ImageReadParam {
+public final class TIFFImageReadParam extends ImageReadParam {
 
     private List<TIFFTagSet> allowedTagSets = new ArrayList<TIFFTagSet>(4);
 
--- a/jdk/src/java.desktop/share/classes/javax/swing/JRootPane.java	Thu Nov 03 13:06:24 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/javax/swing/JRootPane.java	Thu Nov 03 13:44:56 2016 -0700
@@ -320,28 +320,6 @@
      * a UI-specific action like pressing the <b>Enter</b> key occurs.
      */
     protected JButton defaultButton;
-    /**
-     * As of Java 2 platform v1.3 this unusable field is no longer used.
-     * To override the default button you should replace the <code>Action</code>
-     * in the <code>JRootPane</code>'s <code>ActionMap</code>. Please refer to
-     * the key bindings specification for further details.
-     *
-     * @deprecated As of Java 2 platform v1.3.
-     *  @see #defaultButton
-     */
-    @Deprecated
-    protected DefaultAction defaultPressAction;
-    /**
-     * As of Java 2 platform v1.3 this unusable field is no longer used.
-     * To override the default button you should replace the <code>Action</code>
-     * in the <code>JRootPane</code>'s <code>ActionMap</code>. Please refer to
-     * the key bindings specification for further details.
-     *
-     * @deprecated As of Java 2 platform v1.3.
-     *  @see #defaultButton
-     */
-    @Deprecated
-    protected DefaultAction defaultReleaseAction;
 
     /**
      * Whether or not true double buffering should be used.  This is typically
@@ -829,35 +807,6 @@
         }
     }
 
-    @SuppressWarnings("serial")
-    static class DefaultAction extends AbstractAction {
-        JButton owner;
-        JRootPane root;
-        boolean press;
-        DefaultAction(JRootPane root, boolean press) {
-            this.root = root;
-            this.press = press;
-        }
-        public void setOwner(JButton owner) {
-            this.owner = owner;
-        }
-        public void actionPerformed(ActionEvent e) {
-            if (owner != null && SwingUtilities.getRootPane(owner) == root) {
-                ButtonModel model = owner.getModel();
-                if (press) {
-                    model.setArmed(true);
-                    model.setPressed(true);
-                } else {
-                    model.setPressed(false);
-                }
-            }
-        }
-        public boolean isEnabled() {
-            return owner.getModel().isEnabled();
-        }
-    }
-
-
     /**
      * Overridden to enforce the position of the glass component as
      * the zero child.
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalBorders.java	Thu Nov 03 13:06:24 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalBorders.java	Thu Nov 03 13:44:56 2016 -0700
@@ -739,7 +739,7 @@
         /**
          * The instance of {@code MetalBumps}.
          */
-        protected MetalBumps bumps = new MetalBumps( 10, 10,
+        private MetalBumps bumps = new MetalBumps( 10, 10,
                                       MetalLookAndFeel.getControlHighlight(),
                                       MetalLookAndFeel.getControlDarkShadow(),
                                      UIManager.getColor("ToolBar.background"));
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java	Thu Nov 03 13:06:24 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java	Thu Nov 03 13:44:56 2016 -0700
@@ -923,7 +923,7 @@
      * @param fc a {@code JFileChooser}
      * @return a new instance of {@code DirectoryComboBoxRenderer}
      */
-    protected DirectoryComboBoxRenderer createDirectoryComboBoxRenderer(JFileChooser fc) {
+    private DefaultListCellRenderer createDirectoryComboBoxRenderer(JFileChooser fc) {
         return new DirectoryComboBoxRenderer();
     }
 
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalScrollBarUI.java	Thu Nov 03 13:06:24 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalScrollBarUI.java	Thu Nov 03 13:44:56 2016 -0700
@@ -62,7 +62,7 @@
     /**
      * The metal bumps.
      */
-    protected MetalBumps bumps;
+    private MetalBumps bumps;
 
     /**
      * The increase button.
--- a/jdk/src/java.desktop/share/classes/sun/awt/shell/ShellFolder.java	Thu Nov 03 13:06:24 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/awt/shell/ShellFolder.java	Thu Nov 03 13:44:56 2016 -0700
@@ -30,6 +30,9 @@
 import java.awt.Toolkit;
 import java.io.*;
 import java.io.FileNotFoundException;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.Path;
 import java.util.*;
 import java.util.concurrent.Callable;
 
@@ -243,7 +246,8 @@
         if (file instanceof ShellFolder) {
             return (ShellFolder)file;
         }
-        if (!file.exists()) {
+
+        if (!Files.exists(file.toPath(), LinkOption.NOFOLLOW_LINKS)) {
             throw new FileNotFoundException();
         }
         return shellFolderManager.createShellFolder(file);
--- a/jdk/src/java.desktop/share/classes/sun/font/NullFontScaler.java	Thu Nov 03 13:06:24 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/font/NullFontScaler.java	Thu Nov 03 13:44:56 2016 -0700
@@ -36,8 +36,8 @@
         boolean supportsCJK, int filesize) {}
 
     StrikeMetrics getFontMetrics(long pScalerContext) {
-        return new StrikeMetrics(0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,
-        0xf0,0xf0,0xf0,0xf0);
+        return new StrikeMetrics(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+                                 0.0f, 0.0f, 0.0f, 0.0f);
     }
 
     float getGlyphAdvance(long pScalerContext, int glyphCode) {
@@ -71,7 +71,7 @@
         return getNullScalerContext();
     }
 
-    void invalidateScalerContext(long ppScalerContext) {
+    void invalidateScalerContext(long pScalerContext) {
         //nothing to do
     }
 
--- a/jdk/src/java.desktop/share/classes/sun/swing/plaf/GTKKeybindings.java	Thu Nov 03 13:06:24 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/swing/plaf/GTKKeybindings.java	Thu Nov 03 13:44:56 2016 -0700
@@ -219,6 +219,38 @@
                         "KP_UP", "selectPrevious"
 
                 }),
+                "Desktop.ancestorInputMap",
+                new UIDefaults.LazyInputMap(new Object[] {
+                        "ctrl F5", "restore",
+                        "ctrl F4", "close",
+                        "ctrl F7", "move",
+                        "ctrl F8", "resize",
+                        "RIGHT", "right",
+                        "KP_RIGHT", "right",
+                        "shift RIGHT", "shrinkRight",
+                        "shift KP_RIGHT", "shrinkRight",
+                        "LEFT", "left",
+                        "KP_LEFT", "left",
+                        "shift LEFT", "shrinkLeft",
+                        "shift KP_LEFT", "shrinkLeft",
+                        "UP", "up",
+                        "KP_UP", "up",
+                        "shift UP", "shrinkUp",
+                        "shift KP_UP", "shrinkUp",
+                        "DOWN", "down",
+                        "KP_DOWN", "down",
+                        "shift DOWN", "shrinkDown",
+                        "shift KP_DOWN", "shrinkDown",
+                        "ESCAPE", "escape",
+                        "ctrl F9", "minimize",
+                        "ctrl F10", "maximize",
+                        "ctrl F6", "selectNextFrame",
+                        "ctrl TAB", "selectNextFrame",
+                        "ctrl alt F6", "selectNextFrame",
+                        "shift ctrl alt F6", "selectPreviousFrame",
+                        "ctrl F12", "navigateNext",
+                        "shift ctrl F12", "navigatePrevious"
+                }),
                 "EditorPane.focusInputMap", multilineInputMap,
                 "FileChooser.ancestorInputMap",
                 new UIDefaults.LazyInputMap(new Object[]{
--- a/jdk/test/ProblemList.txt	Thu Nov 03 13:06:24 2016 -0700
+++ b/jdk/test/ProblemList.txt	Thu Nov 03 13:44:56 2016 -0700
@@ -217,6 +217,13 @@
 ############################################################################
 
 # jdk_sound
+javax/sound/sampled/DirectAudio/bug6372428.java        8055097 generic-all
+javax/sound/sampled/Clip/bug5070081.java               8055097 generic-all
+javax/sound/sampled/DataLine/LongFramePosition.java    8055097 generic-all
+
+javax/sound/sampled/Clip/Drain/ClipDrain.java          7062792 generic-all
+
+javax/sound/sampled/Mixers/DisabledAssertionCrash.java 7067310 generic-all
 
 ############################################################################
 
--- a/jdk/test/java/awt/FileDialog/8017487/bug8017487.java	Thu Nov 03 13:06:24 2016 -0700
+++ b/jdk/test/java/awt/FileDialog/8017487/bug8017487.java	Thu Nov 03 13:44:56 2016 -0700
@@ -22,7 +22,7 @@
  */
 
 /* @test
-   @bug 8017487
+   @bug 8017487 8167988
    @summary filechooser in Windows-Libraries folder: columns are mixed up
    @author Semyon Sadetsky
    @modules java.desktop/sun.awt.shell
--- a/jdk/test/java/awt/TrayIcon/DragEventSource/DragEventSource.java	Thu Nov 03 13:06:24 2016 -0700
+++ b/jdk/test/java/awt/TrayIcon/DragEventSource/DragEventSource.java	Thu Nov 03 13:44:56 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,8 +23,8 @@
 
 /*
   @test
-  @bug 6565779
-  @library ../../../regtesthelpers
+  @bug 6565779 8168292
+  @library ../../regtesthelpers
   @compile DragEventSource.java
   @summary Exception if source of some event is TrayIcon
   @author Andrei Dmitriev: area=awt.tray
@@ -38,9 +38,19 @@
  * instance as source.
  */
 
-import java.awt.*;
-import java.awt.event.*;
-import java.awt.image.*;
+import java.awt.Button;
+import java.awt.Dialog;
+import java.awt.FileDialog;
+import java.awt.FlowLayout;
+import java.awt.Frame;
+import java.awt.Image;
+import java.awt.Panel;
+import java.awt.SystemTray;
+import java.awt.TextArea;
+import java.awt.TrayIcon;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.image.BufferedImage;
 
 public class DragEventSource
 {
@@ -81,11 +91,10 @@
 
         String[] instructions =
         {
-            "Use see a Frame with a button in it.",
-            "Press the button. FileDialog should appear.",
-            "Drag the mouse from the Tray icon to FileDialog ",
-            "using left mouse button.",
-            "If exception happens, the test fails.",
+            "Click 'Open file dialog' button. FileDialog should appear.",
+            "Using left mouse button,",
+            "Drag the mouse from the Tray icon to FileDialog.",
+            "If exception is thrown, the test fails.",
             "Otherwise, pass."
         };
 
--- a/jdk/test/java/awt/Window/ChangeWindowResizabilty/ChangeWindowResizabiltyTest.java	Thu Nov 03 13:06:24 2016 -0700
+++ b/jdk/test/java/awt/Window/ChangeWindowResizabilty/ChangeWindowResizabiltyTest.java	Thu Nov 03 13:44:56 2016 -0700
@@ -21,12 +21,19 @@
  * questions.
  */
 
-/* @bug      8166897
+/* @test
+   @key headful
+   @bug      8166897
    @summary  Some font overlap in the Optionpane dialog.
    @run      main ChangeWindowResizabiltyTest
 */
 
-import java.awt.*;
+import java.awt.Component;
+import java.awt.Dialog;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.Panel;
+import java.awt.Robot;
 
 public class ChangeWindowResizabiltyTest {
     public static void main(String[] args) throws Exception {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/print/PrinterJob/LinearGradientPrintingTest.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ * @test
+ * @bug 8162796
+ * @summary  Verifies if LinearGradientPaint is printed in osx
+ * @run main/manual LinearGradientPrintingTest
+ */
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.LinearGradientPaint;
+import java.awt.Shape;
+import java.awt.event.ActionEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.print.PageFormat;
+import java.awt.print.Printable;
+import java.awt.print.PrinterException;
+import java.awt.print.PrinterJob;
+import javax.swing.AbstractAction;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JTextArea;
+import javax.swing.SwingUtilities;
+import javax.swing.WindowConstants;
+
+public class LinearGradientPrintingTest extends Component implements Printable {
+    private static Thread mainThread;
+    private static boolean testPassed;
+    private static boolean testGeneratedInterrupt;
+    private static JFrame f = null;
+
+    public static void main(String[] args) {
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                //createUI();
+                doTest(LinearGradientPrintingTest::createUI);
+            }
+        });
+        mainThread = Thread.currentThread();
+        try {
+            Thread.sleep(120000);
+        } catch (InterruptedException e) {
+            if (!testPassed && testGeneratedInterrupt) {
+                throw new RuntimeException("LinearGradientPaint did not print");
+            }
+        }
+        if (!testGeneratedInterrupt) {
+            throw new RuntimeException("user has not executed the test");
+        }
+    }
+
+    public static void createUI() {
+        f = new JFrame("LinearGradient Printing Test");
+        f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
+        final LinearGradientPrintingTest gpt = new LinearGradientPrintingTest();
+        Container c = f.getContentPane();
+        c.add(BorderLayout.CENTER, gpt);
+
+        final JButton print = new JButton("Print");
+        print.addActionListener(new AbstractAction() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                PrinterJob job = PrinterJob.getPrinterJob();
+                job.setPrintable(gpt);
+                final boolean doPrint = job.printDialog();
+                if (doPrint) {
+                    try {
+                        job.print();
+                    } catch (PrinterException ex) {
+                        throw new RuntimeException(ex);
+                    }
+                }
+            }
+        });
+        c.add(print, BorderLayout.SOUTH);
+
+        f.pack();
+        f.setVisible(true);
+    }
+
+    public Dimension getPreferredSize() {
+        return new Dimension(500,500);
+    }
+
+    public void paint(Graphics g) {
+        doPaint((Graphics2D)g);
+    }
+
+    public int print( Graphics graphics, PageFormat format, int index ) {
+        Graphics2D g2d = (Graphics2D)graphics;
+        g2d.translate(format.getImageableX(), format.getImageableY());
+        doPaint(g2d);
+        return index == 0 ? PAGE_EXISTS : NO_SUCH_PAGE;
+    }
+
+    static final float DIM = 100;
+    public void doPaint(Graphics2D g2d) {
+
+        g2d.translate(DIM*0.2, DIM*0.2);
+        Shape s = new Rectangle2D.Float(0, 0, DIM*2, DIM*2);
+        Point2D.Double p1 = new Point2D.Double(0.0, 0.0);
+        Point2D.Double p2 = new Point2D.Double(DIM/2.0, DIM/2.0);
+
+        // LinearGradientPaint
+        //g2d.translate(DIM*2.2, 0);
+        Color colors[] =  { Color.red, Color.blue} ;
+        float fractions[]  = { 0.0f, 1.0f };
+
+        LinearGradientPaint lgp =
+           new LinearGradientPaint(p1, p2, fractions, colors,
+              LinearGradientPaint.CycleMethod.NO_CYCLE);
+        g2d.setPaint(lgp);
+        g2d.fill(s);
+
+        g2d.translate(DIM*2.2, 0);
+        Color colors1[] =  { Color.red, Color.blue, Color.green, Color.white} ;
+        float fractions1[]  = { 0.0f, 0.3f, 0.6f, 1.0f };
+
+        LinearGradientPaint lgp1 =
+           new LinearGradientPaint(p1, p2, fractions1, colors1,
+              LinearGradientPaint.CycleMethod.REFLECT);
+        g2d.setPaint(lgp1);
+        g2d.fill(s);
+
+        g2d.translate(-DIM*2.2, DIM*2.2);
+        Color colors2[] =  { Color.red, Color.blue, Color.green, Color.white} ;
+        float fractions2[]  = { 0.0f, 0.3f, 0.6f, 1.0f };
+
+        LinearGradientPaint lgp2 =
+           new LinearGradientPaint(p1, p2, fractions2, colors2,
+              LinearGradientPaint.CycleMethod.REPEAT);
+        g2d.setPaint(lgp2);
+        g2d.fill(s);
+    }
+
+    public static synchronized void pass() {
+        testPassed = true;
+        testGeneratedInterrupt = true;
+        mainThread.interrupt();
+    }
+
+    public static synchronized void fail() {
+        testPassed = false;
+        testGeneratedInterrupt = true;
+        mainThread.interrupt();
+    }
+
+    private static void doTest(Runnable action) {
+        String description
+                = " A LinearGradientPaint graphics will be shown on console.\n"
+                + " The same graphics is sent to printer.\n"
+                + " Please verify if LinearGradientPaint shading is printed.\n"
+                + " If none is printed, press FAIL else press PASS";
+
+        final JDialog dialog = new JDialog();
+        dialog.setTitle("printSelectionTest");
+        JTextArea textArea = new JTextArea(description);
+        textArea.setEditable(false);
+        final JButton testButton = new JButton("Start Test");
+        final JButton passButton = new JButton("PASS");
+        passButton.setEnabled(false);
+        passButton.addActionListener((e) -> {
+            f.dispose();
+            dialog.dispose();
+            pass();
+        });
+        final JButton failButton = new JButton("FAIL");
+        failButton.setEnabled(false);
+        failButton.addActionListener((e) -> {
+            f.dispose();
+            dialog.dispose();
+            fail();
+        });
+        testButton.addActionListener((e) -> {
+            testButton.setEnabled(false);
+            action.run();
+            passButton.setEnabled(true);
+            failButton.setEnabled(true);
+        });
+        JPanel mainPanel = new JPanel(new BorderLayout());
+        mainPanel.add(textArea, BorderLayout.CENTER);
+        JPanel buttonPanel = new JPanel(new FlowLayout());
+        buttonPanel.add(testButton);
+        buttonPanel.add(passButton);
+        buttonPanel.add(failButton);
+        mainPanel.add(buttonPanel, BorderLayout.SOUTH);
+        dialog.add(mainPanel);
+
+        dialog.pack();
+        dialog.setVisible(true);
+        dialog.addWindowListener(new WindowAdapter() {
+           @Override
+            public void windowClosing(WindowEvent e) {
+                System.out.println("main dialog closing");
+                testGeneratedInterrupt = false;
+                mainThread.interrupt();
+            }
+        });
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/print/PrinterJob/RadialGradientPrintingTest.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ * @test
+ * @bug 8162796
+ * @summary  Verifies if RadialGradientPaint is printed in osx
+ * @run main/manual RadialGradientPrintingTest
+ */
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.RadialGradientPaint;
+import java.awt.Shape;
+import java.awt.event.ActionEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.print.PageFormat;
+import java.awt.print.Printable;
+import static java.awt.print.Printable.NO_SUCH_PAGE;
+import static java.awt.print.Printable.PAGE_EXISTS;
+import java.awt.print.PrinterException;
+import java.awt.print.PrinterJob;
+import javax.swing.AbstractAction;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JTextArea;
+import javax.swing.SwingUtilities;
+import javax.swing.WindowConstants;
+
+public class RadialGradientPrintingTest extends Component implements Printable {
+    private static Thread mainThread;
+    private static boolean testPassed;
+    private static boolean testGeneratedInterrupt;
+    private static JFrame f = null;
+
+    public static void main(String[] args) {
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                //createUI();
+                doTest(RadialGradientPrintingTest::createUI);
+            }
+        });
+        mainThread = Thread.currentThread();
+        try {
+            Thread.sleep(120000);
+        } catch (InterruptedException e) {
+            if (!testPassed && testGeneratedInterrupt) {
+                throw new RuntimeException("LinearGradientPaint did not print");
+            }
+        }
+        if (!testGeneratedInterrupt) {
+            throw new RuntimeException("user has not executed the test");
+        }
+    }
+
+    public static void createUI() {
+        f = new JFrame("RadialGradient Printing Test");
+        f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
+        final RadialGradientPrintingTest gpt = new RadialGradientPrintingTest();
+        Container c = f.getContentPane();
+        c.add(BorderLayout.CENTER, gpt);
+
+        final JButton print = new JButton("Print");
+        print.addActionListener(new AbstractAction() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                PrinterJob job = PrinterJob.getPrinterJob();
+                job.setPrintable(gpt);
+                final boolean doPrint = job.printDialog();
+                if (doPrint) {
+                    try {
+                        job.print();
+                    } catch (PrinterException ex) {
+                        throw new RuntimeException(ex);
+                    }
+                }
+            }
+        });
+        c.add(print, BorderLayout.SOUTH);
+
+        f.pack();
+        f.setVisible(true);
+    }
+
+    public Dimension getPreferredSize() {
+        return new Dimension(500,500);
+    }
+
+    public void paint(Graphics g) {
+        doPaint((Graphics2D)g);
+    }
+
+    public int print( Graphics graphics, PageFormat format, int index ) {
+        Graphics2D g2d = (Graphics2D)graphics;
+        g2d.translate(format.getImageableX(), format.getImageableY());
+        doPaint(g2d);
+        return index == 0 ? PAGE_EXISTS : NO_SUCH_PAGE;
+    }
+
+    static final float DIM = 100;
+    public void doPaint(Graphics2D g2d) {
+
+        g2d.translate(DIM*0.2, DIM*0.2);
+        Shape s = new Rectangle2D.Float(0, 0, DIM*2, DIM*2);
+
+        // RadialGradientPaint
+        Point2D centre = new Point2D.Float(DIM/2.0f, DIM/2.0f);
+        float radius = DIM/2.0f;
+        Point2D focus = new Point2D.Float(DIM/3.0f, DIM/3.0f);
+        float stops[] = {0.0f, 1.0f};
+        Color colors[] =  { Color.red, Color.white} ;
+
+        RadialGradientPaint rgp =
+           new RadialGradientPaint(centre, radius, focus, stops, colors,
+              RadialGradientPaint.CycleMethod.NO_CYCLE);
+        g2d.setPaint(rgp);
+        g2d.fill(s);
+
+        g2d.translate(DIM*2.2, 0);
+        Color colors1[] =  { Color.red, Color.blue, Color.green} ;
+        float stops1[] = {0.0f, 0.5f, 1.0f};
+        RadialGradientPaint rgp1 =
+           new RadialGradientPaint(centre, radius, focus, stops1, colors1,
+              RadialGradientPaint.CycleMethod.REFLECT);
+        g2d.setPaint(rgp1);
+        g2d.fill(s);
+
+        g2d.translate(-DIM*2.2, DIM*2.2);
+        Color colors2[] =  { Color.red, Color.blue, Color.green, Color.white} ;
+        float stops2[] = {0.0f, 0.3f, 0.6f, 1.0f};
+        RadialGradientPaint rgp2 =
+           new RadialGradientPaint(centre, radius, focus, stops2, colors2,
+              RadialGradientPaint.CycleMethod.REPEAT);
+        g2d.setPaint(rgp2);
+        g2d.fill(s);
+
+    }
+
+    public static synchronized void pass() {
+        testPassed = true;
+        testGeneratedInterrupt = true;
+        mainThread.interrupt();
+    }
+
+    public static synchronized void fail() {
+        testPassed = false;
+        testGeneratedInterrupt = true;
+        mainThread.interrupt();
+    }
+
+    private static void doTest(Runnable action) {
+        String description
+                = " A RadialGradientPaint graphics will be shown on console.\n"
+                + " The same graphics is sent to printer.\n"
+                + " Please verify if RadialGradientPaint shading is printed.\n"
+                + " If none is printed, press FAIL else press PASS";
+
+        final JDialog dialog = new JDialog();
+        dialog.setTitle("printSelectionTest");
+        JTextArea textArea = new JTextArea(description);
+        textArea.setEditable(false);
+        final JButton testButton = new JButton("Start Test");
+        final JButton passButton = new JButton("PASS");
+        passButton.setEnabled(false);
+        passButton.addActionListener((e) -> {
+            f.dispose();
+            dialog.dispose();
+            pass();
+        });
+        final JButton failButton = new JButton("FAIL");
+        failButton.setEnabled(false);
+        failButton.addActionListener((e) -> {
+            f.dispose();
+            dialog.dispose();
+            fail();
+        });
+        testButton.addActionListener((e) -> {
+            testButton.setEnabled(false);
+            action.run();
+            passButton.setEnabled(true);
+            failButton.setEnabled(true);
+        });
+        JPanel mainPanel = new JPanel(new BorderLayout());
+        mainPanel.add(textArea, BorderLayout.CENTER);
+        JPanel buttonPanel = new JPanel(new FlowLayout());
+        buttonPanel.add(testButton);
+        buttonPanel.add(passButton);
+        buttonPanel.add(failButton);
+        mainPanel.add(buttonPanel, BorderLayout.SOUTH);
+        dialog.add(mainPanel);
+
+        dialog.pack();
+        dialog.setVisible(true);
+        dialog.addWindowListener(new WindowAdapter() {
+           @Override
+            public void windowClosing(WindowEvent e) {
+                System.out.println("main dialog closing");
+                testGeneratedInterrupt = false;
+                mainThread.interrupt();
+            }
+        });
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Devices/ClosedReceiver.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Receiver;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.Synthesizer;
+
+/**
+ * @test
+ * @bug 4616517
+ * @summary Receiver.send() does not work properly
+ */
+public class ClosedReceiver {
+
+    public static void main(String[] args) throws Exception {
+        out("#4616517: Receiver.send() does not work properly");
+        if (!isMidiInstalled()) {
+            out("Soundcard does not exist or sound drivers not installed!");
+            out("This test requires sound drivers for execution.");
+            return;
+        }
+
+        boolean passed = true;
+
+        passed &= testReceiverSend();
+        passed &= testClosedReceivers();
+        if (passed) {
+            out("Test PASSED.");
+        } else {
+            throw new Exception("Test FAILED.");
+        }
+    }
+
+    /**
+     * Execute Receiver.send() and expect that there is no exception.
+     */
+    private static boolean testReceiverSend() {
+        boolean result = true;
+
+        Receiver receiver;
+        ShortMessage shMsg = new ShortMessage();
+
+        try {
+            receiver = MidiSystem.getReceiver();
+            shMsg.setMessage(ShortMessage.NOTE_ON, 0,60, 93);
+            try {
+                receiver.send( shMsg, -1 );
+            } catch(IllegalStateException ilEx) {
+                ilEx.printStackTrace(System.out);
+                out("IllegalStateException was thrown incorrectly!");
+                result = false;
+            }
+            receiver.close();
+        } catch(MidiUnavailableException e) {
+            out("Midi unavailable, cannot test.");
+        } catch(InvalidMidiDataException ine) {
+            out("InvalidMidiDataException, cannot test.");
+        }
+        return result;
+    }
+
+    private static boolean testClosedReceivers() {
+        boolean result = true;
+        Receiver receiver;
+        Synthesizer synt = null;
+
+        // test Synthesizer's Receiver
+        try {
+            synt = MidiSystem.getSynthesizer();
+            synt.open();
+        } catch(MidiUnavailableException e) {
+            out("Midi unavailable, cannot test.");
+            return result;
+        }
+        try {
+            receiver = synt.getReceiver();
+        } catch (MidiUnavailableException e) {
+            out("unable to get Receiver from synthesizer, cannot test.");
+            return result;
+        }
+        result &= testClosedReceiver(receiver);
+        synt.close();
+
+        // test all MidiDevices' Receivers
+
+        MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo();
+        for (int i = 0; i < devices.length; i++) {
+            try {
+                MidiDevice device = MidiSystem.getMidiDevice(devices[i]);
+                if (device.getMaxReceivers() != 0) {
+                    receiver = device.getReceiver();
+                    result &= testClosedReceiver(receiver);
+                }
+            } catch (Exception e) {
+                out(e);
+                out("cannot test.");
+                return result;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Execute send() on a closed Receivers and expect IllegalStateException.
+     */
+    private static boolean testClosedReceiver(Receiver receiver) {
+        boolean result = true;
+        out("testing Receiver: " + receiver);
+        ShortMessage shMsg = new ShortMessage();
+        try {
+            shMsg.setMessage(ShortMessage.NOTE_ON, 0,60, 93);
+        } catch(InvalidMidiDataException e) {
+            out(e);
+            out("unable to construct ShortMessage, cannot test.");
+            return result;
+        }
+
+        // begin of test
+        receiver.close();
+        try {
+            receiver.send( shMsg, -1 );
+            out("IllegalStateException was not thrown "
+                + "on Receiver.send()!");
+            result = false;
+        } catch(IllegalStateException e) {
+            out("IllegalStateException was thrown. Ok.");
+        }
+        return result;
+    }
+
+    private static void out(Throwable t) {
+        t.printStackTrace(System.out);
+    }
+
+    private static void out(String message) {
+        System.out.println(message);
+    }
+
+    /**
+     * Returns true if at least one MIDI (port) device is correctly installed on
+     * the system.
+     */
+    private static boolean isMidiInstalled() {
+        boolean result = false;
+        MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo();
+        for (int i = 0; i < devices.length; i++) {
+            try {
+                MidiDevice device = MidiSystem.getMidiDevice(devices[i]);
+                result = !(device instanceof Sequencer)
+                        && !(device instanceof Synthesizer);
+            } catch (Exception e1) {
+                System.err.println(e1);
+            }
+            if (result)
+                break;
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Devices/IOLoop.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,404 @@
+/*
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayOutputStream;
+
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiMessage;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Receiver;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.SysexMessage;
+import javax.sound.midi.Transmitter;
+
+/**
+ * @test
+ * @bug 4782924
+ * @bug 4812168
+ * @bug 4356787
+ * @summary MIDI i/o. This is an interactive test! Start it and follow the
+ *          instructions.
+ * @run main/manual IOLoop
+ */
+public class IOLoop {
+    private static final int LONG_SYSEX_LENGTH = 2000;
+
+    private static Receiver receiver;
+    private static Transmitter transmitter;
+    private static MidiMessage receivedMessage;
+    private static ByteArrayOutputStream baos;
+    private static int expectedBytes;
+    private static int receivedBytes;
+    private static Object lock = new Object();
+    private static long lastTimestamp;
+
+    public static void main(String[] args) throws Exception {
+        ShortMessage sMsg = new ShortMessage();
+        SysexMessage syMsg = new SysexMessage();
+        boolean isTestPassed = true;
+        boolean sysExTestPassed = true;
+        boolean isTestExecuted = true;
+
+        out("To run this test successfully, you need to have attached");
+        out("  your MIDI out port with the MIDI in port.");
+
+        MidiDevice inDev = null;
+        MidiDevice outDev = null;
+
+        // setup
+        try {
+            MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
+
+            int devNum = Integer.decode(args[0]).intValue();
+            out("-> opening Transmitter from "+infos[devNum]);
+            inDev = MidiSystem.getMidiDevice(infos[devNum]);
+            inDev.open();
+            transmitter = inDev.getTransmitter();
+            Receiver testReceiver = new TestReceiver();
+            transmitter.setReceiver(testReceiver);
+
+            devNum = Integer.decode(args[1]).intValue();
+            out("-> opening Receiver from "+infos[devNum]);
+            outDev = MidiSystem.getMidiDevice(infos[devNum]);
+            outDev.open();
+            receiver = outDev.getReceiver();
+
+        } catch (Exception e) {
+            System.out.println(e);
+            System.out.println("Cannot test!");
+            return;
+        }
+
+        // test
+        sMsg.setMessage(ShortMessage.NOTE_OFF | 0, 27, 100);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.NOTE_OFF | 0, 0, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.NOTE_OFF | 15, 127, 127);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.NOTE_ON | 4, 27, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.NOTE_ON | 0, 0, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.NOTE_ON | 15, 127, 127);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.POLY_PRESSURE | 11, 98, 99);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.POLY_PRESSURE | 0, 0, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.POLY_PRESSURE | 15, 127, 127);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.CONTROL_CHANGE | 13, 1, 63);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.CONTROL_CHANGE | 0, 0, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.CONTROL_CHANGE | 15, 127, 127);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.PROGRAM_CHANGE | 2, 120, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.PROGRAM_CHANGE | 0, 0, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.PROGRAM_CHANGE | 15, 127, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.CHANNEL_PRESSURE | 6, 30, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.CHANNEL_PRESSURE | 0, 0, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.CHANNEL_PRESSURE | 15, 127, 0);
+        isTestPassed &= testMessage(sMsg);
+
+        sMsg.setMessage(ShortMessage.PITCH_BEND | 6, 56, 4);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.PITCH_BEND | 0, 0, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.PITCH_BEND | 15, 127, 127);
+        isTestPassed &= testMessage(sMsg);
+
+        sMsg.setMessage(ShortMessage.MIDI_TIME_CODE, 0, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.MIDI_TIME_CODE, 127, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.SONG_POSITION_POINTER, 1, 77);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.SONG_POSITION_POINTER, 0, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.SONG_POSITION_POINTER, 127, 127);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.SONG_SELECT, 51, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.SONG_SELECT, 0, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.SONG_SELECT, 127, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.TUNE_REQUEST);
+        isTestPassed &= testMessage(sMsg);
+
+        sMsg.setMessage(ShortMessage.TIMING_CLOCK);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.START);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.CONTINUE);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.STOP);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.ACTIVE_SENSING);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.SYSTEM_RESET);
+        isTestPassed &= testMessage(sMsg);
+
+        syMsg.setMessage(new byte[]{(byte) 0xF0, (byte) 0xF7}, 2);
+        isTestPassed &= testMessage(syMsg);
+        syMsg.setMessage(new byte[]{(byte) 0xF0, 0x01, (byte) 0xF7}, 3);
+        isTestPassed &= testMessage(syMsg);
+        syMsg.setMessage(new byte[]{(byte) 0xF0, 0x02, 0x03, (byte) 0xF7}, 4);
+        isTestPassed &= testMessage(syMsg);
+        syMsg.setMessage(new byte[]{(byte) 0xF0, 0x04, 0x05, 0x06, (byte) 0xF7}, 5);
+        isTestPassed &= testMessage(syMsg);
+
+        if (isTestPassed) {
+            byte[] sysexArray = new byte[LONG_SYSEX_LENGTH];
+            sysexArray[0] = (byte) 0xF0;
+            for (int i = 1; i < sysexArray.length; i++) {
+                sysexArray[i] = (byte) (i % 0x80);
+            }
+//          syMsg.setMessage(new byte[]{(byte) 0xF7, (byte) ShortMessage.START}, 2);
+//          sMsg.setMessage(ShortMessage.START);
+//          isTestPassed &= testMessage(syMsg, sMsg, DEFAULT_SLEEP_INTERVALL);
+            for (int trial = sysexArray.length; trial > 4; trial -= 1234) {
+                sleep(500);
+                sysexArray[trial - 1] = (byte) 0xF7;
+                syMsg.setMessage(sysexArray, trial);
+                sysExTestPassed &= testMessage(syMsg);
+                break;
+            }
+        }
+
+        // cleanup
+        receiver.close();
+        transmitter.close();
+        inDev.close();
+        outDev.close();
+
+        if (isTestExecuted) {
+            if (isTestPassed && sysExTestPassed) {
+
+                out("Test PASSED.");
+            } else {
+                if (isTestPassed
+                    && !sysExTestPassed
+                    && (System.getProperty("os.name").startsWith("Windows"))) {
+                    out("Some Windows MIDI i/o drivers have a problem with larger ");
+                    out("sys ex messages. The failing sys ex cases are OK, therefore.");
+                    out("Test PASSED.");
+                } else {
+                    throw new Exception("Test FAILED.");
+                }
+            }
+        } else {
+            out("Test NOT FAILED");
+        }
+    }
+
+    private static boolean testMessage(MidiMessage message) {
+        receivedMessage = null;
+        baos = new ByteArrayOutputStream();
+        expectedBytes = message.getLength();
+        receivedBytes = 0;
+        System.out.print("Sending message " + getMessageString(message.getMessage())+"...");
+        receiver.send(message, -1);
+        /* sending 3 bytes can roughly be done in 1 millisecond,
+         * so this estimate waits at max 3 times longer than the message takes,
+         * plus a little offset to allow the MIDI subsystem some processing time
+         */
+        int offset = 300; // standard offset 100 millis
+        if (message instanceof SysexMessage) {
+            // add a little processing time to sysex messages
+            offset += 1000;
+        }
+        if (receivedBytes < expectedBytes) {
+            sleep(expectedBytes + offset);
+        }
+        boolean equal;
+        byte[] data = baos.toByteArray();
+        if (data.length > 0) {
+            equal = messagesEqual(message.getMessage(), data);
+        } else {
+            equal = messagesEqual(message, receivedMessage);
+            if (receivedMessage != null) {
+                data = receivedMessage.getMessage();
+            } else {
+                data = null;
+            }
+        }
+        if (!equal) {
+            if ((message.getStatus() & 0xF0) == ShortMessage.PITCH_BEND) {
+                out("NOT failed (may expose a bug in ALSA)");
+                equal = true;
+                sleep(100);
+            }
+            if ((message.getStatus() == 0xF6) && (message.getLength() == 1)) {
+                out("NOT failed (may expose an issue on Solaris)");
+                equal = true;
+                sleep(100);
+            }
+            else if ((message.getStatus()) == 0xF0 && message.getLength() < 4) {
+                out("NOT failed (not a correct sys ex message)");
+                equal = true;
+                sleep(200);
+            } else {
+                out("FAILED:");
+                out("  received as " + getMessageString(data));
+            }
+        } else {
+            System.out.println("OK");
+        }
+        return equal;
+    }
+
+    private static void sleep(int milliseconds) {
+        synchronized(lock) {
+            try {
+                lock.wait(milliseconds);
+            } catch (InterruptedException e) {
+            }
+        }
+    }
+
+    private static String getMessageString(byte[] data) {
+        String s;
+        if (data == null) {
+            s = "<null>";
+        } else if (data.length == 0) {
+            s = "0-sized array";
+        } else {
+            int status = data[0] & 0xFF;
+            if (data.length <= 3) {
+                if (status < 240) {
+                    s = "command 0x" + Integer.toHexString(status & 0xF0) + " channel " + (status & 0x0F);
+                } else {
+                    s = "status 0x" + Integer.toHexString(status);
+                }
+                if (data.length > 1) {
+                    s += " data 0x" + Integer.toHexString(data[1] & 0xFF);
+                    if (data.length > 2) {
+                        s += " 0x" + Integer.toHexString(data[2] & 0xFF);
+                    }
+                }
+            } else {
+                s = "status " + Integer.toHexString(status)+" and length "+data.length+" bytes";
+            }
+        }
+        return s;
+    }
+
+    private static boolean messagesEqual(MidiMessage m1, MidiMessage m2) {
+        if (m1 == null || m2 == null) {
+            return false;
+        }
+        if (m1.getLength() != m2.getLength()) {
+            return false;
+        }
+        byte[] array1 = m1.getMessage();
+        byte[] array2 = m2.getMessage();
+        return messagesEqual(array1, array2);
+    }
+
+    private static boolean messagesEqual(byte[] a1, byte[] a2) {
+        if (a1.length != a2.length) return false;
+        for (int i = 0; i < a1.length; i++) {
+            if (a1[i] != a2[i]) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private static void out(String s) {
+        System.out.println(s);
+        System.out.flush();
+    }
+
+    private static String canIn(MidiDevice dev) {
+        if (dev.getMaxTransmitters() != 0) {
+            return "IN ";
+        }
+        return "   ";
+    }
+
+    private static String canOut(MidiDevice dev) {
+        if (dev.getMaxReceivers() != 0) {
+            return "OUT ";
+        }
+        return "   ";
+    }
+
+
+    private static void checkTimestamp(long timestamp) {
+        // out("checking timestamp...");
+        if (timestamp < 1) {
+            out("timestamp 0 or negative!");
+        }
+        if (timestamp < lastTimestamp) {
+            out("timestamp not progressive!");
+        }
+        lastTimestamp = timestamp;
+    }
+
+    private static class TestReceiver implements Receiver {
+        public void send(MidiMessage message, long timestamp) {
+            //System.out.print(""+message.getLength()+"..");
+            checkTimestamp(timestamp);
+            try {
+                receivedMessage = message;
+                if (message.getStatus() == 0xF0
+                    || (message.getLength() > 3 && message.getStatus() != 0xF7)) {
+                    // sys ex message
+                    byte[] data = message.getMessage();
+                    baos.write(data);
+                    receivedBytes += data.length;
+                }
+                else if (message.getStatus() == 0xF7) {
+                    // sys ex cont'd message
+                    byte[] data = message.getMessage();
+                    // ignore the prepended 0xF7
+                    baos.write(data, 1, data.length-1);
+                    receivedBytes += (data.length - 1);
+                } else {
+                    receivedBytes += message.getLength();
+                }
+                if (receivedBytes >= expectedBytes) {
+                    synchronized(lock) {
+                        lock.notify();
+                    }
+                }
+                System.out.print(""+receivedBytes+"..");
+
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+
+        public void close() {
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Devices/MidiDeviceGetReceivers.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.List;
+
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Receiver;
+import javax.sound.midi.Transmitter;
+
+/**
+ * @test
+ * @bug 4931387
+ * @summary Add methods to MidiDevice to get list of Transmitters and Receivers
+ */
+public class MidiDeviceGetReceivers {
+
+    private static boolean executed = false;
+    private static boolean failed = false;
+
+    public static void main(String[] args) throws Exception {
+        out("unit test 4931387: Add methods to MidiDevice to get list of Transmitters and Receivers");
+        doAllTests();
+        if (executed) {
+            if (failed) throw new Exception("Test FAILED!");
+            out("Test PASSED.");
+        } else {
+            out("Test NOT failed.");
+        }
+    }
+
+    private static void doAllTests() {
+        MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
+        for (int i = 0; i < infos.length; i++) {
+            MidiDevice device = null;
+            try {
+                device = MidiSystem.getMidiDevice(infos[i]);
+                doTest(device);
+            } catch (MidiUnavailableException e) {
+                out("Exception occured when retrieving device "+infos[i]+": "+e);
+            }
+        }
+        if (infos.length == 0) {
+            out("No MIDI devices exist or sound drivers not installed!");
+        }
+    }
+
+    private static boolean containsReceiver(MidiDevice dev, Receiver rec) {
+        List<Receiver> recvs = dev.getReceivers();
+        return recvs.contains(rec);
+    }
+
+    private static boolean containsTransmitter(MidiDevice dev, Transmitter tra) {
+        List<Transmitter> tras = dev.getTransmitters();
+        return tras.contains(tra);
+    }
+
+    private static void doTest(MidiDevice device) {
+        boolean thisFailed = false;
+        out1("Testing: " + device+"...");
+        try {
+            device.open();
+        } catch (Exception e) {
+            out2("device.open threw exception: "+e);
+            out2("cannot test this device.");
+            return;
+        }
+        if (device.getMaxReceivers() != 0) {
+            // device offers receivers
+            try {
+                List<Receiver> origList = device.getReceivers();
+                Receiver rec = device.getReceiver();
+                if (!containsReceiver(device, rec)) {
+                    out2("Getting a receiver did not add it to device list!");
+                    thisFailed = true;
+                }
+                if (origList.contains(rec)) {
+                    out2("Original unmodifiable list was modified by adding a receiver!");
+                    thisFailed = true;
+                }
+                rec.close();
+                if (containsReceiver(device, rec)) {
+                    out2("Closing a receiver did not remove it from device list!");
+                    thisFailed = true;
+                }
+                // add a new receiver so that the device.close will really test
+                // that the receiver is removed
+                rec = device.getReceiver();
+                if (!containsReceiver(device, rec)) {
+                    out2("Getting a receiver again did not add it to device list!");
+                    thisFailed = true;
+                }
+            } catch (MidiUnavailableException e) {
+                out2("Exception on getting Receiver: " + e);
+            }
+        }
+        if (device.getMaxTransmitters() != 0) {
+            // device offers transmitters
+            try {
+                List<Transmitter> origList = device.getTransmitters();
+                Transmitter tra = device.getTransmitter();
+                if (!containsTransmitter(device, tra)) {
+                    out2("Getting a transmitter did not add it to device list!");
+                    thisFailed = true;
+                }
+                if (origList.contains(tra)) {
+                    out2("Original unmodifiable list was modified by adding a transmitter!");
+                    thisFailed = true;
+                }
+                tra.close();
+                if (containsTransmitter(device, tra)) {
+                    out2("Closing a transmitter did not remove it from device list!");
+                    thisFailed = true;
+                }
+                tra = device.getTransmitter();
+                if (!containsTransmitter(device, tra)) {
+                    out2("Getting a transmitter again did not add it to device list!");
+                    thisFailed = true;
+                }
+            } catch (MidiUnavailableException e) {
+                out("Exception on getting Transmitter: " + e);
+            }
+        }
+        try {
+            device.close();
+            if (device.getTransmitters().size() > 0) {
+                out2(" Device still has transmitters after close() was called!");
+                thisFailed = true;
+            }
+            if (device.getReceivers().size() > 0) {
+                out2(" Device still has receivers after close() was called!");
+                thisFailed = true;
+            }
+        } catch (Exception e) {
+            out2("device.close threw exception: "+e);
+        }
+        if (!thisFailed) {
+            out("OK");
+        } else {
+            failed = true;
+        }
+        executed = true;
+    }
+
+    static boolean lfMissing = false;
+
+    private static void out(String message) {
+        lfMissing = true;
+        System.out.println(message);
+    }
+
+    /* don't print LF at end */
+    private static void out1(String message) {
+        System.out.print(message);
+        lfMissing = true;
+    }
+
+    /* print at a new line, indented */
+    private static void out2(String message) {
+        if (lfMissing) {
+            System.out.println();
+            lfMissing = false;
+        }
+        System.out.println("  "+message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Devices/MidiIO.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+
+/**
+ * @test
+ * @bug 4356787
+ * @summary MIDI device I/O is not working
+ */
+public class MidiIO {
+
+    public static void main(String[] args) throws Exception {
+        out("4356787: MIDI device I/O is not working (windows)");
+
+        if (System.getProperty("os.name").startsWith("Windows")) {
+            boolean forInput=true;
+            boolean forOutput=true;
+            int outOnlyCount=0;
+            int inOnlyCount=0;
+            out("  available MIDI devices:");
+            MidiDevice.Info[] aInfos = MidiSystem.getMidiDeviceInfo();
+            for (int i = 0; i < aInfos.length; i++) {
+                try {
+                    MidiDevice      device = MidiSystem.getMidiDevice(aInfos[i]);
+                    boolean         bAllowsInput = (device.getMaxTransmitters() != 0);
+                    boolean         bAllowsOutput = (device.getMaxReceivers() != 0);
+                    if (bAllowsInput && !bAllowsOutput) {
+                        inOnlyCount++;
+                    }
+                    if (!bAllowsInput && bAllowsOutput) {
+                        outOnlyCount++;
+                    }
+                    if ((bAllowsInput && forInput) || (bAllowsOutput && forOutput)) {
+                        out(""+i+"  "
+                                +(bAllowsInput?"IN ":"   ")
+                                +(bAllowsOutput?"OUT ":"    ")
+                                +aInfos[i].getName()+", "
+                                +aInfos[i].getVendor()+", "
+                                +aInfos[i].getVersion()+", "
+                                +aInfos[i].getDescription());
+                    }
+                }
+                catch (MidiUnavailableException e) {
+                    // device is obviously not available...
+                }
+            }
+            if (aInfos.length == 0) {
+                out("No devices available. Test should be run on systems with MIDI drivers installed.");
+            } else {
+                if (outOnlyCount>1) {
+                    if (inOnlyCount==0) {
+                        //throw new Exception("No input devices! test fails.");
+                        out("System provides out devices, but no input devices. This means either");
+                        out("a bug in Java Sound, or the drivers are not set up correctly.");
+                    }
+                    out("Test passed.");
+                } else {
+                    out("no MIDI I/O installed. Test should be run on systems with MIDI drivers installed.");
+                }
+            }
+        } else {
+            out("  -- not on Windows. Test doesn't apply.");
+        }
+    }
+
+    static void out(String s) {
+        System.out.println(s); System.out.flush();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Devices/MidiOutGetMicrosecondPositionBug.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.Synthesizer;
+
+/**
+ * @test
+ * @bug 4903786
+ * @summary MIDI OUT does not implement getMicrosecondPosition() consistently
+ */
+public class MidiOutGetMicrosecondPositionBug {
+    static int successfulTests = 0;
+
+    private static void testDevice(MidiDevice device) throws Exception {
+        boolean timestampsAvailable = false;
+        boolean timestampPrecisionOk = false;
+        try {
+            // expected behaviour if not opened?
+            device.open();
+            /* First, we're testing if timestamps are provided at all.
+               Returning -1 (unsupported), while allowed by the API
+               specification, is not sufficient to pass this test. */
+            long timestamp = device.getMicrosecondPosition();
+            timestampsAvailable = (timestamp != -1);
+
+            /* Then, we're testing the precision. Note that the system time
+               is measured in milliseconds, while the device time is measured
+               in microseconds. */
+
+            long systemTime1 = System.currentTimeMillis();
+            long deviceTime1 = device.getMicrosecondPosition();
+            // rest for 5 seconds
+            Thread.sleep(5000);
+            long systemTime2 = System.currentTimeMillis();
+            long deviceTime2 = device.getMicrosecondPosition();
+
+            // now both period measurements are calculated in milliseconds.
+            long systemDuration = systemTime2 - systemTime1;
+            long deviceDuration = (deviceTime2 - deviceTime1) / 1000;
+            long delta = Math.abs(systemDuration - deviceDuration);
+            // a deviation of 0.5 seconds (= 500 ms) is allowed.
+            timestampPrecisionOk = (delta <= 500);
+        } catch (Throwable t) {
+            System.out.println("  - Caught exception. Not failed.");
+            System.out.println("  - " + t.toString());
+            return;
+        } finally {
+            device.close();
+        }
+        if (! timestampsAvailable) {
+            throw new Exception("timestamps are not supported");
+        }
+        if (! timestampPrecisionOk) {
+            throw new Exception("device timer not precise enough");
+        }
+        successfulTests++;
+    }
+
+    private static void doAll() throws Exception {
+        MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
+        for (int i=0; i < infos.length; i++) {
+            MidiDevice device = MidiSystem.getMidiDevice(infos[i]);
+            if ((! (device instanceof Sequencer)) &&
+                (! (device instanceof Synthesizer)) &&
+                (device.getMaxReceivers() > 0 || device.getMaxReceivers() == -1)) {
+
+                System.out.println("--------------");
+                System.out.println("Testing MIDI device: " + infos[i]);
+                testDevice(device);
+            }
+            if (infos.length==0) {
+                System.out.println("No MIDI devices available!");
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        if (!isMidiInstalled()) {
+            return;
+        }
+        doAll();
+        if (successfulTests==0) {
+            System.out.println("Could not execute any of the tests. Test NOT failed.");
+        } else {
+            System.out.println("Test PASSED.");
+        }
+    }
+
+    /**
+     * Returns true if at least one MIDI (port) device is correctly installed on
+     * the system.
+     */
+    public static boolean isMidiInstalled() {
+        boolean result = false;
+        MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo();
+        for (int i = 0; i < devices.length; i++) {
+            try {
+                MidiDevice device = MidiSystem.getMidiDevice(devices[i]);
+                result = ! (device instanceof Sequencer) && ! (device instanceof Synthesizer);
+            } catch (Exception e1) {
+                System.err.println(e1);
+            }
+            if (result)
+                break;
+        }
+        if (!result) {
+            System.err.println("Soundcard does not exist or sound drivers not installed!");
+            System.err.println("This test requires sound drivers for execution.");
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Devices/OpenClose.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,611 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Receiver;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.Synthesizer;
+import javax.sound.midi.Transmitter;
+
+/**
+ * @test
+ * @bug 4616517
+ * @summary Receiver.send() does not work properly. Tests open/close behaviour
+ *          of MidiDevices. For this test, it is essential that the MidiDevice
+ *          picked from the list of devices (MidiSystem.getMidiDeviceInfo()) is
+ *          the same as the one used by
+ *          MidiSystem.getReceiver()/getTransmitter(). To achieve this, default
+ *          provider properties for Receivers/Transmitters are used.
+ */
+public class OpenClose {
+
+    private static boolean isTestExecuted;
+    private static boolean isTestPassed;
+
+    public static void main(String[] args) throws Exception {
+        boolean failed = false;
+        out("#4616517: Receiver.send() does not work properly");
+        if (!isMidiInstalled()) {
+            out("Soundcard does not exist or sound drivers not installed!");
+            out("This test requires sound drivers for execution.");
+            return;
+        }
+        MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
+        MidiDevice outDevice = null;
+        MidiDevice inDevice = null;
+        for (int i = 0; i < infos.length; i++) {
+            MidiDevice device = MidiSystem.getMidiDevice(infos[i]);
+            if (! (device instanceof Synthesizer) &&
+                ! (device instanceof Sequencer)) {
+                if (device.getMaxReceivers() != 0) {
+                    outDevice = device;
+                }
+                if (device.getMaxTransmitters() != 0) {
+                    inDevice = device;
+                }
+            }
+        }
+        if (outDevice != null) {
+            // set the default provider properties
+            System.setProperty(Receiver.class.getName(),
+                               "#" + outDevice.getDeviceInfo().getName());
+        }
+        if (inDevice != null) {
+            System.setProperty(Transmitter.class.getName(),
+                               "#" + inDevice.getDeviceInfo().getName());
+        }
+        out("Using MIDI OUT Device: " + outDevice);
+        out("Using MIDI IN Device: " + inDevice);
+
+        isTestExecuted = false;
+        if (outDevice != null) {
+            isTestExecuted = true;
+            TestHelper testHelper = new ReceiverTestHelper(outDevice);
+            try {
+                doTest("Receiver", testHelper);
+                failed |= testHelper.hasFailed();
+            } catch (Exception e) {
+                out("Exception occured, cannot test!");
+                isTestExecuted = false;
+            }
+        }
+
+        if (inDevice != null) {
+            isTestExecuted = true;
+            TestHelper testHelper = new TransmitterTestHelper(inDevice);
+            try {
+                doTest("Transmitter", testHelper);
+                failed |= testHelper.hasFailed();
+            } catch (Exception e) {
+                out("Exception occured, cannot test!");
+                isTestExecuted = false;
+            }
+        }
+
+        isTestPassed = ! failed;
+
+        if (isTestExecuted) {
+            if (isTestPassed) {
+                out("Test PASSED.");
+            } else {
+                throw new Exception("Test FAILED.");
+            }
+        } else {
+            out("Test NOT FAILED");
+        }
+    }
+
+    private static void doTest(String type,
+                               TestHelper testHelper) throws Exception {
+        /* Case 1:
+           - MidiDevice.open()
+           - MidiDevice.close()
+        */
+        out("checking " + type + " case 1...");
+        testHelper.checkClosed();
+
+        testHelper.openDevice();
+        testHelper.checkOpen();
+
+        testHelper.closeDevice();
+        testHelper.checkClosed();
+
+        out("...OK");
+
+        /* Case 2a:
+           - MidiSystem.get[Receiver|Transmitter]()
+           - [Receiver|Transmitter].close()
+        */
+        out("checking " + type + " case 2a...");
+        testHelper.checkClosed();
+
+        testHelper.fetchObjectMidiSystem();
+        testHelper.checkOpen();
+
+        testHelper.closeObjectMidiSystem();
+        testHelper.checkClosed();
+
+        out("...OK");
+
+        /* Case 2b:
+           - MidiDevice.get[Receiver|Transmitter]()
+           - [Receiver|Transmitter].close()
+        */
+        out("checking " + type + " case 2b...");
+        testHelper.checkClosed();
+
+        testHelper.fetchObjectDevice();
+        testHelper.checkClosed();
+
+        testHelper.closeObjectDevice();
+        testHelper.checkClosed();
+
+        out("...OK");
+
+        /* Case 3a:
+           - MidiSystem.get[Receiver|Transmitter]()
+           - MidiDevice.open()
+           - MidiDevice.close()
+           - [Receiver|Transmitter].close()
+        */
+        out("checking " + type + " case 3a...");
+        testHelper.checkClosed();
+
+        testHelper.fetchObjectMidiSystem();
+        testHelper.checkOpen();
+
+        testHelper.openDevice();
+        testHelper.checkOpen();
+
+        testHelper.closeDevice();
+        testHelper.checkClosed();
+
+        testHelper.closeObjectMidiSystem();
+        testHelper.checkClosed();
+
+        out("...OK");
+
+        /* Case 3b:
+           - MidiDevice.get[Receiver|Transmitter]()
+           - MidiDevice.open()
+           - MidiDevice.close()
+           - [Receiver|Transmitter].close()
+        */
+        out("checking " + type + " case 3b...");
+        testHelper.checkClosed();
+
+        testHelper.fetchObjectDevice();
+        testHelper.checkClosed();
+
+        testHelper.openDevice();
+        testHelper.checkOpen();
+
+        testHelper.closeDevice();
+        testHelper.checkClosed();
+
+        testHelper.closeObjectDevice();
+        testHelper.checkClosed();
+
+        out("...OK");
+
+        /* Case 4a:
+           - MidiSystem.get[Receiver|Transmitter]()
+           - MidiDevice.open()
+           - [Receiver|Transmitter].close()
+           - MidiDevice.close()
+        */
+        out("checking " + type + " case 4a...");
+        testHelper.checkClosed();
+
+        testHelper.fetchObjectMidiSystem();
+        testHelper.checkOpen();
+
+        testHelper.openDevice();
+        testHelper.checkOpen();
+
+        testHelper.closeObjectMidiSystem();
+        testHelper.checkOpen();
+
+        testHelper.closeDevice();
+        testHelper.checkClosed();
+
+        out("...OK");
+
+        /* Case 4b:
+           - MidiDevice.get[Receiver|Transmitter]()
+           - MidiDevice.open()
+           - [Receiver|Transmitter].close()
+           - MidiDevice.close()
+        */
+        out("checking " + type + " case 4b...");
+        testHelper.checkClosed();
+
+        testHelper.fetchObjectDevice();
+        testHelper.checkClosed();
+
+        testHelper.openDevice();
+        testHelper.checkOpen();
+
+        testHelper.closeObjectDevice();
+        testHelper.checkOpen();
+
+        testHelper.closeDevice();
+        testHelper.checkClosed();
+
+        out("...OK");
+
+        /* Case 5a:
+           - MidiDevice.open()
+           - MidiSystem.get[Receiver|Transmitter]()
+           - MidiDevice.close()
+           - [Receiver|Transmitter].close()
+        */
+        out("checking " + type + " case 5a...");
+        testHelper.checkClosed();
+
+        testHelper.openDevice();
+        testHelper.checkOpen();
+
+        testHelper.fetchObjectMidiSystem();
+        testHelper.checkOpen();
+
+        testHelper.closeDevice();
+        testHelper.checkClosed();
+
+        testHelper.closeObjectMidiSystem();
+        testHelper.checkClosed();
+
+        out("...OK");
+
+        /* Case 5b:
+           - MidiDevice.open()
+           - MidiDevice.get[Receiver|Transmitter]()
+           - MidiDevice.close()
+           - [Receiver|Transmitter].close()
+        */
+        out("checking " + type + " case 5b...");
+        testHelper.checkClosed();
+
+        testHelper.openDevice();
+        testHelper.checkOpen();
+
+        testHelper.fetchObjectDevice();
+        testHelper.checkOpen();
+
+        testHelper.closeDevice();
+        testHelper.checkClosed();
+
+        testHelper.closeObjectDevice();
+        testHelper.checkClosed();
+
+        out("...OK");
+
+        /* Case 6a:
+           - MidiDevice.open()
+           - MidiSystem.get[Receiver|Transmitter]()
+           - [Receiver|Transmitter].close()
+           - MidiDevice.close()
+        */
+        out("checking " + type + " case 6a...");
+        testHelper.checkClosed();
+
+        testHelper.openDevice();
+        testHelper.checkOpen();
+
+        testHelper.fetchObjectMidiSystem();
+        testHelper.checkOpen();
+
+        testHelper.closeObjectMidiSystem();
+        testHelper.checkOpen();
+
+        testHelper.closeDevice();
+        testHelper.checkClosed();
+
+        out("...OK");
+
+        /* Case 6b:
+           - MidiDevice.open()
+           - MidiDevice.get[Receiver|Transmitter]()
+           - [Receiver|Transmitter].close()
+           - MidiDevice.close()
+        */
+        out("checking " + type + " case 6b...");
+        testHelper.checkClosed();
+
+        testHelper.openDevice();
+        testHelper.checkOpen();
+
+        testHelper.fetchObjectDevice();
+        testHelper.checkOpen();
+
+        testHelper.closeObjectDevice();
+        testHelper.checkOpen();
+
+        testHelper.closeDevice();
+        testHelper.checkClosed();
+
+        out("...OK");
+
+        /* Case 7:
+           - MidiSystem.get[Receiver|Transmitter]() // 1
+           - MidiDevice.get[Receiver|Transmitter]() // 2
+           - [Receiver|Transmitter].close() // 2
+           - [Receiver|Transmitter].close() // 1
+        */
+        out("checking " + type + " case 7...");
+        testHelper.checkClosed();
+
+        testHelper.fetchObjectMidiSystem();
+        testHelper.checkOpen();
+
+        testHelper.fetchObjectDevice();
+        testHelper.checkOpen();
+
+        testHelper.closeObjectDevice();
+        testHelper.checkOpen();
+
+        testHelper.closeObjectMidiSystem();
+        testHelper.checkClosed();
+
+        out("...OK");
+
+        /* Case 8:
+           - MidiSystem.get[Receiver|Transmitter]() // 1
+           - MidiDevice.get[Receiver|Transmitter]() // 2
+           - [Receiver|Transmitter].close() // 1
+           - [Receiver|Transmitter].close() // 2
+        */
+        out("checking " + type + " case 8...");
+        testHelper.checkClosed();
+
+        testHelper.fetchObjectMidiSystem();
+        testHelper.checkOpen();
+
+        testHelper.fetchObjectDevice();
+        testHelper.checkOpen();
+
+        testHelper.closeObjectMidiSystem();
+        testHelper.checkClosed();
+
+        testHelper.closeObjectDevice();
+        testHelper.checkClosed();
+
+        out("...OK");
+
+        /* Case 9:
+           - MidiDevice.get[Receiver|Transmitter]() // 2
+           - MidiSystem.get[Receiver|Transmitter]() // 1
+           - [Receiver|Transmitter].close() // 2
+           - [Receiver|Transmitter].close() // 1
+        */
+        out("checking " + type + " case 9...");
+        testHelper.checkClosed();
+
+        testHelper.fetchObjectDevice();
+        testHelper.checkClosed();
+
+        testHelper.fetchObjectMidiSystem();
+        testHelper.checkOpen();
+
+        testHelper.closeObjectDevice();
+        testHelper.checkOpen();
+
+        testHelper.closeObjectMidiSystem();
+        testHelper.checkClosed();
+
+        out("...OK");
+
+        /* Case 10:
+           - MidiDevice.get[Receiver|Transmitter]() // 2
+           - MidiSystem.get[Receiver|Transmitter]() // 1
+           - [Receiver|Transmitter].close() // 1
+           - [Receiver|Transmitter].close() // 2
+        */
+        out("checking " + type + " case 10...");
+        testHelper.checkClosed();
+
+        testHelper.fetchObjectDevice();
+        testHelper.checkClosed();
+
+        testHelper.fetchObjectMidiSystem();
+        testHelper.checkOpen();
+
+        testHelper.closeObjectMidiSystem();
+        testHelper.checkClosed();
+
+        testHelper.closeObjectDevice();
+        testHelper.checkClosed();
+
+        out("...OK");
+
+        /* Case N - 1:
+           - 10 x MidiSystem.get[Receiver|Transmitter]()
+           - 10 x [Receiver|Transmitter].close()
+        */
+        out("checking " + type + " case N - 1...");
+        TestHelper[] testHelpers = new TestHelper[10];
+        for (int i = 0; i < 10; i++) {
+            testHelpers[i] = (TestHelper) testHelper.clone();
+        }
+        testHelper.checkClosed();
+
+        for (int i = 0; i < 10; i++) {
+            testHelpers[i].fetchObjectMidiSystem();
+            testHelper.checkOpen();
+        }
+
+
+        for (int i = 0; i < 9; i++) {
+            testHelpers[i].closeObjectMidiSystem();
+            testHelper.checkOpen();
+        }
+
+        testHelpers[9].closeObjectMidiSystem();
+        testHelper.checkClosed();
+
+        out("...OK");
+    }
+
+    private static void out(String message) {
+        System.out.println(message);
+    }
+
+    private static abstract class TestHelper implements Cloneable {
+        private MidiDevice device;
+        private boolean failed;
+
+        protected TestHelper(MidiDevice device) {
+            this.device = device;
+            failed = false;
+        }
+
+        protected MidiDevice getDevice() {
+            return device;
+        }
+
+        public boolean hasFailed() {
+            return failed;
+        }
+
+        public void openDevice() throws MidiUnavailableException {
+            getDevice().open();
+        }
+
+        public void closeDevice() {
+            getDevice().close();
+        }
+
+        public void checkOpen(){
+            checkOpen(getDevice(), true);
+        }
+
+        public void checkClosed(){
+            checkOpen(getDevice(), false);
+        }
+
+        private void checkOpen(MidiDevice device, boolean desiredState) {
+            if (device.isOpen() != desiredState) {
+                out("device should be " +
+                                    getStateString(desiredState) + ", but isn't!");
+                failed = true;
+            }
+        }
+
+
+        private String getStateString(boolean state) {
+            return state ? "open" : "closed";
+        }
+
+
+        public abstract void fetchObjectMidiSystem() throws MidiUnavailableException;
+        public abstract void fetchObjectDevice() throws MidiUnavailableException;
+        public abstract void closeObjectMidiSystem();
+        public abstract void closeObjectDevice();
+
+        public Object clone() {
+            try {
+                return super.clone();
+            } catch (CloneNotSupportedException e) {
+                return null;
+            }
+        }
+    }
+
+    private static class ReceiverTestHelper extends TestHelper {
+        private Receiver receiverMidiSystem;
+        private Receiver receiverDevice;
+
+        public ReceiverTestHelper(MidiDevice device) {
+            super(device);
+        }
+
+        public void fetchObjectMidiSystem() throws MidiUnavailableException {
+            receiverMidiSystem = MidiSystem.getReceiver();
+        }
+
+
+        public void fetchObjectDevice() throws MidiUnavailableException {
+            receiverDevice = getDevice().getReceiver();
+        }
+
+
+        public void closeObjectMidiSystem() {
+            receiverMidiSystem.close();
+        }
+
+
+        public void closeObjectDevice() {
+            receiverDevice.close();
+        }
+    }
+
+    private static class TransmitterTestHelper extends TestHelper {
+        private Transmitter transmitterMidiSystem;
+        private Transmitter transmitterDevice;
+
+        public TransmitterTestHelper(MidiDevice device) {
+            super(device);
+        }
+
+        public void fetchObjectMidiSystem() throws MidiUnavailableException {
+            transmitterMidiSystem = MidiSystem.getTransmitter();
+        }
+
+
+        public void fetchObjectDevice() throws MidiUnavailableException {
+            transmitterDevice = getDevice().getTransmitter();
+        }
+
+
+        public void closeObjectMidiSystem() {
+            transmitterMidiSystem.close();
+        }
+
+
+        public void closeObjectDevice() {
+            transmitterDevice.close();
+        }
+    }
+
+    /**
+     * Returns true if at least one MIDI (port) device is correctly installed on
+     * the system.
+     */
+    public static boolean isMidiInstalled() {
+        boolean result = false;
+        MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo();
+        for (int i = 0; i < devices.length; i++) {
+            try {
+                MidiDevice device = MidiSystem.getMidiDevice(devices[i]);
+                result = ! (device instanceof Sequencer) && ! (device instanceof Synthesizer);
+            } catch (Exception e1) {
+                System.err.println(e1);
+            }
+            if (result)
+                break;
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Devices/ReceiverTransmitterAvailable.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Receiver;
+import javax.sound.midi.Transmitter;
+
+/**
+ * @test
+ * @bug 4616517
+ * @summary Receiver.send() does not work properly
+ */
+public class ReceiverTransmitterAvailable {
+
+    private static boolean isTestExecuted;
+    private static boolean isTestPassed;
+
+    public static void main(String[] args) throws Exception {
+        out("#4616517: Receiver.send() does not work properly");
+        doAllTests();
+        if (isTestExecuted) {
+            if (isTestPassed) {
+                out("Test PASSED.");
+            } else {
+                throw new Exception("Test FAILED.");
+            }
+        } else {
+            out("Test NOT FAILED");
+        }
+    }
+
+    private static void doAllTests() {
+        boolean problemOccured = false;
+        boolean succeeded = true;
+        MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
+        for (int i = 0; i < infos.length; i++) {
+            MidiDevice device = null;
+            try {
+                device = MidiSystem.getMidiDevice(infos[i]);
+                succeeded &= doTest(device);
+            } catch (MidiUnavailableException e) {
+                out("exception occured; cannot test");
+                problemOccured = true;
+            }
+        }
+        if (infos.length == 0) {
+            out("Soundcard does not exist or sound drivers not installed!");
+            out("This test requires sound drivers for execution.");
+        }
+        isTestExecuted = !problemOccured;
+        isTestPassed = succeeded;
+    }
+
+    private static boolean doTest(MidiDevice device) {
+        boolean succeeded = true;
+        out("Testing: " + device);
+        boolean expectingReceivers = (device.getMaxReceivers() != 0);
+        boolean expectingTransmitters = (device.getMaxTransmitters() != 0);
+        try {
+            Receiver rec = device.getReceiver();
+            rec.close();
+            if (! expectingReceivers) {
+                out("no exception on getting Receiver");
+                succeeded = false;
+            }
+        } catch (MidiUnavailableException e) {
+            if (expectingReceivers) {
+                out("Exception on getting Receiver: " + e);
+                succeeded = false;
+            }
+        }
+        try {
+            Transmitter trans = device.getTransmitter();
+            trans.close();
+            if (! expectingTransmitters) {
+                out("no exception on getting Transmitter");
+                succeeded = false;
+            }
+        } catch (MidiUnavailableException e) {
+            if (expectingTransmitters) {
+                out("Exception on getting Transmitter: " + e);
+                succeeded = false;
+            }
+        }
+        return succeeded;
+    }
+
+    private static void out(String message) {
+        System.out.println(message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Devices/Reopen.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.Synthesizer;
+
+/**
+ * @test
+ * @bug 4914667
+ * @summary Closing and reopening MIDI IN device on Linux throws
+ *          MidiUnavailableException
+ */
+public class Reopen {
+
+    private static boolean isTestExecuted;
+    private static boolean isTestPassed;
+
+    /*
+     * run manually:
+     * java Reopen 100 in      for 100 iterations on the MIDI IN device
+     * java Reopen 16 out      for 16 iterations on the MIDI OUT device
+     */
+    public static void main(String[] args) throws Exception {
+        if (args.length == 0) {
+            doAllTests();
+        } else if (args.length == 2) {
+            int numIterations = Integer.parseInt(args[0]);
+            if (args[1].equals("in")) {
+                doTest(numIterations, true);
+            } else {
+                doTest(numIterations, false);
+            }
+        } else {
+            out("usage: java Reopen <iterations> in|out");
+        }
+    }
+
+    private static void doAllTests() throws Exception {
+        out("#4914667: Closing and reopening MIDI IN device on Linux throws MidiUnavailableException");
+        boolean success = true;
+        try {
+            success &= doTest(20, true); // MIDI IN
+            success &= doTest(20, false); // MIDI OUT
+            isTestExecuted = true;
+        } catch (Exception e) {
+            out(e);
+            isTestExecuted = false;
+        }
+        isTestPassed = success;
+        if (isTestExecuted) {
+            if (isTestPassed) {
+                out("Test PASSED.");
+            } else {
+                throw new Exception("Test FAILED.");
+            }
+        } else {
+            out("Test NOT FAILED");
+        }
+    }
+
+    private static boolean doTest(int numIterations, boolean input) throws Exception {
+        MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
+        MidiDevice outDevice = null;
+        MidiDevice inDevice = null;
+        for (int i = 0; i < infos.length; i++) {
+            MidiDevice device = MidiSystem.getMidiDevice(infos[i]);
+            if (! (device instanceof Sequencer) &&
+                ! (device instanceof Synthesizer)) {
+                if (device.getMaxReceivers() != 0) {
+                    outDevice = device;
+                }
+                if (device.getMaxTransmitters() != 0) {
+                    inDevice = device;
+                }
+            }
+        }
+        MidiDevice testDevice = null;
+        if (input) {
+            testDevice = inDevice;
+        } else {
+            testDevice = outDevice;
+        }
+        if (testDevice == null) {
+            out("Cannot test: device not available.");
+            return true;
+        }
+        out("Using Device: " + testDevice);
+
+        for (int i = 0; i < numIterations; i++) {
+            out("@@@ ITERATION: " + i);
+            testDevice.open();
+            // This sleep ensures that the thread of MidiInDevice is started.
+            sleep(50);
+            testDevice.close();
+        }
+        return true;
+    }
+
+    private static void sleep(int milliseconds) {
+        try {
+            Thread.sleep(milliseconds);
+        } catch (InterruptedException e) {
+        }
+    }
+
+    private static void out(Throwable t) {
+        t.printStackTrace(System.out);
+    }
+
+    private static void out(String message) {
+        System.out.println(message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/File/SMFCp037.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+
+import javax.sound.midi.MidiSystem;
+
+/**
+ * @test
+ * @bug 4303933
+ * @summary MidiSystem fails to load MIDI file on systems with EBCDIC simulation
+ */
+public class SMFCp037 {
+
+    public static void main(String args[]) throws Exception {
+        // Test to read MIDI files with Cp037 character set - close enough
+        // for EBCDIC simulation
+        System.setProperty("file.encoding", "Cp037");
+        // try to read this file with Cp037 encoding
+        MidiSystem.getSequence(new ByteArrayInputStream(SHORT_SMF));
+        System.out.println("  test passed.");
+    }
+
+public static byte[] SHORT_SMF = {
+        77, 84, 104, 100, 0, 0, 0, 6, 0, 1, 0, 2, 0, 120, 77, 84, 114, 107, 0, 0,
+        0, 27, 0, -1, 3, 19, 77, 73, 68, 73, 32, 116, 101, 115, 116, 32, 45, 32,
+        116, 114, 97, 99, 107, 32, 48, 0, -1, 47, 0, 77, 84, 114, 107, 0, 0, 0, -44,
+        0, -1, 3, 19, 77, 73, 68, 73, 32, 116, 101, 115, 116, 32, 45, 32, 116, 114,
+        97, 99, 107, 32, 49, 0, -64, 30, 0, -112, 68, 126, 0, -32, 6, 67, 0, 14,
+        71, 0, 20, 74, 0, 26, 77, 0, 32, 80, 0, 42, 85, 6, 50, 89, 6, 56, 92, 5,
+        66, 97, 6, 74, 101, 6, 80, 104, 11, 84, 106, 20, 76, 102, 6, 70, 99, 5, 60,
+        94, 6, 52, 90, 5, 44, 86, 4, 34, 81, 5, 26, 77, 5, 20, 74, 6, 10, 69, 5,
+        2, 65, 7, 0, 64, 42, -112, 66, 123, 11, 68, 0, 72, 63, 126, 4, 66, 0, 43,
+        -32, 0, 63, 6, 0, 60, 7, 0, 56, 6, 0, 53, 5, 0, 49, 5, 0, 43, 4, 0, 37, 3,
+        0, 30, 3, 0, 25, 3, 0, 19, 3, 0, 13, 4, 0, 8, 4, 0, 2, 4, 0, 0, 70, 0, 3,
+        5, 0, 9, 3, 0, 14, 7, 0, 16, 25, 0, 21, 5, 0, 25, 7, 0, 28, 5, 0, 32, 5,
+        0, 36, 5, 0, 41, 6, 0, 46, 5, 0, 50, 5, 0, 53, 4, 0, 58, 7, 0, 61, 7, 0,
+        64, 117, -112, 63, 0, 0, -1, 47, 0
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/File/SMFParserBreak.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Sequence;
+
+/**
+ * @test
+ * @bug 4910986
+ * @summary MIDI file parser breaks up on http connection
+ */
+public class SMFParserBreak {
+
+    public static void main(String[] args) throws Exception {
+
+        InputStream is = new ByteArrayInputStream(midifile);
+        // create a buffered input stream that seems
+        // to be on an unfortunate boundary for the
+        // 1.4.2 SMF parser implementation
+        is = new ChunkInputStream(is, 32);
+        Sequence sequence = MidiSystem.getSequence(is);
+
+        long duration = sequence.getMicrosecondLength() / 10000;
+        System.out.println("Duration: "+duration+" deciseconds ");
+
+        // the test is passed if no exception thrown
+        System.out.println("Test passed");
+    }
+
+    // A MIDI file
+    static byte[] midifile = {
+        77, 84, 104, 100, 0, 0, 0, 6, 0, 1, 0, 3, -30, 120, 77, 84, 114, 107, 0,
+        0, 0, 123, 0, -112, 30, 100, -113, 49, -128, 50, 100, -114, 69, -112, 31,
+        100, -114, 33, -128, 51, 100, -114, 55, -112, 32, 100, -114, 120, -128, 52,
+        100, -114, 40, -112, 33, 100, -114, 26, -128, 53, 100, -114, 26, -112, 34,
+        100, -114, 76, -128, 54, 100, -114, 12, -112, 35, 100, -114, 91, -128, 55,
+        100, -114, 69, -112, 36, 100, -114, 33, -128, 56, 100, -114, 55, -112, 37,
+        100, -114, 84, -128, 57, 100, -114, 40, -112, 38, 100, -114, 26, -128, 58,
+        100, -114, 26, -112, 39, 100, -113, 24, -128, 59, 100, -113, 60, -112, 40,
+        100, -113, 110, -128, 60, 100, -113, 96, -112, 41, 100, -113, 39, -128, 61,
+        100, 0, -1, 47, 0, 77, 84, 114, 107, 0, 0, 0, 4, 0, -1, 47, 0, 77, 84, 114,
+        107, 0, 0, 0, 4, 0, -1, 47, 0
+    };
+}
+
+/* an input stream that always returns data in chunks */
+class ChunkInputStream extends FilterInputStream {
+    int chunkSize;
+    int p = 0; // position
+
+    public ChunkInputStream(InputStream is, int chunkSize) {
+        super(is);
+        this.chunkSize = chunkSize;
+    }
+
+    // override to increase counter
+    public int read() throws IOException {
+        int ret = super.read();
+        if (ret >= 0) {
+            p++;
+        }
+        return ret;
+    }
+
+    // override to make sure that read(byte[], int, int) is used
+    public int read(byte[] b) throws IOException {
+        return read(b, 0, b.length);
+    }
+
+    // override to split the data in chunks
+    public int read(byte[] b, int off, int len) throws IOException {
+        // if we would pass a chunk boundary,
+        // only return up to the chunk boundary
+        if ( (p / chunkSize) < ( (p+len) / chunkSize)) {
+            // p+len is in the next chunk
+            len -= ((p+len) % chunkSize);
+        }
+        int ret = super.read(b, off, len);
+        if (ret >= 0) {
+            p += ret;
+        }
+        return ret;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/File/WriteRealTimeMessageNPE.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+
+import javax.sound.midi.MidiEvent;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.Track;
+
+/**
+ * @test
+ * @bug 5048381
+ * @summary NPE when writing a sequence with a realtime MIDI message
+ */
+public class WriteRealTimeMessageNPE {
+
+    public static void main(String args[]) throws Exception {
+        System.out.println("5048381: NullPointerException when saving a MIDI sequence");
+        boolean npeThrown = false;
+        boolean noEx = false;
+
+        Sequence seq = new Sequence(Sequence.PPQ, 384, 1);
+        Track t = seq.getTracks()[0];
+        ShortMessage msg = new ShortMessage();
+        msg.setMessage(0xF8, 0, 0);
+        t.add(new MidiEvent(msg, 0));
+
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        try {
+            MidiSystem.write(seq, 0, out);
+            noEx = true;
+        } catch (NullPointerException npe) {
+            npeThrown = true;
+            System.out.println("## Failed: Threw unexpected NPE: "+npe);
+            throw new Exception("Test FAILED!");
+        } catch (Exception e) {
+            System.out.println("Threw unexpected Exception: "+e);
+            System.out.println("But at least did not throw NPE...");
+        }
+        if (noEx) {
+            InputStream is = new ByteArrayInputStream(out.toByteArray());
+            seq = MidiSystem.getSequence(is);
+            System.out.println("Sequence has "+seq.getTracks().length+" tracks.");
+            if (seq.getTracks().length > 0) {
+                System.out.println("Track 0 has "+seq.getTracks()[0].size()+" events.");
+            }
+        }
+        System.out.println("Test passed.");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/MetaMessage/MetaMessageClone.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import  javax.sound.midi.MetaMessage;
+
+/**
+ * @test
+ * @bug 4511796
+ * @summary Check that MetaMessage.clone() works correctly
+ */
+public class MetaMessageClone {
+
+    private static void printMsg(MetaMessage msg, byte[] data) {
+        System.out.println(""+msg.getLength()+" total bytes, type="+msg.getType()+", dataLength="+data.length);
+    }
+
+    private static void checkClone(MetaMessage msg) throws Exception {
+        System.out.print("Original: ");
+        byte[] msgData=msg.getData();
+        printMsg(msg, msgData);
+        MetaMessage msg2=(MetaMessage) msg.clone();
+        byte[] msg2Data=msg2.getData();
+        System.out.print("Clone:    ");
+        printMsg(msg2, msg2Data);
+
+        if (msg2.getLength()!=msg.getLength()
+            || msg.getType()!=msg2.getType()
+            || msgData.length!=msg2Data.length) {
+                throw new Exception("cloned MetaMessage is not equal.");
+        }
+        int max=Math.min(msgData.length, 10);
+        for (int i=0; i<max; i++) {
+            if (msgData[i]!=msg2Data[i]) {
+                throw new Exception("Cloned MetaMessage data is not equal.");
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        // let's create some MetaMessages and check them
+        MetaMessage msg=new MetaMessage();
+        String text="a textmarker";
+        msg.setMessage(1, text.getBytes(), text.length());
+        checkClone(msg);
+        msg.setMessage(0x2E, new byte[0], 0);
+        checkClone(msg);
+        byte[] data=new byte[17000];
+        for (int i=0; i<30; data[i]=(byte) (i++ & 0xFF));
+        msg.setMessage(0x02, data, 80); checkClone(msg);
+        msg.setMessage(0x02, data, 160); checkClone(msg);
+        msg.setMessage(0x02, data, 400); checkClone(msg);
+        msg.setMessage(0x02, data, 1000); checkClone(msg);
+        msg.setMessage(0x02, data, 10000); checkClone(msg);
+        msg.setMessage(0x02, data, 17000); checkClone(msg);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/MidiSystem/6411624/Test6411624.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,384 @@
+/*
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.awt.Button;
+import java.awt.Dialog;
+import java.awt.Frame;
+import java.awt.Panel;
+import java.awt.TextArea;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+/**
+ * @test
+ * @bug 6411624
+ * @summary Tests that MidiSystem.getReceiver() & MidiSystem.getTransmitter
+ *          doesn't return sequencer
+ * @build bug6411624
+ * @run main/manual Test6411624
+ */
+public class Test6411624 {
+
+   private static void init() throws Exception {
+        //*** Create instructions for the user here ***
+
+        String[] instructions =
+        {
+         "This test should only be run on solaris or linux system",
+         "WITHOUT audio card installed (to test on SunRay set",
+         "incorrect $AUDIODEV value).",
+         "If you system does not meet this conditions, press PASS.",
+         "To run the test follow these instructions:",
+         "1. Open a terminal window.",
+         "2. Type \"cd " + System.getProperty("test.classes") + "\".",
+         "3. Type \"" + System.getProperty("java.home") + "/bin/java bug6411624\".",
+         "4. Follow the instructions shown in the terminal window.",
+         "If you see \"All tests sucessfully passed\", press PASS else press FAIL."
+       };
+
+      Sysout.createDialog( );
+      Sysout.printInstructions( instructions );
+
+    }
+
+ /*****************************************************
+     Standard Test Machinery Section
+      DO NOT modify anything in this section -- it's a
+      standard chunk of code which has all of the
+      synchronisation necessary for the test harness.
+      By keeping it the same in all tests, it is easier
+      to read and understand someone else's test, as
+      well as insuring that all tests behave correctly
+      with the test harness.
+     There is a section following this for test-defined
+      classes
+   ******************************************************/
+   private static boolean theTestPassed = false;
+   private static boolean testGeneratedInterrupt = false;
+   private static String failureMessage = "";
+
+   private static Thread mainThread = null;
+
+   private static int sleepTime = 300000;
+
+   public static void main( String args[] ) throws Exception
+    {
+      mainThread = Thread.currentThread();
+      try
+       {
+         init();
+       }
+      catch( TestPassedException e )
+       {
+         //The test passed, so just return from main and harness will
+         // interepret this return as a pass
+         return;
+       }
+      //At this point, neither test passed nor test failed has been
+      // called -- either would have thrown an exception and ended the
+      // test, so we know we have multiple threads.
+
+      //Test involves other threads, so sleep and wait for them to
+      // called pass() or fail()
+      try
+       {
+         Thread.sleep( sleepTime );
+         //Timed out, so fail the test
+         throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" );
+       }
+      catch (InterruptedException e)
+       {
+         if( ! testGeneratedInterrupt ) throw e;
+
+         //reset flag in case hit this code more than once for some reason (just safety)
+         testGeneratedInterrupt = false;
+         if ( theTestPassed == false )
+          {
+            throw new RuntimeException( failureMessage );
+          }
+       }
+
+    }//main
+
+   public static synchronized void setTimeoutTo( int seconds )
+    {
+      sleepTime = seconds * 1000;
+    }
+
+   public static synchronized void pass()
+    {
+      Sysout.println( "The test passed." );
+      Sysout.println( "The test is over, hit  Ctl-C to stop Java VM" );
+      //first check if this is executing in main thread
+      if ( mainThread == Thread.currentThread() )
+       {
+         //Still in the main thread, so set the flag just for kicks,
+         // and throw a test passed exception which will be caught
+         // and end the test.
+         theTestPassed = true;
+         throw new TestPassedException();
+       }
+      //pass was called from a different thread, so set the flag and interrupt
+      // the main thead.
+      theTestPassed = true;
+      testGeneratedInterrupt = true;
+      mainThread.interrupt();
+    }//pass()
+
+   public static synchronized void fail()
+    {
+      //test writer didn't specify why test failed, so give generic
+      fail( "it just plain failed! :-)" );
+    }
+
+   public static synchronized void fail( String whyFailed )
+    {
+      Sysout.println( "The test failed: " + whyFailed );
+      Sysout.println( "The test is over, hit  Ctl-C to stop Java VM" );
+      //check if this called from main thread
+      if ( mainThread == Thread.currentThread() )
+       {
+         //If main thread, fail now 'cause not sleeping
+         throw new RuntimeException( whyFailed );
+       }
+      theTestPassed = false;
+      testGeneratedInterrupt = true;
+      failureMessage = whyFailed;
+      mainThread.interrupt();
+    }//fail()
+
+ }// class Orient
+
+//This exception is used to exit from any level of call nesting
+// when it's determined that the test has passed, and immediately
+// end the test.
+class TestPassedException extends RuntimeException
+ {
+ }
+
+//*********** End Standard Test Machinery Section **********
+
+
+//************ Begin classes defined for the test ****************
+
+// make listeners in a class defined here, and instantiate them in init()
+
+/* Example of a class which may be written as part of a test
+class NewClass implements anInterface
+ {
+   static int newVar = 0;
+
+   public void eventDispatched(AWTEvent e)
+    {
+      //Counting events to see if we get enough
+      eventCount++;
+
+      if( eventCount == 20 )
+       {
+         //got enough events, so pass
+
+         Orient.pass();
+       }
+      else if( tries == 20 )
+       {
+         //tried too many times without getting enough events so fail
+
+         Orient.fail();
+       }
+
+    }// eventDispatched()
+
+ }// NewClass class
+
+*/
+
+
+//************** End classes defined for the test *******************
+
+
+
+
+/****************************************************
+ Standard Test Machinery
+ DO NOT modify anything below -- it's a standard
+  chunk of code whose purpose is to make user
+  interaction uniform, and thereby make it simpler
+  to read and understand someone else's test.
+ ****************************************************/
+
+/**
+ This is part of the standard test machinery.
+ It creates a dialog (with the instructions), and is the interface
+  for sending text messages to the user.
+ To print the instructions, send an array of strings to Sysout.createDialog
+  WithInstructions method.  Put one line of instructions per array entry.
+ To display a message for the tester to see, simply call Sysout.println
+  with the string to be displayed.
+ This mimics System.out.println but works within the test harness as well
+  as standalone.
+ */
+
+class Sysout
+ {
+   private static TestDialog dialog;
+
+   public static void createDialogWithInstructions( String[] instructions )
+    {
+      dialog = new TestDialog( new Frame(), "Instructions" );
+      dialog.printInstructions( instructions );
+      dialog.show();
+      println( "Any messages for the tester will display here." );
+    }
+
+   public static void createDialog( )
+    {
+      dialog = new TestDialog( new Frame(), "Instructions" );
+      String[] defInstr = { "Instructions will appear here. ", "" } ;
+      dialog.printInstructions( defInstr );
+      dialog.show();
+      println( "Any messages for the tester will display here." );
+    }
+
+
+   public static void printInstructions( String[] instructions )
+    {
+      dialog.printInstructions( instructions );
+    }
+
+
+   public static void println( String messageIn )
+    {
+      dialog.displayMessage( messageIn );
+    }
+
+ }// Sysout  class
+
+/**
+  This is part of the standard test machinery.  It provides a place for the
+   test instructions to be displayed, and a place for interactive messages
+   to the user to be displayed.
+  To have the test instructions displayed, see Sysout.
+  To have a message to the user be displayed, see Sysout.
+  Do not call anything in this dialog directly.
+  */
+class TestDialog extends Dialog implements ActionListener
+ {
+
+   TextArea instructionsText;
+   TextArea messageText;
+   int maxStringLength = 80;
+   Panel  buttonP = new Panel();
+   Button passB = new Button( "pass" );
+   Button failB = new Button( "fail" );
+
+   //DO NOT call this directly, go through Sysout
+   public TestDialog( Frame frame, String name )
+    {
+      super( frame, name );
+      int scrollBoth = TextArea.SCROLLBARS_BOTH;
+      instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth );
+      add( "North", instructionsText );
+
+      messageText = new TextArea( "", 5, maxStringLength, scrollBoth );
+      add("Center", messageText);
+
+      passB = new Button( "pass" );
+      passB.setActionCommand( "pass" );
+      passB.addActionListener( this );
+      buttonP.add( "East", passB );
+
+      failB = new Button( "fail" );
+      failB.setActionCommand( "fail" );
+      failB.addActionListener( this );
+      buttonP.add( "West", failB );
+
+      add( "South", buttonP );
+      pack();
+
+      show();
+    }// TestDialog()
+
+   //DO NOT call this directly, go through Sysout
+   public void printInstructions( String[] instructions )
+    {
+      //Clear out any current instructions
+      instructionsText.setText( "" );
+
+      //Go down array of instruction strings
+
+      String printStr, remainingStr;
+      for( int i=0; i < instructions.length; i++ )
+       {
+         //chop up each into pieces maxSringLength long
+         remainingStr = instructions[ i ];
+         while( remainingStr.length() > 0 )
+          {
+            //if longer than max then chop off first max chars to print
+            if( remainingStr.length() >= maxStringLength )
+             {
+               //Try to chop on a word boundary
+               int posOfSpace = remainingStr.
+                  lastIndexOf( ' ', maxStringLength - 1 );
+
+               if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1;
+
+               printStr = remainingStr.substring( 0, posOfSpace + 1 );
+               remainingStr = remainingStr.substring( posOfSpace + 1 );
+             }
+            //else just print
+            else
+             {
+               printStr = remainingStr;
+               remainingStr = "";
+             }
+
+            instructionsText.append( printStr + "\n" );
+
+          }// while
+
+       }// for
+
+    }//printInstructions()
+
+   //DO NOT call this directly, go through Sysout
+   public void displayMessage( String messageIn )
+    {
+      messageText.append( messageIn + "\n" );
+    }
+
+   //catch presses of the passed and failed buttons.
+   //simply call the standard pass() or fail() static methods of
+   //DialogOrient
+   public void actionPerformed( ActionEvent e )
+    {
+      if( e.getActionCommand() == "pass" )
+       {
+         Test6411624.pass();
+       }
+      else
+       {
+         Test6411624.fail();
+       }
+    }
+
+ }// TestDialog  class
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/MidiSystem/6411624/bug6411624.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Receiver;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.Synthesizer;
+import javax.sound.midi.Transmitter;
+
+/**
+ * This test should be run on specific environment (solaris or linux w/o
+ * audio card installed).
+ */
+public class bug6411624 {
+
+    public static void main(String args[]) throws Exception {
+        log("This test should only be run on solaris or linux system");
+        log("without audio card installed (to test on SunRay set");
+        log("incorrect $AUDIODEV value).");
+        readln();
+
+        boolean testRecv = false;
+        boolean testTrans = false;
+        boolean testSeq = true;
+
+        // print add info (midi device list)
+        try {
+            MidiDevice.Info[] midis = MidiSystem.getMidiDeviceInfo();
+            log("MidiDevices (total " + midis.length + "):");
+            for (int i=0; i<midis.length; i++) {
+                log("" + i + ": " + midis[i].toString());
+//                MidiDevice dev = MidiSystem.getMidiDevice(midis[i]);
+//                log("    device: " + dev);
+            }
+        } catch (Exception ex) {
+            log("!!!EXCEPTION:");
+            ex.printStackTrace();
+        }
+
+        log("");
+        log("getting default receiver...");
+        try {
+            Receiver rec = MidiSystem.getReceiver();
+            log(" - OK: " + rec);
+            testRecv = checkDevice(rec);
+            rec.close();
+        } catch (MidiUnavailableException e) {
+            log("MidiUnavailableException has been thrown - OK");
+            testRecv = true;
+        }
+
+
+        log("");
+        log("getting default transmitter...");
+        try {
+            Transmitter trans = MidiSystem.getTransmitter();
+            log(" - OK: " + trans);
+            testTrans = checkDevice(trans);
+            trans.close();
+        } catch (MidiUnavailableException e) {
+            log("MidiUnavailableException has been thrown - OK");
+            testTrans = true;
+        }
+
+
+        // print default synthesizer
+        log("");
+        log("getting default synth...");
+        try {
+            Synthesizer synth = MidiSystem.getSynthesizer();
+            log(" - OK: " + synth);
+            synth.close();
+        } catch (MidiUnavailableException e) {
+            log("MidiUnavailableException has been thrown - OK:");
+            e.printStackTrace();
+        }
+
+
+        log("");
+        log("getting default sequencer (connected)...");
+        try {
+            Sequencer seq = MidiSystem.getSequencer();
+            log("OK: " + seq);
+
+            // check that returned sequencer doesn't connected to another sequencer
+            log("  receivers:");
+            log("    max=" + seq.getMaxReceivers());
+            List<Receiver> recvList = seq.getReceivers();
+            log("    count=" + recvList.size());
+            Iterator<Receiver> recvIter = recvList.iterator();
+            int i = 0;
+            while (recvIter.hasNext()) {
+                Receiver recv = recvIter.next();
+                log("    " + (++i) + ": " + recv);
+            }
+
+            log("  transmitters:");
+            log("    max=" + seq.getMaxTransmitters());
+            List<Transmitter> transList = seq.getTransmitters();
+            log("    count=" + transList.size());
+            Iterator<Transmitter> transIter = transList.iterator();
+            i = 0;
+            while (transIter.hasNext()) {
+                Transmitter trans = transIter.next();
+                log("    " + (++i) + ": " + trans);
+                Receiver recv = trans.getReceiver();
+                log("      recv: " + recv);
+                if (!checkDevice(recv))
+                    testSeq = false;
+            }
+
+            log("opening sequencer...");
+            seq.open();
+            log("OK.");
+
+            log("closing...");
+            seq.close();
+            log("OK.");
+        } catch (MidiUnavailableException e) {
+            log("MidiUnavailableException has been thrown - OK:");
+            e.printStackTrace();
+        }
+
+
+        // debug testing - non-connected sequencer
+        log("");
+        log("getting default sequencer (non-connected)...");
+        try {
+            Sequencer seq = MidiSystem.getSequencer(false);
+            log("OK: " + seq);
+
+            log("  receivers:");
+            log("    max=" + seq.getMaxReceivers());
+            List<Receiver> recvList = seq.getReceivers();
+            log("    count=" + recvList.size());
+            Iterator<Receiver> recvIter = recvList.iterator();
+            int i = 0;
+            while (recvIter.hasNext()) {
+                Receiver recv = recvIter.next();
+                log("    " + (++i) + ": " + recv);
+            }
+
+            log("  transmitters:");
+            log("    max=" + seq.getMaxTransmitters());
+            List<Transmitter> transList = seq.getTransmitters();
+            log("    count=" + transList.size());
+            Iterator<Transmitter> transIter = transList.iterator();
+            i = 0;
+            while (transIter.hasNext()) {
+                Transmitter trans = transIter.next();
+                log("    " + (++i) + ": " + trans);
+                Receiver recv = trans.getReceiver();
+                log("      recv: " + recv);
+            }
+            seq.close();
+        } catch (MidiUnavailableException e) {
+            log("MidiUnavailableException has been thrown (shouln't?):");
+            e.printStackTrace();
+        }
+
+        log("");
+        log("Test result:");
+        // print results
+        if (testRecv && testTrans && testSeq) {
+            log("  All tests sucessfully passed.");
+        } else {
+            log("  Some tests failed:");
+            log("    receiver test:    " + (testRecv ? "OK" : "FAILED"));
+            log("    transmitter test: " + (testTrans ? "OK" : "FAILED"));
+            log("    sequencer test:   " + (testSeq ? "OK" : "FAILED"));
+        }
+        log("\n\n\n");
+    }
+
+    // check that device is not sequencer
+    static boolean checkDevice(Object dev) {
+        String className = dev.getClass().toString().toLowerCase();
+        boolean result = (className.indexOf("sequencer") < 0);
+        if (!result)
+            log("ERROR: inapropriate device");
+        return result;
+    }
+
+    // helper routines
+    static long startTime = currentTimeMillis();
+    static long currentTimeMillis() {
+        //return System.nanoTime() / 1000000L;
+        return System.currentTimeMillis();
+    }
+    static void log(String s) {
+        long time = currentTimeMillis() - startTime;
+        long ms = time % 1000;
+        time /= 1000;
+        long sec = time % 60;
+        time /= 60;
+        long min = time % 60;
+        time /= 60;
+        System.out.println(""
+                + (time < 10 ? "0" : "") + time
+                + ":" + (min < 10 ? "0" : "") + min
+                + ":" + (sec < 10 ? "0" : "") + sec
+                + "." + (ms < 10 ? "00" : (ms < 100 ? "0" : "")) + ms
+                + " (" + Thread.currentThread().getName() + ") " + s);
+    }
+    static void delay(int millis) {
+        try {
+            Thread.sleep(millis);
+        } catch (InterruptedException e) {}
+    }
+    static void readln() {
+        log("");
+        log("Press ENTER to continue...");
+        try {
+            while (System.in.read() != 10) ;
+        } catch (IOException e) { }
+        log("");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/MidiSystem/DefaultDevices.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.List;
+
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Receiver;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.Synthesizer;
+import javax.sound.midi.Transmitter;
+import javax.sound.midi.spi.MidiDeviceProvider;
+
+import com.sun.media.sound.JDK13Services;
+
+/**
+ * @test
+ * @bug 4776511
+ * @bug 4934509
+ * @bug 4938236
+ * @modules java.desktop/com.sun.media.sound
+ * @run main/timeout=600 DefaultDevices
+ * @summary RFE: Setting the default MixerProvider
+ */
+/** Test the retrieving of MidiDevices with default device properties.
+ * This is a part of the test for 4776511.
+ * The test also functions as a unit test for 4934509: SPEC: Document
+ * explicitely MidiSystem.getReceiver's behavior
+ * and a regession test for 4938236: Crash when opening synthesizer implicitly
+ * The test has been updated to reflect a fix for 6411624: MidiSystem.getSequencer()
+ * doesn't throw MidiUnavaivableException if no audio card installed (see also
+ * 6422786: regression test javax/sound/midi/MidiSystem/DefaultDevices.java fails)
+ */
+public class DefaultDevices {
+
+    private static final String ERROR_PROVIDER_CLASS_NAME = "abc";
+    private static final String ERROR_INSTANCE_NAME = "def";
+
+    private static final Class RECEIVER_CLASS = javax.sound.midi.Receiver.class;
+    private static final Class TRANSMITTER_CLASS = javax.sound.midi.Transmitter.class;
+    private static final Class SEQUENCER_CLASS = javax.sound.midi.Sequencer.class;
+    private static final Class SYNTHESIZER_CLASS = javax.sound.midi.Synthesizer.class;
+
+    public static void main(String[] args) throws Exception {
+        boolean allOk = true;
+        MidiDevice.Info[] infos;
+
+        out("\nTesting MidiDevices retrieved via MidiSystem");
+        infos = MidiSystem.getMidiDeviceInfo();
+        allOk &= testDevices(infos, null);
+
+        out("\nTesting MidiDevices retrieved from MidiDeviceProviders");
+        List providers = JDK13Services.getProviders(MidiDeviceProvider.class);
+        for (int i = 0; i < providers.size(); i++) {
+            MidiDeviceProvider provider = (MidiDeviceProvider)providers.get(i);
+            infos = provider.getDeviceInfo();
+            allOk &= testDevices(infos, provider.getClass().getName());
+        }
+
+        if (!allOk) {
+            throw new Exception("Test failed");
+        } else {
+            out("Test passed");
+        }
+    }
+
+    private static boolean testDevices(MidiDevice.Info[] infos,
+            String providerClassName) {
+        boolean allOk = true;
+
+        for (int i = 0; i < infos.length; i++) {
+            MidiDevice device = null;
+            try {
+                device = MidiSystem.getMidiDevice(infos[i]);
+            } catch (MidiUnavailableException e) {
+                out("Exception thrown; Test NOT failed.");
+                e.printStackTrace(System.out);
+                out("");
+            }
+            out("\nTesting device: " + device);
+            if (device instanceof Sequencer) {
+                allOk &= testDevice(device, SEQUENCER_CLASS, providerClassName, true, true);
+                // incorrect cases
+                allOk &= testDevice(device, SYNTHESIZER_CLASS, providerClassName, false, false);
+                allOk &= testDevice(device, RECEIVER_CLASS, providerClassName, false, false);
+                allOk &= testDevice(device, TRANSMITTER_CLASS, providerClassName, false, false);
+            }
+            if (device instanceof Synthesizer) {
+                allOk &= testDevice(device, SYNTHESIZER_CLASS, providerClassName, true, true);
+                allOk &= testDevice(device, RECEIVER_CLASS, providerClassName, false, true);
+                // incorrect cases
+                allOk &= testDevice(device, TRANSMITTER_CLASS, providerClassName, false, false);
+                allOk &= testDevice(device, SEQUENCER_CLASS, providerClassName, false, false);
+            }
+            if (device instanceof Receiver) {
+                allOk &= testDevice(device, RECEIVER_CLASS, providerClassName, true, true);
+                // incorrect cases
+                allOk &= testDevice(device, TRANSMITTER_CLASS, providerClassName, false, false);
+                allOk &= testDevice(device, SYNTHESIZER_CLASS, providerClassName, false, false);
+                allOk &= testDevice(device, SEQUENCER_CLASS, providerClassName, false, false);
+            }
+            if (device instanceof Transmitter) {
+                allOk &= testDevice(device, TRANSMITTER_CLASS, providerClassName, true, true);
+                // incorrect cases
+                allOk &= testDevice(device, RECEIVER_CLASS, providerClassName, false, false);
+                allOk &= testDevice(device, SYNTHESIZER_CLASS, providerClassName, false, false);
+                allOk &= testDevice(device, SEQUENCER_CLASS, providerClassName, false, false);
+            }
+        }
+        return allOk;
+    }
+
+    private static boolean testDevice(MidiDevice device, Class type,
+            String providerClassName, boolean testWrong, boolean expectedResult) {
+        boolean allOk = true;
+        String instanceName = device.getDeviceInfo().getName();
+
+        // no error
+        allOk &= testDevice(device, type, providerClassName,
+                            instanceName, expectedResult);
+
+        if (testWrong) {
+            // erroneous provider class name, correct instance name
+            allOk &= testDevice(device, type, ERROR_PROVIDER_CLASS_NAME,
+                                instanceName, expectedResult);
+
+            // correct provider class name, erroneous instance name
+            // we presume that provider provides only one class of requested type
+            allOk &= testDevice(device, type, providerClassName,
+                                ERROR_INSTANCE_NAME, expectedResult);
+        }
+
+        return allOk;
+    }
+
+    private static boolean testDevice(MidiDevice device, Class type,
+            String providerClassName, String instanceName,
+            boolean expectedResult) {
+        boolean allOk = true;
+
+        try {
+            String propertyName = type.getName();
+            String propertyValue = (providerClassName != null) ? providerClassName: "" ;
+            propertyValue += "#" + instanceName;
+            out("property: " + propertyName + "="+ propertyValue);
+            System.setProperty(propertyName, propertyValue);
+            Object reference = null;
+            Object result = null;
+            if (type == SEQUENCER_CLASS) {
+                reference = device;
+                result = MidiSystem.getSequencer();
+            } else if (type == SYNTHESIZER_CLASS) {
+                reference = device;
+                result = MidiSystem.getSynthesizer();
+            } else if (type == RECEIVER_CLASS) {
+                reference = device.getReceiver();
+                result = MidiSystem.getReceiver();
+            } else if (type == TRANSMITTER_CLASS) {
+                reference = device.getTransmitter();
+                result = MidiSystem.getTransmitter();
+            }
+            out("result: " + result);
+            boolean rightDevice = (reference.getClass() == result.getClass());
+            if (rightDevice != expectedResult) {
+                out("\nERROR: type " + type + " failed:"
+                        + " class should" + (expectedResult ? "" : " NOT") + " be '"
+                        + reference.getClass()
+                        + "' but is '" + result.getClass() + "'!\n");
+                allOk = false;
+            }
+            if (expectedResult
+                    && reference instanceof MidiDevice
+                    && result instanceof MidiDevice) {
+                MidiDevice referenceDevice = (MidiDevice)reference;
+                MidiDevice resultDevice = (MidiDevice)result;
+                if (!referenceDevice.getDeviceInfo().getName().equals(
+                                    resultDevice.getDeviceInfo().getName())) {
+                    out("\nERROR: type " + type + " failed: name should be '"
+                            + referenceDevice.getDeviceInfo().getName()
+                            + "' but is '"
+                            + resultDevice.getDeviceInfo().getName() + "'!\n");
+                    allOk = false;
+                }
+            }
+            if (result instanceof Receiver) {
+                ((Receiver)result).close();
+            } else if (result instanceof Transmitter) {
+                ((Transmitter)result).close();
+            } else if (result instanceof Synthesizer) {
+                ((Synthesizer)result).close();
+            } else if (result instanceof Sequencer) {
+                ((Sequencer)result).close();
+            }
+        } catch (Exception e) {
+            out("Exception thrown; Test NOT failed.");
+            e.printStackTrace(System.out);
+            out("");
+        }
+        return allOk;
+    }
+
+    private static void out(String message) {
+        System.out.println(message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/MidiSystem/DefaultProperties.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.File;
+
+import com.sun.media.sound.JDK13Services;
+
+/**
+ * @test
+ * @bug 4776511
+ * @summary RFE: Setting the default MixerProvider. Test the retrieving and
+ *          parsing of properties. This is a part of the test for 4776511.
+ * @run main/othervm DefaultProperties
+ * @modules java.desktop/com.sun.media.sound
+ */
+public class DefaultProperties {
+
+    private static final Class[] lineTypeClasses = {
+        javax.sound.midi.Receiver.class,
+        javax.sound.midi.Transmitter.class,
+        javax.sound.midi.Sequencer.class,
+        javax.sound.midi.Synthesizer.class,
+    };
+
+    public static void main(String[] args) throws Exception {
+        boolean allOk = true;
+        File file = new File(System.getProperty("test.src", "."), "testdata");
+        System.setProperty("java.home", file.getCanonicalPath());
+
+        for (int i = 0; i < lineTypeClasses.length; i++) {
+            Class cls = lineTypeClasses[i];
+            String propertyName = cls.getName();
+            String result;
+            String provClassName;
+            String instanceName;
+
+            // properties file, both provider class name and instance name
+            provClassName = "xyz";
+            instanceName = "123";
+            result = JDK13Services.getDefaultProviderClassName(cls);
+            if (! provClassName.equals(result)) {
+                out("type " + cls + " failed: provider class should be '" +
+                    provClassName + "' but is '" + result + "'!");
+                allOk = false;
+            }
+            result = JDK13Services.getDefaultInstanceName(cls);
+            if (! instanceName.equals(result)) {
+                out("type " + cls + " failed: instance name should be '" +
+                    instanceName + "' but is '" + result + "'!");
+                allOk = false;
+            }
+
+            // system property, provider class name only, no trailing hash
+            provClassName = "abc";
+            System.setProperty(propertyName, provClassName);
+            result = JDK13Services.getDefaultProviderClassName(cls);
+            if (! provClassName.equals(result)) {
+                out("type " + cls + " failed: provider class should be '" +
+                    provClassName + "' but is '" + result + "'!");
+                allOk = false;
+            }
+            result = JDK13Services.getDefaultInstanceName(cls);
+            if (result != null) {
+                out("type " + cls + " failed: instance name should be " +
+                    "null but is '" + result + "'!");
+                allOk = false;
+            }
+
+            // system property, provider class name only, trailing hash
+            provClassName = "def";
+            System.setProperty(propertyName, provClassName + "#");
+            result = JDK13Services.getDefaultProviderClassName(cls);
+            if (! provClassName.equals(result)) {
+                out("type " + cls + " failed: provider class should be '" +
+                    provClassName + "' but is '" + result + "'!");
+                allOk = false;
+            }
+            result = JDK13Services.getDefaultInstanceName(cls);
+            if (result != null) {
+                out("type " + cls + " failed: instance name should be " +
+                    "null but is '" + result + "'!");
+                allOk = false;
+            }
+
+            // system property, instance name only
+            instanceName = "ghi";
+            System.setProperty(propertyName, "#" + instanceName);
+            result = JDK13Services.getDefaultProviderClassName(cls);
+            if (result != null) {
+                out("type " + cls + " failed: provider class should be " +
+                    "null but is '" + result + "'!");
+                allOk = false;
+            }
+            result = JDK13Services.getDefaultInstanceName(cls);
+            if (! instanceName.equals(result)) {
+                out("type " + cls + " failed: instance name should be '" +
+                    instanceName + "' but is '" + result + "'!");
+                allOk = false;
+            }
+
+            // system property, both provider class and instance name
+            provClassName = "jkl";
+            instanceName = "mno";
+            System.setProperty(propertyName, provClassName + "#" + instanceName);
+            result = JDK13Services.getDefaultProviderClassName(cls);
+            if (! provClassName.equals(result)) {
+                out("type " + cls + "failed: provider class should be '" +
+                    provClassName + "' but is '" + result + "'!");
+                allOk = false;
+            }
+            result = JDK13Services.getDefaultInstanceName(cls);
+            if (! instanceName.equals(result)) {
+                out("type " + cls + "failed: instance name should be '" +
+                    instanceName + "' but is '" + result + "'!");
+                allOk = false;
+            }
+
+            // system property, empty
+            System.setProperty(propertyName, "");
+            result = JDK13Services.getDefaultProviderClassName(cls);
+            if (result != null) {
+                out("type " + cls + " failed: provider class should be " +
+                    "null but is '" + result + "'!");
+                allOk = false;
+            }
+            result = JDK13Services.getDefaultInstanceName(cls);
+            if (result != null) {
+                out("type " + cls + "failed: instance name should be " +
+                    "null but is '" + result + "'!");
+                allOk = false;
+            }
+        }
+        if (! allOk) {
+            throw new Exception("Test failed");
+        } else {
+            out("Test passed");
+        }
+    }
+
+    private static void out(String message) {
+        System.out.println(message);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/MidiSystem/GetSequencer.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.List;
+
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.Transmitter;
+
+/**
+ * @test
+ * @bug 4931400
+ * @summary Clarify default connections in default sequencer
+ */
+public class GetSequencer {
+
+    static boolean failed = false;
+
+    public static void main(String args[]) throws Exception {
+        doTest(1);
+        doTest(2);
+        doTest(3);
+
+        if (failed) throw new Exception("Test FAILED!");
+        out("test OK");
+    }
+
+    public static void doTest(int mode) {
+        Sequencer seq = null;
+        boolean connected = false;
+
+        try {
+            switch (mode) {
+            case 1:
+                seq = MidiSystem.getSequencer();
+                connected = true;
+                break;
+            case 2:
+                seq = MidiSystem.getSequencer(false);
+                connected = false;
+                break;
+            case 3:
+                seq = MidiSystem.getSequencer(true);
+                connected = true;
+                break;
+            }
+            out("Testing Sequencer "+seq);
+            if (connected) {
+                out("  opened in connected mode.");
+            } else {
+                out("  opened in non-connected mode.");
+            }
+            System.out.println("  opening...");
+            seq.open();
+        } catch (MidiUnavailableException mue) {
+            System.err.println("MidiUnavailableException was thrown: " + mue);
+            System.err.println("  could not test this sequencer.");
+            return;
+        }
+
+        try {
+            List<Transmitter> transmitters = seq.getTransmitters();
+            int size = transmitters.size();
+            out("  transmitters.size()="+size);
+            if (size != 1 && connected) {
+                out("  should have 1 connection! Failed.");
+                failed = true;
+            }
+            if (size != 0 && !connected) {
+                out("  should have 0 connections! Failed.");
+                failed = true;
+            }
+            out("  closing...");
+            seq.close();
+            transmitters = seq.getTransmitters();
+            size = transmitters.size();
+            out("  transmitters.size()="+size);
+            if (size != 0) {
+                out("  should have 0 connections! Failed.");
+                failed = true;
+            }
+
+            out("  opening again...");
+            seq.open();
+            transmitters = seq.getTransmitters();
+            size = transmitters.size();
+            out("  transmitters.size()="+size);
+            if (size != 1 && connected) {
+                out("  should have 1 connection! Failed.");
+                failed = true;
+            }
+            if (size != 0 && !connected) {
+                out("  should have 0 connections! Failed.");
+                failed = true;
+            }
+        } catch (Exception e) {
+            System.err.println("  unexpectedException was thrown: " + e);
+            System.err.println("  causes this test to FAIL.");
+            failed = true;
+        }
+        seq.close();
+    }
+
+    static void out(String s) {
+        System.out.println(s);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/MidiSystem/MidiFileTypeUniqueness.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.midi.MidiSystem;
+
+/**
+ * @test
+ * @bug 4883060
+ * @summary  AudioSystem.getAudioFileTypes returns duplicates
+ */
+public class MidiFileTypeUniqueness {
+
+    public static void main(String[] args) throws Exception {
+        boolean foundDuplicates = false;
+        int[]   aTypes = MidiSystem.getMidiFileTypes();
+        for (int i = 0; i < aTypes.length; i++)
+        {
+            for (int j = 0; j < aTypes.length; j++)
+            {
+                if (aTypes[i] == aTypes[j] && i != j) {
+                    foundDuplicates = true;
+                }
+            }
+        }
+        if (foundDuplicates) {
+            throw new Exception("Test failed");
+        } else {
+            System.out.println("Test passed");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/MidiSystem/ProviderCacheing.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.List;
+
+import com.sun.media.sound.JDK13Services;
+
+/**
+ * @test
+ * @bug 4776511
+ * @summary RFE: Setting the default MixerProvider. Test the cacheing of
+ *          providers. This is a part of the test for 4776511.
+ * @modules java.desktop/com.sun.media.sound
+ */
+public class ProviderCacheing {
+
+    private static final Class[] providerClasses = {
+        javax.sound.midi.spi.MidiDeviceProvider.class,
+        javax.sound.midi.spi.MidiFileReader.class,
+        javax.sound.midi.spi.MidiFileWriter.class,
+        javax.sound.midi.spi.SoundbankReader.class,
+    };
+
+    public static void main(String[] args) throws Exception {
+        boolean allCached = true;
+        for (int i = 0; i < providerClasses.length; i++) {
+            List list0 = JDK13Services.getProviders(providerClasses[i]);
+            List list1 = JDK13Services.getProviders(providerClasses[i]);
+            if (list0 == list1) {
+                out("Providers should not be cached for " + providerClasses[i]);
+                allCached = false;
+            }
+        }
+
+        if (! allCached) {
+            throw new Exception("Test failed");
+        } else {
+            out("Test passed");
+        }
+    }
+
+    private static void out(String message) {
+        System.out.println(message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/MidiSystem/testdata/conf/sound.properties	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,27 @@
+#
+# Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+javax.sound.midi.Receiver=xyz#123
+javax.sound.midi.Transmitter=xyz#123
+javax.sound.midi.Sequencer=xyz#123
+javax.sound.midi.Synthesizer=xyz#123
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequence/GetMicrosecondLength.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.MetaMessage;
+import javax.sound.midi.MidiEvent;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.Track;
+
+/**
+ * @test
+ * @bug 4929955
+ * @summary Sequence.getMicrosecondLength() returns wrong value
+ */
+public class GetMicrosecondLength {
+
+    public static boolean failed = false;
+    //private static Sequencer seq = null;
+
+    public static void main(String[] args) throws Exception {
+        /*
+          try {
+          seq = MidiSystem.getSequencer();
+          } catch (Exception e) {
+          e.printStackTrace();
+          }
+        */
+        for (int sec = 1; sec < 10; sec += 4) {
+            for (int tempo=0; tempo < 1000; tempo+=120) {
+                for (int resolution=1; resolution < 480; ) {
+                    testSequence(sec, tempo, resolution);
+                    if (resolution == 1) {
+                        resolution = 120;
+                    } else {
+                        resolution += 120;
+                    }
+                }
+            }
+        }
+        if (failed) throw new Exception("Test FAILED!");
+        out("Test Passed.");
+    }
+
+    /**
+     * Create a new Sequence for testing.
+     */
+    private static void testSequence(int lengthInSeconds, int tempoInBPM, int resolution) {
+        Sequence sequence = null;
+        long lengthInMicroseconds = lengthInSeconds * 1000000;
+        boolean createTempoEvent = true;
+        if (tempoInBPM == 0) {
+            tempoInBPM = 120;
+            createTempoEvent = false;
+            System.out.print("Creating sequence: "+lengthInSeconds+"sec, "
+                             +"resolution="+resolution+" ticks/beat...");
+        } else {
+            System.out.print("Creating sequence: "+lengthInSeconds+"sec, "
+                             +tempoInBPM+" beats/min, "
+                             +"resolution="+resolution+" ticks/beat...");
+        }
+        //long lengthInTicks = (lengthInMicroseconds * resolution) / tempoInBPM;
+        long lengthInTicks = (lengthInMicroseconds * tempoInBPM * resolution) / 60000000l;
+        //out("expected length in ticks: " + lengthInTicks);
+        try {
+            sequence = new Sequence(Sequence.PPQ, resolution);
+            Track track = sequence.createTrack();
+            if (createTempoEvent) {
+                int tempoInMPQ = (int) (60000000l / tempoInBPM);
+                MetaMessage tm = new MetaMessage();
+                byte[] msg = new byte[3];
+                msg[0] = (byte) (tempoInMPQ >> 16);
+                msg[1] = (byte) ((tempoInMPQ >> 8) & 0xFF);
+                msg[2] = (byte) (tempoInMPQ & 0xFF);
+
+                tm.setMessage(0x51 /* Meta Tempo */, msg, msg.length);
+                track.add(new MidiEvent(tm, 0));
+                //out("regtest: tempoInMPQ="+tempoInMPQ);
+                //out("Added tempo event: new size="+track.size());
+            }
+            ShortMessage mm = new ShortMessage();
+            mm.setMessage(0xF6, 0, 0);
+            MidiEvent me = new MidiEvent(mm, lengthInTicks);
+            track.add(me);
+            //out("Added realtime event: new size="+track.size());
+        } catch (InvalidMidiDataException e) {
+            out(e);
+        }
+        boolean thisFailed = false;
+        long actualLengthInTicks = sequence.getTickLength();
+        // allow +/- 5%
+        if (Math.abs(actualLengthInTicks - lengthInTicks) > lengthInTicks / 20) {
+            out("FAILED:");
+            out("  expected length in ticks: " + lengthInTicks);
+            out("  actual length in ticks  : " + actualLengthInTicks);
+            thisFailed = true;
+        }
+        long actualLengthInUs = sequence.getMicrosecondLength();
+        // allow +/- 5%
+        if (Math.abs(actualLengthInUs - lengthInMicroseconds) > lengthInMicroseconds / 20) {
+            if (!thisFailed) {
+                out("FAILED:");
+            }
+            out("  expected length in microsecs: " + lengthInMicroseconds);
+            out("  actual length in microsecs  : " + actualLengthInUs);
+            thisFailed = true;
+        }
+        if (!thisFailed) {
+            out("OK");
+        }
+        /*if (seq != null) {
+          try {
+          seq.setSequence(sequence);
+          out("Sequencer tempo="+seq.getTempoInBPM());
+          } catch (Exception e) {
+          e.printStackTrace();
+          }
+          }
+        */
+        failed |= thisFailed;
+    }
+
+
+    private static void out(Throwable t) {
+        t.printStackTrace(System.out);
+    }
+
+    private static void out(String message) {
+        System.out.println(message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequence/MidiSMPTE.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Sequence;
+
+/**
+ * @test
+ * @bug 4291250
+ * @summary Midi files with SMPTE time do not play properly
+ */
+public class MidiSMPTE {
+
+    public static void main(String[] args) throws Exception {
+        Sequence s = null;
+        //File midiFile = new File("outsmpte.mid");
+        //InputStream is = new FileInputStream(midiFile);
+        //is = new BufferedInputStream(is);
+        InputStream is = new ByteArrayInputStream(smptemidifile);
+        s = MidiSystem.getSequence(is);
+        long duration = s.getMicrosecondLength() / 1000000;
+        System.out.println("Duration: "+duration+" seconds ");
+        if (duration > 14) {
+            throw new Exception("SMPTE time reader is broken! Test FAILED");
+        }
+        System.out.println("Test passed");
+    }
+
+    public static void printFile(String filename) throws Exception {
+        File file = new File(filename);
+        FileInputStream fis = new FileInputStream(file);
+        byte[] data = new byte[(int) file.length()];
+        fis.read(data);
+        String s = "";
+        for (int i=0; i<data.length; i++) {
+            s+=String.valueOf(data[i])+", ";
+            if (s.length()>72) {
+                System.out.println(s);
+                s="";
+            }
+        }
+        System.out.println(s);
+    }
+
+    // A MIDI file with SMPTE timing
+    static byte[] smptemidifile = {
+            77, 84, 104, 100, 0, 0, 0, 6, 0, 1, 0, 3, -30, 120, 77, 84, 114, 107, 0,
+            0, 0, 123, 0, -112, 30, 100, -113, 49, -128, 50, 100, -114, 69, -112, 31,
+            100, -114, 33, -128, 51, 100, -114, 55, -112, 32, 100, -114, 120, -128, 52,
+            100, -114, 40, -112, 33, 100, -114, 26, -128, 53, 100, -114, 26, -112, 34,
+            100, -114, 76, -128, 54, 100, -114, 12, -112, 35, 100, -114, 91, -128, 55,
+            100, -114, 69, -112, 36, 100, -114, 33, -128, 56, 100, -114, 55, -112, 37,
+            100, -114, 84, -128, 57, 100, -114, 40, -112, 38, 100, -114, 26, -128, 58,
+            100, -114, 26, -112, 39, 100, -113, 24, -128, 59, 100, -113, 60, -112, 40,
+            100, -113, 110, -128, 60, 100, -113, 96, -112, 41, 100, -113, 39, -128, 61,
+            100, 0, -1, 47, 0, 77, 84, 114, 107, 0, 0, 0, 4, 0, -1, 47, 0, 77, 84, 114,
+            107, 0, 0, 0, 4, 0, -1, 47, 0
+    };
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequence/SMPTEDuration.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.MidiEvent;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.Track;
+
+/**
+ * @test
+ * @bug 4702328
+ * @summary Wrong time in sequence for SMPTE based types
+ */
+public class SMPTEDuration {
+
+    public static void main(String args[]) throws Exception {
+         int[][] dataMes =  { {ShortMessage.NOTE_ON, 10, 0x24, 0x50} ,
+                 { ShortMessage.NOTE_OFF, 10, 0x24, 0x44 },
+                 { ShortMessage.NOTE_ON, 10, 0x24, 0x50 },
+                 { ShortMessage.NOTE_ON, 10, 0x26, 0x50 },
+                 { ShortMessage.NOTE_OFF, 10, 0x26, 0x53 } };
+         long[] ticks = { 0, 68, 240, 240, 286};
+         int res = 240;
+         ShortMessage msg;
+         Sequence midiData = null;
+         Track track;
+         boolean failed = false;
+
+
+         try {
+             midiData = new Sequence(Sequence.SMPTE_24 , res);
+         } catch (InvalidMidiDataException invMidiEx) {
+             invMidiEx.printStackTrace(System.out);
+             System.out.println("Unexpected InvalidMidiDataException: "
+                     + invMidiEx.getMessage());
+             failed = true;
+         }
+         track = midiData.createTrack();
+         for (int i = 0; i < dataMes.length; i++) {
+             msg = new ShortMessage();
+             try {
+                 msg.setMessage(dataMes[i][0], dataMes[i][1], dataMes[i][2],
+                         dataMes[i][3]);
+             } catch (InvalidMidiDataException invMidiEx) {
+                 invMidiEx.printStackTrace(System.out);
+                 System.out.println("Unexpected InvalidMidiDataException: "
+                         + invMidiEx.getMessage());
+                 failed = true;
+             }
+             track.add(new MidiEvent(msg, ticks[i]));
+         }
+         //   lengthInMs = (tickLength*1000000)/(divType*Res)
+         long micros = (long) ((midiData.getTickLength() * 1000000) / (res * Sequence.SMPTE_24));
+         if (midiData.getMicrosecondLength() != micros) {
+             failed = true;
+             System.out.println("getMicrosecondLength() returns wrong length: "
+                     + midiData.getMicrosecondLength());
+             System.out.println("getMicrosecondLength() must return length: "
+                     + micros);
+         }
+         if (midiData.getTickLength() != 286) {
+             failed = true;
+             System.out.println("getTickLength() returns wrong length: "
+                     + midiData.getTickLength());
+         }
+
+         if( failed == true ) {
+             throw new Exception("test failed");
+         } else {
+             System.out.println("Passed.");
+         }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequencer/LoopIAE.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.MidiEvent;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.Track;
+
+/**
+ * @test
+ * @bug 5025549
+ * @summary Verify that setLoopEndPoint throws IAE
+ */
+public class LoopIAE {
+
+    static ShortMessage MidiMsg3(int a, int b, int c) {
+        try {
+            ShortMessage msg = new ShortMessage();
+            msg.setMessage((byte)a,(byte)b,(byte)c);
+            return msg;
+        } catch(InvalidMidiDataException ex) {
+            throw new RuntimeException();
+        }
+    }
+
+    static boolean failed = false;
+
+    public static void main(String[] argv) throws Exception {
+        if (!hasSequencer()) {
+            return;
+        }
+        Sequencer sequencer = MidiSystem.getSequencer();
+        Sequence sequence = new Sequence(Sequence.PPQ, 240);
+        Track track = sequence.createTrack();
+
+        track.add(new MidiEvent(MidiMsg3(ShortMessage.NOTE_ON+0,45,100),0));
+        track.add(new MidiEvent(MidiMsg3(ShortMessage.NOTE_ON+0,45,0),0 + 240));
+        track.add(new MidiEvent(MidiMsg3(ShortMessage.NOTE_ON+9,45,100),10*20));
+        track.add(new MidiEvent(MidiMsg3(ShortMessage.NOTE_ON+9,45,0),10*20 + 10));
+
+        try {
+            sequencer.open();
+            sequencer.setSequence(sequence);
+            sequencer.setTempoInBPM(100);
+
+            System.out.println("Setting loop end point to 1");
+            sequencer.setLoopEndPoint(1);
+            System.out.println("  -> effectively: "+sequencer.getLoopEndPoint());
+            System.out.println("Setting loop start point to 2 -- should throw IAE");
+            sequencer.setLoopStartPoint(2);
+            System.out.println("  -> effectively: "+sequencer.getLoopStartPoint());
+            System.out.println("No IllegalArgumentException was thrown!");
+            failed = true;
+        } catch (IllegalArgumentException iae) {
+            System.out.println("IAE was thrown correctly.");
+        } catch (MidiUnavailableException mue) {
+            System.out.println("MidiUnavailableException was thrown: " + mue);
+            System.out.println("Cannot execute test.");
+        } catch (InvalidMidiDataException imEx) {
+            System.out.println("InvalidMidiDataException was thrown.");
+            imEx.printStackTrace();
+            System.out.println("Cannot execute test.");
+        } finally {
+            if (sequencer != null && sequencer.isOpen()) {
+                sequencer.close();
+            }
+        }
+        if (failed) {
+            throw new Exception("Test FAILED!");
+        }
+        System.out.println("test passed.");
+    }
+
+    static boolean hasSequencer() {
+        try {
+            Sequencer seq = MidiSystem.getSequencer();
+            if (seq != null) {
+                if (seq.isOpen()) {
+                    seq.close();
+                }
+                return true;
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        System.out.println("No sequencer available! Cannot execute test.");
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequencer/Looping.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.MetaEventListener;
+import javax.sound.midi.MetaMessage;
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiEvent;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.Track;
+
+/**
+ * @test
+ * @bug 4204105
+ * @summary RFE: add loop() method(s) to Sequencer
+ * @key intermittent
+ */
+public class Looping {
+
+    public static void main(String[] args) throws Exception {
+        out("4204105: RFE: add loop() method(s) to Sequencer");
+        boolean passed = testAll();
+        if (passed) {
+            out("Test PASSED.");
+        } else {
+            throw new Exception("Test FAILED.");
+        }
+    }
+
+    /**
+     * Execute the test on all available Sequencers.
+     *
+     * @return true if the test passed for all Sequencers, false otherwise
+     */
+    private static boolean testAll() throws Exception {
+        boolean result = true;
+        MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo();
+        for (int i = 0; i < devices.length; i++) {
+            MidiDevice device = MidiSystem.getMidiDevice(devices[i]);
+            if (device instanceof Sequencer) {
+                result &= testSequencer((Sequencer) device);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Execute the test on the passed Sequencer.
+     *
+     * @return true if the test is passed this Sequencer, false otherwise
+     */
+    private static boolean testSequencer(Sequencer seq) throws Exception{
+        boolean result = true;
+        out("testing: " + seq);
+
+        result &= testGetSet(seq);
+
+        seq.setSequence(createSequence());
+
+        result &= testGetSet(seq);
+
+        result &= testPlay(seq);
+
+        return result;
+    }
+
+    private static boolean testGetSet(Sequencer seq) {
+        boolean result = true;
+        Sequence sequence = seq.getSequence();
+        boolean isSequenceLoaded = (sequence != null);
+
+        out("TestGetSet");
+
+        try {
+            if (seq.getLoopStartPoint() != 0) {
+                out("start point", isSequenceLoaded,
+                    "isn't 0!");
+                result = false;
+            }
+        } catch (IllegalArgumentException iae) {
+            if (!isSequenceLoaded) {
+                out("Caught permissable IllegalArgumentException:");
+            } else {
+                out("Threw unacceptable IllegalArgumentException! FAILED");
+                result = false;
+            }
+            out(iae.toString());
+        }
+
+        if (seq.getLoopEndPoint() != -1) {
+            out("end point", isSequenceLoaded,
+                "isn't -1!");
+            result = false;
+        }
+
+        try {
+            seq.setLoopStartPoint(25);
+            if (seq.getLoopStartPoint() != 25) {
+                out("setLoopStartPoint()", isSequenceLoaded,
+                    "doesn't set the start point correctly!");
+                result = false;
+            }
+        } catch (IllegalArgumentException iae) {
+            if (!isSequenceLoaded) {
+                out("Caught permissable IllegalArgumentException:");
+            } else {
+                out("Threw unacceptable IllegalArgumentException! FAILED");
+                result = false;
+            }
+            out(iae.toString());
+        }
+
+        try {
+            seq.setLoopEndPoint(26);
+            if (seq.getLoopEndPoint() != 26) {
+                out("setLoopEndPoint()", isSequenceLoaded,
+                    "doesn't set the end point correctly!");
+                result = false;
+            }
+        } catch (IllegalArgumentException iae) {
+            if (!isSequenceLoaded) {
+                out("Caught permissable IllegalArgumentException:");
+            } else {
+                out("Threw unacceptable IllegalArgumentException! FAILED");
+                result = false;
+            }
+            out(iae.toString());
+        }
+
+        try {
+            seq.setLoopStartPoint(0);
+            if (seq.getLoopStartPoint() != 0) {
+                out("setLoopStartPoint()", isSequenceLoaded,
+                    "doesn't set the start point correctly!");
+                result = false;
+            }
+        } catch (IllegalArgumentException iae) {
+            if (!isSequenceLoaded) {
+                out("Caught permissable IllegalArgumentException:");
+            } else {
+                out("Threw unacceptable IllegalArgumentException! FAILED");
+                result = false;
+            }
+            out(iae.toString());
+        }
+
+        if (isSequenceLoaded) {
+            seq.setLoopEndPoint(sequence.getTickLength());
+            if (seq.getLoopEndPoint() != sequence.getTickLength()) {
+                out("setLoopEndPoint()", isSequenceLoaded,
+                    "doesn't set the end point correctly!");
+                result = false;
+            }
+        } else {
+            // fails
+            seq.setLoopEndPoint(-1);
+            if (seq.getLoopEndPoint() != -1) {
+                out("setLoopEndPoint()", isSequenceLoaded,
+                    "doesn't set the end point correctly!");
+                result = false;
+            }
+        }
+
+        if (seq.getLoopCount() != 0) {
+            out("loop count", isSequenceLoaded,
+                "isn't 0!");
+            result = false;
+        }
+
+        seq.setLoopCount(1001);
+        if (seq.getLoopCount() != 1001) {
+            out("setLoopCount()", isSequenceLoaded,
+                "doesn't set the loop count correctly!");
+            result = false;
+        }
+
+        seq.setLoopCount(Sequencer.LOOP_CONTINUOUSLY);
+        if (seq.getLoopCount() != Sequencer.LOOP_CONTINUOUSLY) {
+            out("setLoopCount(Sequencer.LOOP_CONTINUOUSLY)", isSequenceLoaded,
+                "doesn't set the loop count correctly!");
+            result = false;
+        }
+
+        try {
+            seq.setLoopCount(-55);
+            out("setLoopCount()", isSequenceLoaded,
+                "doesn't throw IllegalArgumentException on illegal value!");
+            result = false;
+        } catch (IllegalArgumentException e) {
+            // EXCEPTION IS EXPECTED
+            out("Caught permissable IAE");
+        }
+
+        seq.setLoopCount(0);
+        if (seq.getLoopCount() != 0) {
+            out("setLoopCount()", isSequenceLoaded,
+                "doesn't set the loop count correctly!");
+            result = false;
+        }
+
+        return result;
+    }
+
+    private static boolean testPlay(Sequencer seq) {
+        boolean result = true;
+        long stopTime;
+
+        out("TestPlay");
+
+        TestMetaEventListener listener = new TestMetaEventListener();
+        seq.addMetaEventListener(listener);
+        long startTime = System.currentTimeMillis();
+        try {
+            seq.open();
+            out("Playing sequence, length="+(seq.getMicrosecondLength()/1000)+"millis");
+            seq.start();
+            while (true) {
+                stopTime = listener.getStopTime();
+                if (stopTime != 0) {
+                    break;
+                }
+                try {
+                    Thread.sleep(100);
+                } catch (InterruptedException e) {
+                }
+            }
+            long measuredDuration = stopTime - startTime;
+            out("play duration (us): " + measuredDuration);
+        } catch (Exception e) {
+            out("test not executed; exception:");
+            e.printStackTrace();
+        }
+        seq.close();
+        return result;
+    }
+
+    /**
+     * Create a new Sequence for testing.
+     *
+     * @return a dummy Sequence, or null, if a problem occured while creating
+     *         the Sequence
+     */
+    private static Sequence createSequence() {
+        Sequence sequence = null;
+        int lengthInSeconds = 2;
+        long lengthInMicroseconds = lengthInSeconds * 1000000;
+        int resolution = 480;
+        long lengthInTicks = (lengthInMicroseconds * 120 * resolution) / 60000000l;
+        out("length in ticks: " + lengthInTicks);
+        try {
+            sequence = new Sequence(Sequence.PPQ, resolution, 1);
+            Track track = sequence.createTrack();
+            ShortMessage mm = new ShortMessage();
+            mm.setMessage(0xF6, 0, 0);
+            MidiEvent me = new MidiEvent(mm, lengthInTicks);
+            track.add(me);
+        } catch (InvalidMidiDataException e) {
+            // DO NOTHING
+        }
+        out("sequence length (ticks): " + sequence.getTickLength());
+        out("sequence length (us): " + sequence.getMicrosecondLength());
+        return sequence;
+    }
+
+
+    private static void out(String m1, boolean isSequenceLoaded, String m2) {
+        out(m1 + (isSequenceLoaded ? " with Sequence " : " without Sequence ") + m2);
+    }
+
+    private static void out(String message) {
+        System.out.println(message);
+    }
+
+    private static class TestMetaEventListener implements MetaEventListener {
+        private long stopTime;
+
+
+        public void meta(MetaMessage m) {
+            System.out.print("  Got MetaMessage: ");
+            if (m.getType() == 47) {
+                stopTime = System.currentTimeMillis();
+                System.out.println(" End Of Track -- OK");
+            } else {
+                System.out.println(" unknown. Ignored.");
+            }
+        }
+
+        public long getStopTime() {
+            return stopTime;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequencer/MetaCallback.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.midi.Instrument;
+import javax.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.MetaEventListener;
+import javax.sound.midi.MetaMessage;
+import javax.sound.midi.MidiEvent;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.Track;
+
+/**
+ * @test
+ * @bug 4347135
+ * @summary MIDI MetaMessage callback inconsistent
+ * @run main/othervm MetaCallback
+ */
+public class MetaCallback implements MetaEventListener {
+
+    static ShortMessage MidiMsg3(int a, int b, int c) {
+        try {
+            ShortMessage msg = new ShortMessage();
+            msg.setMessage((byte)a,(byte)b,(byte)c);
+            return msg;
+        } catch(InvalidMidiDataException ex) {
+            throw new RuntimeException();
+        }
+    }
+
+    //Synthesizer synth;
+    Instrument[] instruments;
+    Sequencer sequencer;
+    Sequence sequence;
+    Track track;
+
+    public static int TOTAL_COUNT = 100;
+
+    int metaCount = 0;
+    boolean finished = false;
+
+    MetaCallback() throws Exception {
+
+        sequencer=MidiSystem.getSequencer();
+        sequence=new Sequence(Sequence.PPQ,240);
+        track=sequence.createTrack();
+        sequencer.addMetaEventListener(this);
+
+        byte[] data = new byte[1];
+
+        track.add(new MidiEvent(MidiMsg3(ShortMessage.NOTE_ON+0,45,100),0));
+        track.add(new MidiEvent(MidiMsg3(ShortMessage.NOTE_ON+0,45,0),0 + 240));
+        int c;
+        for(c=0; c < TOTAL_COUNT; c++) {
+            data[0]=(byte)(c+1);
+            MetaMessage meta = new MetaMessage();
+            meta.setMessage(1, data, 1); // type, data, length
+            track.add(new MidiEvent(meta,c*20));
+        }
+        track.add(new MidiEvent(MidiMsg3(ShortMessage.NOTE_ON+9,45,100),c*20));
+        track.add(new MidiEvent(MidiMsg3(ShortMessage.NOTE_ON+9,45,0),c*20 + 10));
+
+        sequencer.setSlaveSyncMode(Sequencer.SyncMode.INTERNAL_CLOCK);
+        sequencer.setMasterSyncMode(Sequencer.SyncMode.INTERNAL_CLOCK);
+        sequencer.open();
+        sequencer.setSequence(sequence);
+        sequencer.setTempoInBPM(100);
+        System.out.println("Starting playback...");
+        this.start();
+        while (!finished && sequencer.getTickPosition() < sequencer.getTickLength()) {
+            System.out.println("Tick "+sequencer.getTickPosition()+"...");
+            Thread.sleep(1000);
+        }
+        System.out.println("Stopping playback...");
+        this.stop();
+        if (metaCount != TOTAL_COUNT) {
+            throw new Exception("Expected "+TOTAL_COUNT+" callbacks, but got "+metaCount+"!");
+        }
+    }
+    void start() {sequencer.start();}
+    void stop() {sequencer.stop();}
+
+    public void meta(MetaMessage msg) {
+        System.out.println(""+metaCount+": got "+msg);
+        if (msg.getType() == 0x2F) {
+            finished = true;
+        } else if (msg.getData().length > 0 && msg.getType() == 1) {
+            metaCount++;
+        }
+    }
+
+    public static void main(String[] argv) throws Exception {
+        if (hasSequencer()) {
+            new MetaCallback();
+            System.out.println("Test passed");
+        }
+    }
+
+    static boolean hasSequencer() {
+        try {
+            Sequencer seq = MidiSystem.getSequencer();
+            if (seq != null) {
+                seq.open();
+                seq.close();
+                return true;
+            }
+        } catch (Exception e) {}
+        System.out.println("No sequencer available! Cannot execute test.");
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequencer/Recording.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.MetaMessage;
+import javax.sound.midi.MidiEvent;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Receiver;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.Track;
+
+/**
+ * @test
+ * @bug 4932841
+ * @key intermittent
+ * @summary Sequencer's recording feature does not work
+ */
+public class Recording {
+
+    public static boolean failed = false;
+    public static boolean passed = false;
+    private static Sequencer seq = null;
+
+    public static void main(String[] args) throws Exception {
+        try {
+            seq = MidiSystem.getSequencer();
+
+            // create an arbitrary sequence which lasts 10 seconds
+            Sequence sequence = createSequence(10, 120, 240);
+
+            seq.setSequence(sequence);
+            out("Set Sequence to Sequencer. Tempo="+seq.getTempoInBPM());
+
+            Track track = sequence.createTrack();
+            int oldSize = track.size();
+            seq.recordEnable(track, -1);
+
+            seq.open();
+
+            // if getReceiver throws Exception, failed!
+            failed = true;
+            Receiver rec = seq.getReceiver();
+
+            // start recording and add various events
+            seq.startRecording();
+
+            // is exception from here on, not failed
+            failed = false;
+
+            if (!seq.isRecording()) {
+                failed = true;
+                throw new Exception("Sequencer did not start recording!");
+            }
+            if (!seq.isRunning()) {
+                failed = true;
+                throw new Exception("Sequencer started recording, but is not running!");
+            }
+
+            // first: add an event to the middle of the sequence
+            ShortMessage msg = new ShortMessage();
+            msg.setMessage(0xC0, 80, 00);
+            rec.send(msg, 5l * 1000l * 1000l);
+
+            Thread.sleep(1000);
+
+            // then add a real-time event
+            msg = new ShortMessage();
+            msg.setMessage(0xC0, 81, 00);
+            long secondEventTick = seq.getTickPosition();
+            rec.send(msg, -1);
+
+            seq.stopRecording();
+            if (seq.isRecording()) {
+                failed = true;
+                throw new Exception("Stopped recording, but Sequencer is still recording!");
+            }
+            if (!seq.isRunning()) {
+                failed = true;
+                throw new Exception("Stopped recording, but Sequencer but is not running anymore!");
+            }
+
+            seq.stop();
+            if (seq.isRunning()) {
+                failed = true;
+                throw new Exception("Stopped Sequencer, but it is still running!");
+            }
+
+            // now examine the contents of the recorded track:
+            // 1) number of events: should be 2 more
+            int newSize = track.size();
+            int addedEventCount = newSize - oldSize;
+
+            out("Added "+addedEventCount+" events to recording track.");
+            if (addedEventCount != 2) {
+                failed = true;
+                throw new Exception("Did not add 2 events!");
+            }
+
+            // 2) the first event should be at roughly "secondEventTick"
+            MidiEvent ev = track.get(0);
+            msg = (ShortMessage) ev.getMessage();
+            out("The first recorded event is at tick position: "+ev.getTick());
+            if (Math.abs(ev.getTick() - secondEventTick) > 1000) {
+                out(" -> but expected something like: "+secondEventTick+"! FAILED.");
+                failed = true;
+            }
+
+            ev = track.get(1);
+            msg = (ShortMessage) ev.getMessage();
+            out("The 2nd recorded event is at tick position: "+ev.getTick());
+            out(" -> sequence's tick length is "+seq.getTickLength());
+            if (Math.abs(ev.getTick() - (sequence.getTickLength() / 2)) > 1000) {
+                out(" -> but expected something like: "+(seq.getTickLength()/2)+"! FAILED.");
+                failed = true;
+            }
+
+            passed = true;
+        } catch (Exception e) {
+            out(e.toString());
+            if (!failed) out("Test not failed.");
+        }
+        if (seq != null) {
+            seq.close();
+        }
+
+        if (failed) {
+            throw new Exception("Test FAILED!");
+        }
+        else if (passed) {
+            out("Test Passed.");
+        }
+    }
+
+    /**
+     * Create a new Sequence for testing.
+     */
+    private static Sequence createSequence(int lengthInSeconds, int tempoInBPM,
+                                           int resolution) {
+        Sequence sequence = null;
+        long lengthInMicroseconds = lengthInSeconds * 1000000;
+        boolean createTempoEvent = true;
+        if (tempoInBPM == 0) {
+            tempoInBPM = 120;
+            createTempoEvent = false;
+            System.out.print("Creating sequence: "+lengthInSeconds+"sec, "
+                             +"resolution="+resolution+" ticks/beat...");
+        } else {
+            System.out.print("Creating sequence: "+lengthInSeconds+"sec, "
+                             +tempoInBPM+" beats/min, "
+                             +"resolution="+resolution+" ticks/beat...");
+        }
+        //long lengthInTicks = (lengthInMicroseconds * resolution) / tempoInBPM;
+        long lengthInTicks = (lengthInMicroseconds * tempoInBPM * resolution) / 60000000l;
+        //out("expected length in ticks: " + lengthInTicks);
+        try {
+            sequence = new Sequence(Sequence.PPQ, resolution);
+            Track track = sequence.createTrack();
+            if (createTempoEvent) {
+                int tempoInMPQ = (int) (60000000l / tempoInBPM);
+                MetaMessage tm = new MetaMessage();
+                byte[] msg = new byte[3];
+                msg[0] = (byte) (tempoInMPQ >> 16);
+                msg[1] = (byte) ((tempoInMPQ >> 8) & 0xFF);
+                msg[2] = (byte) (tempoInMPQ & 0xFF);
+
+                tm.setMessage(0x51 /* Meta Tempo */, msg, msg.length);
+                track.add(new MidiEvent(tm, 0));
+                //out("regtest: tempoInMPQ="+tempoInMPQ);
+                //out("Added tempo event: new size="+track.size());
+            }
+            ShortMessage mm = new ShortMessage();
+            mm.setMessage(0xF6, 0, 0);
+            MidiEvent me = new MidiEvent(mm, lengthInTicks);
+            track.add(me);
+            //out("Added realtime event: new size="+track.size());
+        } catch (InvalidMidiDataException e) {
+            out(e);
+        }
+        out("OK");
+
+        return sequence;
+    }
+
+    private static void out(Throwable t) {
+        t.printStackTrace(System.out);
+    }
+
+    private static void out(String message) {
+        System.out.println(message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequencer/SeqRecordDoesNotCopy.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.midi.MidiEvent;
+import javax.sound.midi.MidiMessage;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Receiver;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.Track;
+
+/**
+ * @test
+ * @bug 5048381
+ * @summary Sequencer doesn't create distinct messages when recording events.
+ * @key headful
+ */
+public class SeqRecordDoesNotCopy {
+    public static void main(String argv[]) throws Exception {
+        Sequencer s = MidiSystem.getSequencer();
+        s.open();
+        try {
+            Sequence seq = new Sequence(Sequence.PPQ, 384, 2);
+            s.setSequence(seq);
+            Track t = seq.getTracks()[0];
+            ShortMessage msg = new ShortMessage();
+            msg.setMessage(0x90, 0x40, 0x7F);
+            t.add(new MidiEvent(msg, 11000));
+            msg.setMessage(0x90, 0x40, 0x00);
+            t.add(new MidiEvent(msg, 12000));
+            t = seq.getTracks()[1];
+            s.recordEnable(t, -1);
+            System.out.println("Started recording...");
+            s.startRecording();
+            Receiver r = s.getReceiver();
+            Thread.sleep(100);
+            // send a normal message
+            System.out.println("Recording a normal NOTE ON message...");
+            msg.setMessage(0x90, 0x40, 0x6F);
+            r.send(msg, -1);
+            Thread.sleep(100);
+            // send a normal message
+            System.out.println("Recording a normal NOTE OFF message...");
+            msg.setMessage(0x90, 0x40, 0x00);
+            r.send(msg, -1);
+            Thread.sleep(100);
+            s.stop();
+            // now see if the messages were recorded
+            System.out.println("Recorded messages:");
+            int sameMessage = 0;
+            for (int i = 0; i < t.size(); i++) {
+                System.out.print(" "+(i+1)+". ");
+                printEvent(t.get(i));
+                if (t.get(i).getMessage() == msg) {
+                    System.out.println("## Failed: Same Message reference!");
+                    sameMessage++;
+                }
+            }
+            if (sameMessage > 0) {
+                System.out.println("## Failed: The same instance was recorded!");
+                throw new Exception("Test FAILED!");
+            }
+            System.out.println("Did not detect any duplicate messages.");
+            System.out.println("Test passed.");
+        } catch (Exception e) {
+            System.out.println("Unexpected Exception: "+e);
+            //e.printStackTrace();
+            throw new Exception("Test FAILED!");
+        } finally {
+            s.close();
+        }
+    }
+    public static void printEvent(MidiEvent event)
+    {
+        MidiMessage message = event.getMessage();
+        long tick = event.getTick();
+        byte[] data = message.getMessage();
+
+        StringBuffer sb = new StringBuffer((data.length * 3) - 1);
+
+        for (int i = 0; i < data.length; i++)
+        {
+                sb.append(toHexByteString(data[i]));
+                if (i < data.length - 1) sb.append(' ');
+        }
+        System.out.printf("%5d: %s%n", tick, sb);
+    }
+
+    private static String toHexByteString(int n)
+    {
+        if (n < 0) n &= 0xFF;
+        String s = Integer.toHexString(n).toUpperCase();
+        if (s.length() == 1) s = '0' + s;
+        return s;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequencer/SeqRecordsRealTimeEvents.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.midi.MidiEvent;
+import javax.sound.midi.MidiMessage;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Receiver;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.Track;
+
+/**
+ * @test
+ * @bug 5048381
+ * @summary Sequencer records real time messages into the sequence
+ * @key headful
+ */
+public class SeqRecordsRealTimeEvents {
+    public static void main(String argv[]) throws Exception {
+        Sequencer s = MidiSystem.getSequencer();
+        s.open();
+        try {
+            Sequence seq = new Sequence(Sequence.PPQ, 384, 2);
+            s.setSequence(seq);
+            Track t = seq.getTracks()[0];
+            ShortMessage msg = new ShortMessage();
+            msg.setMessage(0x90, 0x40, 0x7F);
+            t.add(new MidiEvent(msg, 11000));
+            msg = new ShortMessage();
+            msg.setMessage(0x90, 0x40, 0x00);
+            t.add(new MidiEvent(msg, 12000));
+            t = seq.getTracks()[1];
+            s.recordEnable(t, -1);
+            System.out.println("Started recording...");
+            s.startRecording();
+            Receiver r = s.getReceiver();
+            Thread.sleep(100);
+            int oldTrackSize = t.size();
+            // send a realtime message to the track
+            System.out.println("Recording real time message...");
+            msg = new ShortMessage();
+            msg.setMessage(0xF8, 0, 0);
+            r.send(msg, -1);
+            Thread.sleep(100);
+            // send a normal message
+            msg = new ShortMessage();
+            System.out.println("Recording a normal NOTE ON message...");
+            msg.setMessage(0x90, 0x40, 0x6F);
+            r.send(msg, -1);
+            Thread.sleep(100);
+            s.stop();
+            // now see if the messages were recorded
+            int newMessages = t.size() - oldTrackSize;
+            System.out.println("Recorded messages:");
+            for (int i = 0; i < t.size(); i++) {
+                System.out.print(" "+(i+1)+". ");
+                printEvent(t.get(i));
+            }
+            if (newMessages == 0) {
+                System.out.println("## Failed: No messages were recorded!");
+                throw new Exception("Test FAILED!");
+            } else if (newMessages == 1) {
+                System.out.println("Only one message was recorded. Correct!");
+            } else if (newMessages > 1) {
+                System.out.println("## Failed: 2 or more messages were recorded!");
+                throw new Exception("Test FAILED!");
+            }
+            System.out.println("Test passed.");
+        } catch (Exception e) {
+            System.out.println("Unexpected Exception: "+e);
+            //e.printStackTrace();
+            throw new Exception("Test FAILED!");
+        } finally {
+            s.close();
+        }
+    }
+    public static void printEvent(MidiEvent event)
+    {
+        MidiMessage message = event.getMessage();
+        long tick = event.getTick();
+        byte[] data = message.getMessage();
+
+        StringBuffer sb = new StringBuffer((data.length * 3) - 1);
+
+        for (int i = 0; i < data.length; i++)
+        {
+                sb.append(toHexByteString(data[i]));
+                if (i < data.length - 1) sb.append(' ');
+        }
+        System.out.printf("%5d: %s%n", tick, sb);
+    }
+
+    private static String toHexByteString(int n)
+    {
+        if (n < 0) n &= 0xFF;
+        String s = Integer.toHexString(n).toUpperCase();
+        if (s.length() == 1) s = '0' + s;
+        return s;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequencer/SeqStartRecording.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Sequencer;
+
+/**
+ * @test
+ * @bug 5001943
+ * @summary Sequencer.startRecording throws unexpected NPE
+ * @key headful
+ */
+public class SeqStartRecording {
+    public static void main(String argv[]) throws Exception {
+        Sequencer seq = MidiSystem.getSequencer();
+        seq.open();
+        try {
+            seq.startRecording();
+            System.out.println("Test passed.");
+        } catch (NullPointerException npe) {
+            System.out.println("Caught NPE: "+npe);
+            npe.printStackTrace();
+            throw new Exception("Test FAILED!");
+        } catch (Exception e) {
+            System.out.println("Unexpected Exception: "+e);
+            e.printStackTrace();
+            System.out.println("Test NOT failed.");
+        } finally {
+            seq.close();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequencer/SequencerCacheValues.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Sequencer;
+
+/**
+ * @test
+ * @bug 4716740
+ * @summary default sequencer does not set the tempo factor
+ */
+public class SequencerCacheValues {
+
+    static boolean failed = false;
+
+    public static void main(String args[]) throws Exception {
+        Sequencer seq = null;
+        int totalNumberOfSequencers = 0;
+
+        MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
+        for (int device=0; device<infos.length; device++) {
+            //seq = MidiSystem.getSequencer();
+            MidiDevice dev = MidiSystem.getMidiDevice(infos[device]);
+            if (dev instanceof Sequencer) {
+                seq = (Sequencer) dev;
+                totalNumberOfSequencers++;
+                System.out.println("Opening sequencer "+infos[device]);
+                try {
+                    seq.open();
+                    try {
+                        doTest(seq);
+                    } finally {
+                        if (seq != null) {
+                            seq.close();
+                            seq = null;
+                        }
+                    }
+                } catch (MidiUnavailableException mue) {
+                    System.err.println("MidiUnavailableException was thrown: " + mue);
+                    System.err.println("could not test this sequencer.");
+                }
+            }
+        }
+        if (totalNumberOfSequencers == 0) {
+            System.out.println("No sequencers installed!");
+            failed = true;
+        }
+        if (failed) {
+            throw new Exception("FAILED");
+        } else {
+            System.out.println("test OK");
+        }
+    }
+
+    public static boolean equalsFloat(float f1, float f2) {
+        return (f1-f2<0.0001) && (f2-f1<0.0001);
+    }
+
+    public static void doTest(Sequencer seq) throws Exception {
+        seq.setTempoInMPQ(3.0f);
+        System.out.println("Setting tempo in MPQ to "+3.0f);
+        if (!equalsFloat(seq.getTempoInMPQ(), 3.0f)) {
+            System.err.println("getTempoInMPQ() returns wrong value : "
+                + seq.getTempoInMPQ());
+            failed = true;
+        }
+
+        System.out.println("Setting tempo factor to "+2.0f);
+        seq.setTempoFactor(2.0f);
+        if (!equalsFloat(seq.getTempoFactor(), 2.0f)) {
+            System.err.println("getTempoFactor() returns: " + seq.getTempoFactor());
+            failed = true;
+        }
+
+        float bpmTempo = 120.0f;
+        System.out.println("Setting tempo to "+120.0f+"bpm");
+        seq.setTempoInBPM(bpmTempo);
+        if (!equalsFloat(seq.getTempoInMPQ(), (60000000.0f/seq.getTempoInBPM()))) {
+            System.err.println("getTempoInMPQ() returns: " + seq.getTempoInMPQ());
+            System.err.println("getTempoInBPM() returns: " + seq.getTempoInBPM());
+            failed = true;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequencer/SequencerSetMuteSolo.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.Sequencer;
+
+/**
+ * @test
+ * @bug 4713900
+ * @summary default Sequencer allows to set Mute for invalid track
+ */
+public class SequencerSetMuteSolo {
+
+    public static void main(String args[]) throws Exception {
+        if (!hasSequencer()) {
+            return;
+        }
+
+        //printMidiFile(args[0]);
+
+        boolean failed = false;
+        Sequencer seq = null;
+        Sequence midiData = getSequence();
+        int numTracks = midiData.getTracks().length;
+        int totalNumberOfSequencers = 0;
+        int totalNumberOfTestedSequencers = 0;
+
+        MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
+        for (int device=0; device<infos.length; device++) {
+            //seq = MidiSystem.getSequencer();
+            MidiDevice dev = MidiSystem.getMidiDevice(infos[device]);
+            if (dev instanceof Sequencer) {
+                seq = (Sequencer) dev;
+                totalNumberOfSequencers++;
+                System.out.println("Opening sequencer "+infos[device]);
+                try {
+                    seq.open();
+                    try {
+                        seq.setSequence(midiData);
+                        System.err.println("Number of tracks: " + numTracks);
+                        System.err.println("TrackMute["+numTracks+"] state was: " + seq.getTrackMute(numTracks));
+                        System.err.println("  setting to muted.");
+                        seq.setTrackMute(numTracks, true);
+                        System.err.println("  TrackMute["+numTracks+"] is now: " + seq.getTrackMute(numTracks));
+                        if (seq.getTrackMute(numTracks)) {
+                            failed = true;
+                        }
+                        System.err.println("TrackSolo["+numTracks+"] state was: " + seq.getTrackSolo(numTracks));
+                        System.err.println("  setting to solo.");
+                        seq.setTrackSolo(numTracks, true);
+                        System.err.println("  TrackSolo["+numTracks+"] is now: " + seq.getTrackSolo(numTracks));
+                        if (seq.getTrackSolo(numTracks)) {
+                            failed = true;
+                        }
+                        totalNumberOfTestedSequencers++;
+                    } finally {
+                        if (seq != null) {
+                            seq.close();
+                            seq = null;
+                        }
+                    }
+                } catch (MidiUnavailableException mue) {
+                    System.err.println("MidiUnavailableException was thrown: " + mue);
+                    System.err.println("could not test this sequencer.");
+                    return;
+                }
+            }
+        }
+        if (totalNumberOfSequencers == 0) {
+            System.out.println("No sequencers installed!");
+            failed = true;
+        }
+        if (totalNumberOfTestedSequencers == 0) {
+            System.out.println("Could not test any sequencers!");
+            failed = true;
+        }
+        if( failed ) {
+            throw new Exception("FAILED");
+        } else {
+            System.out.println("test OK");
+        }
+    }
+
+    public static String getString(byte b) {
+        //String res = Integer.toHexString(b & 0xFF).toUpperCase();
+        //while (res.length()<2) res="0"+res;
+        //return res;
+        return String.valueOf(b);
+    }
+
+
+    public static void printMidiFile(String filename) throws Exception {
+        File file = new File(filename);
+        FileInputStream fis = new FileInputStream(file);
+        byte[] data = new byte[(int) file.length()];
+        fis.read(data);
+        String s = "";
+        for (int i=0; i<data.length; i++) {
+                s+=getString(data[i])+", ";
+                if (s.length()>72) {
+                        System.out.println(s);
+                        s="";
+                }
+        }
+        System.out.println(s);
+    }
+
+    public static Sequence getSequence() throws Exception {
+        ByteArrayInputStream bais = new ByteArrayInputStream(pitchbend);
+        Sequence seq = MidiSystem.getSequence(bais);
+        return seq;
+    }
+
+    public static byte[] pitchbend = {
+        77, 84, 104, 100, 0, 0, 0, 6, 0, 1, 0, 2, 0, 120, 77, 84, 114, 107, 0, 0,
+        0, 27, 0, -1, 3, 19, 77, 73, 68, 73, 32, 116, 101, 115, 116, 32, 45, 32,
+        116, 114, 97, 99, 107, 32, 48, 0, -1, 47, 0, 77, 84, 114, 107, 0, 0, 0, -44,
+        0, -1, 3, 19, 77, 73, 68, 73, 32, 116, 101, 115, 116, 32, 45, 32, 116, 114,
+        97, 99, 107, 32, 49, 0, -64, 30, 0, -112, 68, 126, 0, -32, 6, 67, 0, 14,
+        71, 0, 20, 74, 0, 26, 77, 0, 32, 80, 0, 42, 85, 6, 50, 89, 6, 56, 92, 5,
+        66, 97, 6, 74, 101, 6, 80, 104, 11, 84, 106, 20, 76, 102, 6, 70, 99, 5, 60,
+        94, 6, 52, 90, 5, 44, 86, 4, 34, 81, 5, 26, 77, 5, 20, 74, 6, 10, 69, 5,
+        2, 65, 7, 0, 64, 42, -112, 66, 123, 11, 68, 0, 72, 63, 126, 4, 66, 0, 43,
+        -32, 0, 63, 6, 0, 60, 7, 0, 56, 6, 0, 53, 5, 0, 49, 5, 0, 43, 4, 0, 37, 3,
+        0, 30, 3, 0, 25, 3, 0, 19, 3, 0, 13, 4, 0, 8, 4, 0, 2, 4, 0, 0, 70, 0, 3,
+        5, 0, 9, 3, 0, 14, 7, 0, 16, 25, 0, 21, 5, 0, 25, 7, 0, 28, 5, 0, 32, 5,
+        0, 36, 5, 0, 41, 6, 0, 46, 5, 0, 50, 5, 0, 53, 4, 0, 58, 7, 0, 61, 7, 0,
+        64, 117, -112, 63, 0, 0, -1, 47, 0
+    };
+
+    static boolean hasSequencer() {
+        try {
+            Sequencer seq = MidiSystem.getSequencer();
+            if (seq != null) {
+                seq.open();
+                seq.close();
+                return true;
+            }
+        } catch (Exception e) {}
+        System.out.println("No sequencer available! Cannot execute test.");
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequencer/SequencerState.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.Sequencer;
+
+/**
+ * @test
+ * @bug 4913027
+ * @summary several Sequencer methods should specify behaviour on closed Sequencer
+ */
+public class SequencerState {
+
+    private static boolean hasSequencer() {
+        try {
+            Sequencer seq = MidiSystem.getSequencer();
+            if (seq != null) {
+                seq.open();
+                seq.close();
+                return true;
+            }
+        } catch (Exception e) {}
+        System.out.println("No sequencer available! Cannot execute test.");
+        return false;
+    }
+
+
+    public static void main(String[] args) throws Exception {
+        out("4913027: several Sequencer methods should should specify behaviour on closed Sequencer");
+        if (hasSequencer()) {
+            boolean passed = testAll();
+            if (passed) {
+                out("Test PASSED.");
+            } else {
+                throw new Exception("Test FAILED.");
+            }
+        }
+    }
+
+    /**
+     * Execute the test on all available Sequencers.
+     *
+     * @return true if the test passed for all Sequencers, false otherwise
+     */
+    private static boolean testAll() throws Exception {
+        boolean result = true;
+        MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo();
+        for (int i = 0; i < devices.length; i++) {
+            MidiDevice device = MidiSystem.getMidiDevice(devices[i]);
+            if (device instanceof Sequencer) {
+                result &= testSequencer((Sequencer) device);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Execute the test on the passed Sequencer.
+     *
+     * @return true if the test is passed this Sequencer, false otherwise
+     */
+    private static boolean testSequencer(Sequencer seq) throws Exception {
+        boolean result = true;
+
+        out("testing: " + seq);
+        /* test calls in closed state.
+         */
+        if (seq.isOpen()) {
+            out("Sequencer is already open, cannot test!");
+            return result;
+        }
+
+        try {
+            seq.start();
+            out("closed state: start() does not throw IllegalStateException!");
+            result = false;
+        } catch (IllegalStateException e) {
+        }
+
+        try {
+            seq.stop();
+            out("closed state: stop() does not throw IllegalStateException!");
+            result = false;
+        } catch (IllegalStateException e) {
+        }
+
+        try {
+            seq.startRecording();
+            out("closed state: startRecording() does not throw IllegalStateException!");
+            result = false;
+        } catch (IllegalStateException e) {
+        }
+
+        try {
+            seq.stopRecording();
+            out("closed state: stopRecording() does not throw IllegalStateException!");
+            result = false;
+        } catch (IllegalStateException e) {
+        }
+
+        Sequence sequence = createSequence();
+        if (sequence == null) {
+            out("created Sequence is null, cannot test!");
+            return result;
+        }
+        try {
+            seq.setSequence(sequence);
+        } catch (IllegalStateException e) {
+            out("closed state: setSequence(Sequence) throws IllegalStateException!");
+            result = false;
+        }
+
+        InputStream inputStream = createSequenceInputStream();
+        if (inputStream == null) {
+            out("created InputStream is null, cannot test!");
+            return result;
+        }
+        try {
+            seq.setSequence(inputStream);
+        } catch (IllegalStateException e) {
+            out("closed state: setSequence(InputStream) throws IllegalStateException!");
+            result = false;
+        }
+
+        try {
+            seq.getSequence();
+        } catch (IllegalStateException e) {
+            out("closed state: getSequence() throws IllegalStateException!");
+            result = false;
+        }
+
+        /* test calls in open state.
+         */
+        seq.open();
+        if (! seq.isOpen()) {
+            out("Sequencer is not open, cannot test!");
+            return result;
+        }
+
+        try {
+            seq.start();
+        } catch (IllegalStateException e) {
+            out("open state: start() throws IllegalStateException!");
+            result = false;
+        }
+
+        try {
+            seq.stop();
+        } catch (IllegalStateException e) {
+            out("open state: stop() throws IllegalStateException!");
+            result = false;
+        }
+
+        try {
+            seq.startRecording();
+        } catch (IllegalStateException e) {
+            out("open state: startRecording() throws IllegalStateException!");
+            result = false;
+        }
+
+        try {
+            seq.stopRecording();
+        } catch (IllegalStateException e) {
+            out("open state: stopRecording() throws IllegalStateException!");
+            result = false;
+        }
+
+        sequence = createSequence();
+        if (sequence == null) {
+            out("created Sequence is null, cannot test!");
+            return result;
+        }
+        try {
+            seq.setSequence(sequence);
+        } catch (IllegalStateException e) {
+            out("open state: setSequence(Sequence) throws IllegalStateException!");
+            result = false;
+        }
+
+        inputStream = createSequenceInputStream();
+        if (inputStream == null) {
+            out("created InputStream is null, cannot test!");
+            return result;
+        }
+        try {
+            seq.setSequence(inputStream);
+        } catch (IllegalStateException e) {
+            out("open state: setSequence(InputStream) throws IllegalStateException!");
+            result = false;
+        }
+
+        try {
+            seq.getSequence();
+        } catch (IllegalStateException e) {
+            out("open state: getSequence() throws IllegalStateException!");
+            result = false;
+        }
+
+        seq.close();
+        return result;
+    }
+
+    /**
+     * Create a new Sequence for testing.
+     *
+     * @return a dummy Sequence, or null, if a problem occured while creating
+     *         the Sequence
+     */
+    private static Sequence createSequence() {
+        Sequence sequence = null;
+        try {
+            sequence = new Sequence(Sequence.PPQ, 480, 1);
+        } catch (InvalidMidiDataException e) {
+            // DO NOTHING
+        }
+        return sequence;
+    }
+
+    /**
+     * Create a new InputStream containing a Sequence for testing.
+     *
+     * @return an InputStream containing a dummy Sequence, or null, if a problem
+     *         occured while creating the InputStream
+     */
+    private static InputStream createSequenceInputStream() {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        Sequence sequence = createSequence();
+        if (sequence == null) {
+            return null;
+        }
+        try {
+            MidiSystem.write(sequence, 0, baos);
+            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+            return bais;
+        } catch (IOException e) {
+            return null;
+        }
+    }
+
+
+    private static void out(String message) {
+        System.out.println(message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequencer/SetTickPosition.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.midi.MidiEvent;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.Track;
+
+/**
+ * @test
+ * @bug 4493775
+ * @summary Sequncer method, setTickPosition(long) doesnot set the Tick position
+ */
+public class SetTickPosition {
+        private static boolean testPassed = true;
+
+        public void runTest()
+        {
+            Sequencer theSequencer = null;
+            try
+            {
+                System.out.print("Getting Sequencer...");
+                theSequencer = MidiSystem.getSequencer();
+                System.out.println("got "+theSequencer);
+
+                if(!(theSequencer.isOpen()))
+                {
+                    System.out.println("Opening Sequencer...");
+                    theSequencer.open();
+
+                    if(!(theSequencer.isOpen()))
+                    {
+                        System.out.println("Unable to open the Sequencer. Test NOT FAILED.");
+                        return;
+                    }
+                }
+
+                System.out.println("theSequencer is open!\n");
+
+                System.out.println("Creating New Sequence...");
+                Sequence theSequence = new Sequence(Sequence.PPQ, 120);
+
+                System.out.println("Adding Track To Sequence...");
+                Track theTrack = theSequence.createTrack();
+
+                int theChannel = 0;
+
+                int theNote = 60;
+                int theVelocity = 100;
+                ShortMessage theShortMessage = new ShortMessage();
+
+                for (int tick=0; tick<2000; tick+=120) {
+                    //System.out.println("Adding NOTE_ON To Track At Tick: " + tick + "...\n");
+                    theShortMessage.setMessage(ShortMessage.NOTE_ON, theChannel, theNote, theVelocity);
+                    MidiEvent theMidiEvent = new MidiEvent(theShortMessage, tick);
+                    theTrack.add(theMidiEvent);
+
+                    //System.out.println("Adding NOTE_OFF To Track At Tick: " + (tick+60) + "...\n");
+                    theShortMessage.setMessage(ShortMessage.NOTE_OFF, theChannel, theNote, theVelocity);
+                    theMidiEvent = new MidiEvent(theShortMessage, tick+60);
+                    theTrack.add(theMidiEvent);
+                }
+                theSequencer.setSequence(theSequence);
+
+                float theTempoInBPM = 120;
+                theSequencer.setTempoInBPM(theTempoInBPM);
+                long theTickLengthOfSequence = theSequencer.getTickLength();
+                System.out.println("Length Of Sequence In Ticks: " + theTickLengthOfSequence);
+                System.out.println("Sequence resolution: " + theSequencer.getSequence().getResolution());
+
+                theSequencer.start();
+                for(long theTickPosition = 0; theTickPosition < theTickLengthOfSequence; theTickPosition += (theTickLengthOfSequence / 10))
+                {
+                    System.out.println("Now Setting Tick Position To: " + theTickPosition);
+                    theSequencer.setTickPosition(theTickPosition);
+
+                    long theCurrentTickPosition = theSequencer.getTickPosition();
+                    long theCurrentMsPosition = (long) (theSequencer.getMicrosecondPosition()/1000);
+                    System.out.println("IsRunning()=" + theSequencer.isRunning());
+                    System.out.println("Now Current Tick Position Is: " + theCurrentTickPosition);
+                    //System.out.println("Now Current micro Position Is: " + theCurrentMsPosition);
+                    System.out.println("");
+
+                    try {
+                        Thread.sleep(800);
+                    } catch (InterruptedException ie) {}
+
+                    // last time, set tick pos to 0
+                    if (theTickPosition>0 && theTickPosition<(theTickLengthOfSequence / 10)) {
+                        theTickPosition=(theTickLengthOfSequence / 10);
+                    }
+
+                    // 30 = 1/4 * 120, the resolution of the sequence
+                    if(Math.abs(theCurrentTickPosition - theTickPosition) > 30) {
+                        System.out.println("theCurrentTickPosition != theTickPosition!");
+                        testPassed = false;
+                    }
+                }
+
+            }
+            catch (Exception ex) { ex.printStackTrace(); }
+            if (theSequencer != null) {
+                theSequencer.close();
+            }
+            if (testPassed) {
+                System.out.println("Test Passed.");
+            }
+        }
+
+    public static void main(String[] args) throws Exception {
+        SetTickPosition thisTest = new SetTickPosition();
+        thisTest.runTest();
+        if (!testPassed) {
+            throw new Exception("Test FAILED");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequencer/TickLength.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.MetaEventListener;
+import javax.sound.midi.MetaMessage;
+import javax.sound.midi.MidiEvent;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.Track;
+
+/**
+ * @test
+ * @bug 4427890
+ * @run main/othervm TickLength
+ * @summary Sequencer.getTickLength() and Sequence.getTickLength() report the
+ *          wrong length
+ */
+public class TickLength implements MetaEventListener {
+    private Sequence          theSequence;
+    private Sequencer         theSequencer;
+
+    public TickLength() {
+     this.initMidiCompoments();
+     System.out.println("Got Sequencer "+theSequencer);
+     theSequence = this.generateSequence();
+     try {
+       theSequencer.setSequence(theSequence);
+     }
+     catch(Exception e) {
+       System.out.println(this.getClass()+"\tCannot set sequence to sequencer ("+e+")");
+       return;
+     }
+    }
+
+    public  void start() {
+     theSequencer.start();
+    }
+
+    /*
+     instantiate the necessary midi components
+    */
+    private boolean initMidiCompoments() {
+
+
+     try {
+       theSequencer = MidiSystem.getSequencer();
+     }
+     catch(Exception e) {
+       System.out.println(this.getClass()+"\tSequencer Device not supported"+e+")");
+       return false;
+     }
+
+     try {
+       theSequencer.open();
+     }
+     catch(Exception e) {
+       System.out.println(this.getClass()+"Cannot open Sequencer Device");
+       return false;
+     }
+     if(!theSequencer.addMetaEventListener(this)) {
+       System.out.println(this.getClass()+"\tCould not register MetaEventListener - there will be problems with scrolling! ");
+       return false;
+     }
+     return true;
+    }
+
+    static int lastTick = 0;
+
+    private Sequence generateSequence() {
+     MidiEvent dummyMidiEvent;
+     ShortMessage dummyShortMessage;
+     Sequence dummySequence        = null;
+     Track[] allTracks ;
+     Track theTrack;
+
+     try {
+       dummySequence = new Sequence(Sequence.PPQ,1500);
+     }
+     catch(InvalidMidiDataException e) {
+       System.out.println("O o "+e);
+     }
+
+     dummySequence.createTrack();
+     allTracks = dummySequence.getTracks();
+     theTrack = allTracks[0];
+    lastTick = 0;
+     for(int i=0;i<20; i++) {
+       theTrack.add(this.createShortMidiEvent(ShortMessage.NOTE_ON, 2, 30+i, 100,100+1000*i));
+       theTrack.add(this.createMetaMidiEvent(1,"start",100+1000*i));
+       lastTick = (1000*i)+600;
+       theTrack.add(this.createShortMidiEvent(ShortMessage.NOTE_OFF, 2, 30+i, 100, lastTick));
+       theTrack.add(this.createMetaMidiEvent(1,"end",lastTick));
+     }
+
+     return dummySequence;
+    }
+
+    /*
+     A method to create a short midi event (sound)
+    */
+
+    public MidiEvent createShortMidiEvent(int theCommand, int theChannel, int theData1, int theData2, long theTime) {
+     ShortMessage dummyShortMessage;
+     MidiEvent    dummyMidiEvent;
+
+     try {
+       dummyShortMessage = new ShortMessage();
+       dummyShortMessage.setMessage(theCommand, theChannel, theData1, theData2);
+       dummyMidiEvent    = new MidiEvent(dummyShortMessage,theTime);
+     }
+     catch (Exception e) {
+       System.out.println(this.getClass()+"\t"+e);
+       return null;
+     }
+
+     return dummyMidiEvent;
+    }
+
+    /*
+     A method to create a meta midi event (used in  meta() method)
+    */
+    public MidiEvent createMetaMidiEvent(int theType, String theData1, long theTime) {
+     MetaMessage  dummyMetaMessage;
+     MidiEvent    dummyMidiEvent;
+
+     try {
+       dummyMetaMessage = new MetaMessage();
+       dummyMetaMessage.setMessage(theType, theData1.getBytes(), theData1.length());
+       dummyMidiEvent    = new MidiEvent(dummyMetaMessage,theTime);
+     }
+     catch (Exception e) {
+       System.out.println(e);
+       return null;
+     }
+
+     return dummyMidiEvent;
+    }
+
+    /*
+     the method is activated by each meta midi event
+     it puts out the actual tick position, as well as the WRONG total tick length and the RIGHT
+     tick length using the work around by dividing the total length by 64
+    */
+    public void meta(MetaMessage p1) {
+     if(p1.getType() ==47) {
+       return;
+     }
+     System.out.println("getTickPosition:\t"+theSequencer.getTickPosition()
+         +"\t Sequencer.getTickLength:\t"+theSequencer.getTickLength()
+         +"\tReal Length:\t"+lastTick
+         +"\t Sequence.getTickLength:\t"+theSequence.getTickLength()
+         //(theSequencer.getTickLength()/64));
+         );
+    }
+
+    public void checkLengths() throws Exception {
+        System.out.println("Sequencer.getTickLength() = "+theSequencer.getTickLength());
+        System.out.println("Sequence.getTickLength() = "+theSequence.getTickLength());
+        long diff = theSequencer.getTickLength() - theSequence.getTickLength();
+        if (diff > 100 || diff < -100) {
+                throw new Exception("Difference too large! Failed.");
+        }
+        System.out.println("Passed");
+    }
+
+    public static void main(String[] args) throws Exception {
+        if (!hasSequencer()) {
+            return;
+        }
+         TickLength tlt = new TickLength();
+         //tlt.start();
+         tlt.checkLengths();
+    }
+
+    static boolean hasSequencer() {
+        try {
+            Sequencer seq = MidiSystem.getSequencer();
+            if (seq != null) {
+                seq.open();
+                seq.close();
+                return true;
+            }
+        } catch (Exception e) {}
+        System.out.println("No sequencer available! Cannot execute test.");
+        return false;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/ShortMessage/FastShortMessage.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+
+import javax.sound.midi.MidiEvent;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.Track;
+
+/**
+ * @test
+ * @bug 4851018
+ * @summary MidiMessage.getLength and .getData return wrong values.
+ *          also: 4890405: Reading MidiMessage byte array fails in 1.4.2
+ */
+public class FastShortMessage {
+    public static void main(String args[]) throws Exception {
+        int[] dataMes =  {ShortMessage.NOTE_ON | 9, 0x24, 0x50};
+        int res = 240;
+        Sequence midiData = new Sequence(Sequence.PPQ, res);
+
+        Track track = midiData.createTrack();
+        ShortMessage msg = new ShortMessage();
+        msg.setMessage(dataMes[0], dataMes[1], dataMes[2]);
+        track.add(new MidiEvent(msg, 0));
+
+        // save sequence to outputstream
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        MidiSystem.write(midiData, 0, baos);
+
+        // reload that sequence
+        InputStream is = new ByteArrayInputStream(baos.toByteArray());
+        Sequence seq = MidiSystem.getSequence(is);
+
+        track = seq.getTracks()[0];
+        msg = (ShortMessage) (track.get(0).getMessage());
+        byte[] msgData = msg.getMessage();
+
+        if (msgData.length != dataMes.length
+         || (msgData[0] & 0xFF) != dataMes[0]
+         || (msgData[1] & 0xFF) != dataMes[1]
+         || (msgData[2] & 0xFF) != dataMes[2]) {
+            throw new Exception("test failed. read length="+msgData.length);
+        }
+        System.out.println("Test Passed.");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/ShortMessage/FastShortMessage2.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+
+import javax.sound.midi.MidiEvent;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.Track;
+
+/**
+ * @test
+ * @bug 5011306
+ * @summary FastShortMessage.setMessage does not use the data2 parameter
+ */
+public class FastShortMessage2 {
+
+    public static void main(String args[]) throws Exception {
+        int[] dataMes =  {ShortMessage.NOTE_ON | 9, 0x24, 0x50};
+
+        Sequence midiData = new Sequence(Sequence.PPQ, 240);
+        Track track = midiData.createTrack();
+        ShortMessage msg = new ShortMessage();
+        msg.setMessage(dataMes[0], dataMes[1], dataMes[2]);
+        track.add(new MidiEvent(msg, 0));
+        // save sequence to outputstream
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        MidiSystem.write(midiData, 0, baos);
+        // reload that sequence
+        InputStream is = new ByteArrayInputStream(baos.toByteArray());
+        Sequence seq = MidiSystem.getSequence(is);
+        track = seq.getTracks()[0];
+        msg = (ShortMessage) (track.get(0).getMessage());
+        if (!msg.getClass().toString().contains("FastShortMessage")) {
+            System.out.println("msg is not FastShortMessage, this test is useless then..."+msg.getClass());
+        }
+
+        msg.setMessage(dataMes[0], dataMes[1], dataMes[2]);
+        byte[] msgData = msg.getMessage();
+
+        if (msgData.length != dataMes.length
+         || (msgData[0] & 0xFF) != dataMes[0]
+         || (msgData[1] & 0xFF) != dataMes[1]
+         || (msgData[2] & 0xFF) != dataMes[2]) {
+            System.out.println("status="+(msgData[0] & 0xFF)+" and expected "+dataMes[0]);
+            System.out.println("data1="+(msgData[1] & 0xFF)+" and expected "+dataMes[1]);
+            System.out.println("data2="+(msgData[2] & 0xFF)+" and expected "+dataMes[2]);
+            throw new Exception("Test FAILED!");
+        }
+        System.out.println("Test Passed.");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Soundbanks/ExtraCharInSoundbank.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.midi.Instrument;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Soundbank;
+import javax.sound.midi.Synthesizer;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Mixer;
+
+/**
+ * @test
+ * @bug 4429762
+ * @summary Some instrument names in some soundbanks include bad extra characters
+ */
+public class ExtraCharInSoundbank {
+
+    private static void printName(String loadedName)
+    {
+        System.out.println("Loaded Name: " + loadedName);
+        byte[] theLoadedNameByteArray = loadedName.getBytes();
+
+        System.out.print("Name Bytes: ");
+        for(int i = 0; i < theLoadedNameByteArray.length; i++)
+            System.out.print((Integer.toHexString((int)theLoadedNameByteArray[i]).toUpperCase()) + " ");
+        System.out.println("");
+        System.out.println("");
+    }
+
+    private static boolean containsControlChar(String name) {
+        byte[] bytes = name.getBytes();
+        for (int i = 0; i < bytes.length; i++) {
+            if (bytes[i] < 32) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static boolean checkInstrumentNames(Synthesizer theSynthesizer)
+    {
+        boolean containsControlCharacters = false;
+
+        Instrument[] theLoadedInstruments = theSynthesizer.getLoadedInstruments();
+
+        System.out.println("Checking soundbank...");
+        for(int theInstrumentIndex = 0; theInstrumentIndex < theLoadedInstruments.length; theInstrumentIndex++) {
+            String name = theLoadedInstruments[theInstrumentIndex].getName();
+            if (containsControlChar(name)) {
+                containsControlCharacters = true;
+                System.out.print("Instrument[" + theInstrumentIndex + "] contains unexpected control characters: ");
+                printName(name);
+            }
+        }
+        return !containsControlCharacters;
+    }
+
+    public static void main(String[] args) throws Exception {
+        // the internal synthesizer needs a soundcard to work properly
+        if (!isSoundcardInstalled()) {
+            return;
+        }
+        Synthesizer theSynth = MidiSystem.getSynthesizer();
+        System.out.println("Got synth: "+theSynth);
+        theSynth.open();
+        try {
+            Soundbank theSoundbank = theSynth.getDefaultSoundbank();
+            System.out.println("Got soundbank: "+theSoundbank);
+            theSynth.loadAllInstruments(theSoundbank);
+            try {
+                    if (!checkInstrumentNames(theSynth)) {
+                            throw new Exception("Test failed");
+                    }
+            } finally {
+                    theSynth.unloadAllInstruments(theSoundbank);
+            }
+        } finally {
+            theSynth.close();
+        }
+        System.out.println("Test passed.");
+    }
+
+    /**
+     * Returns true if at least one soundcard is correctly installed
+     * on the system.
+     */
+    public static boolean isSoundcardInstalled() {
+        boolean result = false;
+        try {
+            Mixer.Info[] mixers = AudioSystem.getMixerInfo();
+            if (mixers.length > 0) {
+                result = AudioSystem.getSourceDataLine(null) != null;
+            }
+        } catch (Exception e) {
+            System.err.println("Exception occured: "+e);
+        }
+        if (!result) {
+            System.err.println("Soundcard does not exist or sound drivers not installed!");
+            System.err.println("This test requires sound drivers for execution.");
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Soundbanks/GetSoundBankIOException.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.MidiSystem;
+
+/**
+ * @test
+ * @bug 4629810
+ * @summary MidiSystem.getSoundbank() throws unexpected IOException
+ */
+public class GetSoundBankIOException {
+
+    public static void main(String args[]) throws Exception {
+        boolean failed = false;
+        try {
+            String filename = "GetSoundBankIOException.java";
+            System.out.println("Opening "+filename+" as soundbank...");
+            File midiFile = new File(System.getProperty("test.src", "."), filename);
+            MidiSystem.getSoundbank(midiFile);
+            //Soundbank sBank = MidiSystem.getSoundbank(new NonMarkableIS());
+            System.err.println("InvalidMidiDataException was not thrown!");
+            failed = true;
+        } catch (InvalidMidiDataException invMidiEx) {
+            System.err.println("InvalidMidiDataException was thrown. OK.");
+        } catch (IOException ioEx) {
+            System.err.println("Unexpected IOException was caught!");
+            System.err.println(ioEx.getMessage());
+            ioEx.printStackTrace();
+            failed = true;
+        }
+
+        if (failed) throw new Exception("Test FAILED!");
+        System.out.println("Test passed.");
+    }
+
+    private static class NonMarkableIS extends InputStream {
+        int counter = 0;
+
+        public NonMarkableIS() {
+        }
+
+        public int read() throws IOException {
+            if (counter > 1000) return -1;
+            return (++counter) % 256;
+        }
+
+        public synchronized void mark(int readlimit) {
+            System.out.println("Called mark with readlimit= "+readlimit);
+        }
+
+        public synchronized void reset() throws IOException {
+            throw new IOException("mark/reset not supported");
+        }
+
+        public boolean markSupported() {
+            return false;
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Synthesizer/AsynchronousMidiChannel.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.PrintStream;
+
+import javax.sound.midi.Instrument;
+import javax.sound.midi.MidiChannel;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Soundbank;
+import javax.sound.midi.Synthesizer;
+
+/**
+ * @test
+ * @bug 4987585
+ * @summary Some MidiChannel methods are asynchronous
+ */
+public class AsynchronousMidiChannel {
+    static PrintStream log = System.err;
+    static PrintStream ref = System.out;
+
+    public static void main(String args[]) {
+        doIt(args);
+    }
+
+    public static void doIt(String args[]) {
+        Synthesizer synth = null;
+        MidiChannel mChanArr[];
+        MidiChannel chan = null;
+        boolean failed = false;
+        int i = 0;
+        int chanNum = 0;
+
+        int val = 1;
+        int contr = 0;
+        Soundbank sBank;
+        Instrument[] insArr;
+        Instrument instr = null;
+        Object ev = new Object();
+
+        try {
+            synth = MidiSystem.getSynthesizer();
+            System.out.println("Got synth: "+synth);
+            synth.open();
+
+            int latency = (int) synth.getLatency();
+            System.out.println("  -> latency: "
+                               +latency
+                               +" microseconds");
+
+            mChanArr = synth.getChannels();
+            while ((i < mChanArr.length) && (chan == null)) {
+                chanNum = i;
+                chan = mChanArr[i++];
+            }
+            if (chan == null) {
+                System.out.println("No channels in "
+                                   +"this synthesizer!");
+                return;
+            }
+            System.out.println("Got MidiChannel: "+chan);
+
+
+            sBank = synth.getDefaultSoundbank();
+            if (sBank == null) {
+                System.out.println("No default sound bank!");
+                return;
+            }
+
+
+            insArr = sBank.getInstruments();
+            for (int j = 0; j < insArr.length; j++) {
+                if (insArr[j].getPatch().getBank() == val) {
+                    instr = insArr[j];
+                    synth.loadInstrument(instr);
+                }
+            }
+            if (instr == null) {
+                System.out.println("No instr. with this bank!");
+                return;
+            }
+
+            chan.controlChange(contr, val);
+
+            // need to respect the synthesizer's latency
+            if (latency > 0) {
+                try {
+                    Thread.sleep(latency/1000);
+                } catch (InterruptedException inEx) {
+                }
+            }
+
+            if (chan.getController(contr) != val) {
+                failed = true;
+                System.err.println("getController() does not "
+                                   +"return proper value: "
+                + chan.getController(contr));
+            }  else {
+                System.out.println("getController("
+                + contr + ") returns proper value: "
+                + chan.getController(contr));
+            }
+
+        } catch (MidiUnavailableException mue) {
+            System.err.println("MidiUnavailableException was "
+                               +"thrown: " + mue);
+            System.out.println("could not test.");
+            return;
+        } catch(SecurityException se) {
+            se.printStackTrace();
+            System.err.println("Sound access is not denied but "
+            + "SecurityException was thrown!");
+            return;
+
+        } finally {
+            if (synth != null) synth.close();
+        }
+
+
+        if (failed == true) {
+            System.out.println("test failed");
+        } else {
+            System.out.println("OKAY");
+        }
+        return;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Synthesizer/Receiver/bug6186488.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiMessage;
+import javax.sound.midi.MidiSystem;
+
+/**
+ * @test
+ * @bug 6186488
+ * @summary Tests that software Java Syntesizer processed
+ *          non-ShortMessage-derived messages
+ * @run main/manual=yesno bug6186488
+ */
+public class bug6186488 {
+    public static void main(String[] args) throws Exception {
+        MidiDevice/*Synthesizer*/ synth = null;
+
+        try {
+            synth = MidiSystem.getSynthesizer();
+            //synth = MidiSystem.getMidiDevice(infos[0]);
+
+            System.out.println("Synthesizer: " + synth.getDeviceInfo());
+            synth.open();
+            MidiMessage msg = new GenericMidiMessage(0x90, 0x3C, 0x40);
+            //ShortMessage msg = new ShortMessage();
+            //msg.setMessage(0x90, 0x3C, 0x40);
+
+            synth.getReceiver().send(msg, 0);
+            Thread.sleep(2000);
+
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            throw ex;
+        } finally {
+            if (synth != null && synth.isOpen())
+                synth.close();
+        }
+        System.out.print("Did you heard a note? (enter 'y' or 'n') ");
+        int result = System.in.read();
+        System.in.skip(1000);
+        if (result == 'y' || result == 'Y')
+        {
+            System.out.println("Test passed sucessfully.");
+        }
+        else
+        {
+            System.out.println("Test FAILED.");
+            throw new RuntimeException("Test failed.");
+        }
+    }
+
+    private static class GenericMidiMessage extends MidiMessage {
+        GenericMidiMessage(int... message) {
+            super(new byte[message.length]);
+            for (int i=0; i<data.length; i++) {
+                data[i] = (byte)(0xFF & message[i]);
+            }
+        }
+
+        GenericMidiMessage(byte... message) {
+            super(message);
+        }
+
+        public Object clone() {
+            return new GenericMidiMessage((byte[])data.clone());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Synthesizer/SynthesizerGetLatency.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Synthesizer;
+
+/**
+ * @test
+ * @bug 5029790
+ * @summary Synthesizer.getLatency returns wrong value
+ */
+public class SynthesizerGetLatency {
+
+    public static void main(String args[]) throws Exception {
+        Synthesizer synth = null;
+        boolean failed = false;
+        boolean notexec = false;
+        try {
+            synth = MidiSystem.getSynthesizer();
+            System.out.println("Got synth: "+synth);
+            synth.open();
+
+            int latency = (int) synth.getLatency();
+            System.out.println("  -> latency: "
+                               +latency
+                               +" microseconds");
+            if (latency < 5000 && latency > 0) {
+                System.out.println("## This latency is VERY small, probably due to this bug.");
+                System.out.println("## This causes failure of this test.");
+                failed = true;
+            }
+        } catch (MidiUnavailableException mue) {
+            System.err.println("MidiUnavailableException was "
+                               +"thrown: " + mue);
+            System.out.println("could not test.");
+            notexec = true;
+        } catch(SecurityException se) {
+            se.printStackTrace();
+            System.err.println("Sound access is not denied but "
+            + "SecurityException was thrown!");
+            notexec = true;
+        } finally {
+            if (synth != null) synth.close();
+        }
+
+
+        if (failed) {
+            throw new Exception("Test FAILED!");
+        }
+        if (notexec) {
+            System.out.println("Test not failed.");
+        } else {
+            System.out.println("Test Passed.");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Synthesizer/bug4685396.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.midi.Instrument;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Soundbank;
+import javax.sound.midi.Synthesizer;
+
+/**
+ * @test
+ * @bug 4685396
+ * @summary Tests that Synthesizer.remapInstrument works
+ * @run main bug4685396
+ * @key headful
+ */
+public class bug4685396 {
+
+    static Synthesizer synth = null;
+
+    public static boolean isInstrumentExist(Instrument inst, Instrument[] insts) {
+        for (int i = 0; i < insts.length; i++) {
+            if (inst.equals(insts[i]))
+                return true;
+        }
+        return false;
+    }
+
+    static boolean test(
+            boolean reloadInstr,    // reload all instruments?
+            boolean unloadFrom,     // unload "from" instrument?
+            boolean unloadTo        // unload "to" instrument?
+            ) throws Exception
+    {
+        log("Starting test: reloadInstr=" + reloadInstr
+                + ", unloadFrom=" + unloadFrom
+                + ", unloadTo=" + unloadTo
+                + "");
+
+        log("  creating synthesizer...");
+        synth = MidiSystem.getSynthesizer();
+        log("  opening synthesizer...");
+        synth.open();
+
+        Soundbank sbank = synth.getDefaultSoundbank();
+        if (sbank == null)
+            throw new RuntimeException("ERROR: Could not get default soundbank");
+
+        if (reloadInstr) {
+            synth.unloadAllInstruments(sbank);
+            synth.loadAllInstruments(sbank);
+        }
+
+        Instrument[] instrs = synth.getLoadedInstruments();
+
+        log("  " + instrs.length + " instruments loaded.");
+
+        if (instrs.length < 2)
+            throw new RuntimeException("ERROR: need at least 2 loaded instruments");
+
+        Instrument from = instrs[0];
+        Instrument to = instrs[instrs.length - 1];
+
+        if (unloadFrom)
+            synth.unloadInstrument(from);
+        if (unloadTo)
+            synth.unloadInstrument(to);
+
+        log("  from instrument (" + (unloadFrom ? "UNLOADED" : "LOADED")
+                                + "): " + from.toString());
+        log("  to instrument (" + (unloadTo ? "UNLOADED" : "LOADED")
+                                + "): " + to.toString());
+
+        boolean result = false;
+        boolean excepted = false;
+        try {
+            result = synth.remapInstrument(from, to);
+            log("  remapInstrument(from, to) returns " + result);
+        } catch (IllegalArgumentException ex) {
+            excepted = true;
+            log("  EXCEPTION:");
+            ex.printStackTrace(System.out);
+        }
+
+        instrs = synth.getLoadedInstruments();
+        log("  " + instrs.length + " instruments remains loaded.");
+
+        boolean toUnloaded = !isInstrumentExist(to, instrs);
+        boolean fromUnloaded = !isInstrumentExist(from, instrs);
+
+        log("  from instrument is " + (fromUnloaded ? "UNLOADED" : "LOADED"));
+        log("  to instrument is " + (toUnloaded ? "UNLOADED" : "LOADED"));
+
+        boolean bOK = true;
+        if (result) {
+            if (unloadTo) {
+                bOK = false;
+                log("ERROR: unloaded to, but sucessfull remap");
+            }
+            if (!fromUnloaded) {
+                bOK = false;
+                log("ERROR: sucessfull remap, but from hasn't been unloaded");
+            }
+            if (toUnloaded) {
+                bOK = false;
+                log("ERROR: to has been unloaded!");
+            }
+        } else {
+            if (!excepted) {
+                bOK = false;
+                log("ERROR: remap returns false, exception hasn't been thrown");
+            }
+            if (!unloadTo) {
+                bOK = false;
+                log("ERROR: to is loaded, but remap returns false");
+            }
+            if (unloadFrom != fromUnloaded) {
+                bOK = false;
+                log("ERROR: remap returns false, but status of from has been changed");
+            }
+        }
+
+        if (bOK) {
+            log("Test result: OK\n");
+        } else {
+            log("Test result: FAIL\n");
+        }
+
+        return bOK;
+    }
+
+    static void cleanup() {
+        if (synth != null) {
+            synth.close();
+            synth = null;
+        }
+    }
+
+    static boolean runTest(
+            boolean reloadInstr,    // reload all instruments?
+            boolean unloadTo,       // unload "to" instrument?
+            boolean unloadFrom      // unload "from" instrument?
+            )
+    {
+        boolean success = false;
+        try {
+            success = test(reloadInstr, unloadFrom, unloadTo);
+        } catch (Exception ex) {
+            log("Exception: " + ex.toString());
+        }
+        cleanup();
+        return success;
+    }
+
+    public static void main(String args[]) throws Exception {
+        boolean failed = false;
+        if (!runTest(true, false, false))
+            failed = true;
+        if (!runTest(true, false, true))
+            failed = true;
+        if (!runTest(true, true, false))
+            failed = true;
+        if (!runTest(true, true, true))
+            failed = true;
+
+        if (failed) {
+            throw new RuntimeException("Test FAILED.");
+        }
+        log("Test sucessfully passed.");
+    }
+
+
+    // helper routines
+    static long startTime = currentTimeMillis();
+    static long currentTimeMillis() {
+        //return System.nanoTime() / 1000000L;
+        return System.currentTimeMillis();
+    }
+    static void log(String s) {
+        long time = currentTimeMillis() - startTime;
+        long ms = time % 1000;
+        time /= 1000;
+        long sec = time % 60;
+        time /= 60;
+        long min = time % 60;
+        time /= 60;
+        System.out.println(""
+                + (time < 10 ? "0" : "") + time
+                + ":" + (min < 10 ? "0" : "") + min
+                + ":" + (sec < 10 ? "0" : "") + sec
+                + "." + (ms < 10 ? "00" : (ms < 100 ? "0" : "")) + ms
+                + " (" + Thread.currentThread().getName() + ") " + s);
+    }
+    static void delay(int millis) {
+        try {
+            Thread.sleep(millis);
+        } catch (InterruptedException e) {}
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Track/TrackAddSameTick.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.midi.MidiEvent;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.Track;
+
+/**
+ * @test
+ * @bug 4941944
+ * @summary Track may not have a determined order for inserting events at same
+ *          tick time
+ */
+public class TrackAddSameTick {
+
+    static boolean failed = false;
+    static MidiEvent[] evs = new MidiEvent[10];
+
+    public static void main(String argv[]) throws Exception {
+        Sequence seq = new Sequence(Sequence.PPQ, 240);
+        Track t = seq.createTrack();
+
+        log("add 10 events in random order");
+        t.add(createEvent(10, 5));
+        t.add(createEvent(0, 0));
+        t.add(createEvent(10, 6));
+        t.add(createEvent(11, 8));
+        t.add(createEvent(10, 7));
+        t.add(createEvent(0, 1));
+        t.add(createEvent(0, 2));
+        t.add(createEvent(15, 9));
+        t.add(createEvent(0, 3));
+        t.add(createEvent(1, 4));
+
+        // now compare the events.
+        // The note param will tell us the
+        // the expected position
+        long lastTick = 0;
+        for (int i = 0; i < t.size(); i++) {
+            MidiEvent ev = t.get(i);
+            if (ev.getMessage() instanceof ShortMessage) {
+                ShortMessage msg = (ShortMessage) ev.getMessage();
+                log(""+i+": ShortMessage at tick "+ev.getTick()
+                    +" with expected position "+msg.getData1());
+                if (ev.getTick() < lastTick) {
+                    log("  FAILED: last tick is larger than this event's tick!");
+                    failed = true;
+                }
+                if (i != msg.getData1()) {
+                    log("  FAILED: Track did not order correctly.");
+                    failed = true;
+                }
+            }
+        }
+
+        if (failed) throw new Exception("Test FAILED!");
+        log("Test passed.");
+    }
+
+    public static MidiEvent createEvent(long tick, int expectedPos)
+        throws Exception {
+        ShortMessage msg = new ShortMessage();
+        msg.setMessage(0x90, (int) expectedPos, 00);
+        MidiEvent ev = new MidiEvent(msg, tick);
+        return ev;
+    }
+
+    public static void log(String s) {
+        System.out.println(s);
+    }
+
+    public static void log(Exception e) {
+        //System.out.println(s);
+        e.printStackTrace();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Track/bug6416024.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.MetaMessage;
+import javax.sound.midi.MidiEvent;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.Track;
+
+/**
+ * @test
+ * @bug 6416024
+ * @summary Tests that sequence correctly handle removing of EndOfTrack event
+ * @run main bug6416024
+ */
+public class bug6416024 {
+
+    boolean test() {
+        Sequence sequence = null;
+        Track track = null;
+        MidiEvent event = null;
+
+        log("creating sequence...");
+        try {
+            sequence = new Sequence(Sequence.PPQ, 10);
+            log("  - OK: " + sequence);
+        } catch(InvalidMidiDataException e ) {
+            log("  - FAILED: got exception");
+            e.printStackTrace(System.out);
+            return false;
+        }
+
+        log("creating track...");
+        track = sequence.createTrack();
+        log("  - OK: " + track);
+        log("initial track size=" + track.size());
+
+        log("removing all track events...");
+        while (track.size() > 0) {
+            try {
+                event = track.get(0);
+                log("  ..removing event " + event);
+                track.remove(event);
+                log("    - OK, track size=" + track.size());
+            } catch (Exception e) {
+                log("  - FAILED: got exception");
+                e.printStackTrace(System.out);
+                return false;
+            }
+        }
+
+        MetaMessage newMsg = new MetaMessage();
+        MidiEvent newEvent = new MidiEvent(newMsg, 10);
+        log("adding new event...");
+        try {
+            if (!track.add(newEvent)) {
+                log("event hasn't been added");
+                return false;
+            }
+            log("    - OK, track size=" + track.size());
+        } catch (Exception e) {
+            log("  - FAILED: got exception");
+            e.printStackTrace(System.out);
+            return false;
+        }
+
+        return true;
+    }
+
+    public static void main(String args[]) throws Exception {
+        bug6416024 This = new bug6416024();
+        if (This.test()) {
+            log("Test passed sucessfully.");
+        } else {
+            log("Test FAILED!");
+            delay(1000);
+            throw new RuntimeException("Test failed!");
+        }
+    }
+
+    // helper routines
+    static long startTime = currentTimeMillis();
+    static long currentTimeMillis() {
+        //return System.nanoTime() / 1000000L;
+        return System.currentTimeMillis();
+    }
+    static void log(String s) {
+        long time = currentTimeMillis() - startTime;
+        long ms = time % 1000;
+        time /= 1000;
+        long sec = time % 60;
+        time /= 60;
+        long min = time % 60;
+        time /= 60;
+        System.out.println(""
+                + (time < 10 ? "0" : "") + time
+                + ":" + (min < 10 ? "0" : "") + min
+                + ":" + (sec < 10 ? "0" : "") + sec
+                + "." + (ms < 10 ? "00" : (ms < 100 ? "0" : "")) + ms
+                + " (" + Thread.currentThread().getName() + ") " + s);
+    }
+    static void delay(int millis) {
+        try {
+            Thread.sleep(millis);
+        } catch (InterruptedException e) {}
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Transmitter/bug6415669.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Transmitter;
+
+/**
+ * @test
+ * @bug 6415669
+ * @summary Tests that terminating thread which got transmitter doesn't cause
+ *          JVM crash (windows)
+ * @run main bug6415669
+ */
+public class bug6415669 {
+
+    public static void main(String args[]) throws Exception {
+        String osStr = System.getProperty("os.name");
+        boolean isWin = osStr.toLowerCase().startsWith("windows");
+        log("OS: " + osStr);
+        log("Arch: " + System.getProperty("os.arch"));
+        if (!isWin) {
+            log("The test is for Windows only");
+            return;
+        }
+
+        bug6415669 This = new bug6415669();
+        if (This.test()) {
+            log("Test sucessfully passed.");
+        } else {
+            log("Test FAILED!");
+            throw new RuntimeException("Test FAILED!");
+        }
+    }
+
+    volatile Transmitter transmitter = null;
+    Thread openThread = null;
+    boolean test() {
+        openThread = new Thread(new Runnable() {
+            public void run() {
+                try {
+                    log("openThread: getting transmitter...");
+                    transmitter = MidiSystem.getTransmitter();
+                    log("openThread:   - OK: " + transmitter);
+                } catch (MidiUnavailableException ex) {
+                    log("openThread:   - Exception: ");
+                    ex.printStackTrace(System.out);
+                    log("openThread: skipping...");
+                }
+                log("openThread: exiting...");
+            }
+        });
+        log("starting openThread...");
+        openThread.start();
+
+        while (openThread.isAlive())
+            delay(500);
+        // make additional delay
+        delay(500);
+
+        if (transmitter == null) {
+            return true;   // midi is not available, just ignore
+        }
+
+        log("closing transmitter");
+        transmitter.close();
+        log("  - OK");
+
+        return true;
+    }
+
+    // helper routines
+    static long startTime = currentTimeMillis();
+    static long currentTimeMillis() {
+        //return System.nanoTime() / 1000000L;
+        return System.currentTimeMillis();
+    }
+    static void log(String s) {
+        long time = currentTimeMillis() - startTime;
+        long ms = time % 1000;
+        time /= 1000;
+        long sec = time % 60;
+        time /= 60;
+        long min = time % 60;
+        time /= 60;
+        System.out.println(""
+                + (time < 10 ? "0" : "") + time
+                + ":" + (min < 10 ? "0" : "") + min
+                + ":" + (sec < 10 ? "0" : "") + sec
+                + "." + (ms < 10 ? "00" : (ms < 100 ? "0" : "")) + ms
+                + " (" + Thread.currentThread().getName() + ") " + s);
+    }
+    static void delay(int millis) {
+        try {
+            Thread.sleep(millis);
+        } catch (InterruptedException e) {}
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/AudioFileFormat/AudioFileFormatToString.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.sampled.AudioFileFormat;
+import javax.sound.sampled.AudioFormat;
+
+/**
+ * @test
+ * @bug 4672864
+ * @summary AudioFileFormat.toString() throws unexpected NullPointerException
+ */
+public class AudioFileFormatToString {
+
+    static final int STATUS_PASSED = 0;
+    static final int STATUS_FAILED = 2;
+    static final int STATUS_TEMP = 95;
+
+    public static void main(String argv[]) throws Exception {
+        int testExitStatus = run(argv, System.out);
+        if (testExitStatus != STATUS_PASSED) {
+            throw new Exception("Test FAILED " + testExitStatus);
+        }
+        System.out.println("Test passed.");
+    }
+
+    public static int run(String argv[], java.io.PrintStream out) {
+        int testResult = STATUS_PASSED;
+
+        out.println("\n==> Test for AudioFileFormat class:");
+
+        AudioFormat testAudioFormat =
+         new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,  // AudioFormat.Encoding
+                         (float) 44100.0, // float SampleRate
+                         (int) 8, // int sampleSizeInBits
+                         (int) 2, // int channels
+                         (int) 2,    // int frameSize
+                         (float) 110.0,    // float frameRate
+                         true    // boolean bigEndian
+                         );
+        AudioFormat nullAudioFormat = null;
+
+        AudioFileFormat.Type testAudioFileFormatType = AudioFileFormat.Type.WAVE;
+        AudioFileFormat.Type nullAudioFileFormatType = null;
+
+        AudioFileFormat testedAudioFileFormat = null;
+        out.println("\n>> public AudioFileFormat constructor for AudioFileFormat.Type = null: ");
+        try {
+         testedAudioFileFormat =
+             new AudioFileFormat(nullAudioFileFormatType,  // AudioFileFormat.Type
+                                 testAudioFormat, // AudioFormat
+                                 (int) 1024 // int frameLength
+                                 );
+         out.println(">  No any Exception was thrown!");
+         out.println(">  testedAudioFileFormat.getType():");
+         try {
+             AudioFileFormat.Type producedType = testedAudioFileFormat.getType();
+             out.println(">   PASSED: producedType = " + producedType);
+         } catch (Throwable thrown) {
+             out.println("##  FAILED: unexpected Exception was thrown:");
+             thrown.printStackTrace(out);
+             testResult = STATUS_FAILED;
+         }
+         out.println(">  testedAudioFileFormat.toString():");
+         try {
+             String producedString = testedAudioFileFormat.toString();
+             out.println(">   PASSED: producedString = " + producedString);
+         } catch (Throwable thrown) {
+             out.println("##  FAILED: unexpected Exception was thrown:");
+             thrown.printStackTrace(out);
+             testResult = STATUS_FAILED;
+         }
+        } catch (IllegalArgumentException illegArgExcept) {
+         out.println(">   PASSED: expected IllegalArgumentException was thrown:");
+         illegArgExcept.printStackTrace(out);
+        } catch (NullPointerException nullPE) {
+         out.println(">   PASSED: expected NullPointerException was thrown:");
+         nullPE.printStackTrace(out);
+        } catch (Throwable thrown) {
+         out.println("##  FAILED: unexpected Exception was thrown:");
+         thrown.printStackTrace(out);
+         testResult = STATUS_FAILED;
+        }
+
+        out.println("\n>> public AudioFileFormat constructor for AudioFormat = null: ");
+        try {
+         testedAudioFileFormat =
+             new AudioFileFormat(testAudioFileFormatType,  // AudioFileFormat.Type
+                                 nullAudioFormat, // AudioFormat
+                                 (int) 1024 // int frameLength
+                                 );
+         out.println(">  No any Exception was thrown!");
+         out.println(">  testedAudioFileFormat.getFormat():");
+         try {
+             AudioFormat producedFormat = testedAudioFileFormat.getFormat();
+             out.println(">   PASSED: producedFormat = " + producedFormat);
+         } catch (Throwable thrown) {
+             out.println("##  FAILED: unexpected Exception was thrown:");
+             thrown.printStackTrace(out);
+             testResult = STATUS_FAILED;
+         }
+         out.println(">  testedAudioFileFormat.toString():");
+         try {
+             String producedString = testedAudioFileFormat.toString();
+             out.println(">   PASSED: producedString = " + producedString);
+         } catch (Throwable thrown) {
+             out.println("##  FAILED: unexpected Exception was thrown:");
+             thrown.printStackTrace(out);
+             testResult = STATUS_FAILED;
+         }
+        } catch (IllegalArgumentException illegArgExcept) {
+            out.println(">   PASSED: expected IllegalArgumentException was thrown:");
+            illegArgExcept.printStackTrace(out);
+        } catch (NullPointerException nullPE) {
+            out.println(">   PASSED: expected NullPointerException was thrown:");
+            nullPE.printStackTrace(out);
+        } catch (Throwable thrown) {
+            out.println("##  FAILED: unexpected Exception was thrown:");
+            thrown.printStackTrace(out);
+            testResult = STATUS_FAILED;
+        }
+
+        out.println("\n>> protected AudioFileFormat constructor for AudioFileFormat.Type = null: ");
+        try {
+         testedAudioFileFormat =
+             new TestAudioFileFormat(nullAudioFileFormatType,  // AudioFileFormat.Type
+                                     (int) 1024, // byteLength
+                                     testAudioFormat, // AudioFormat
+                                     (int) 1024 // int frameLength
+                                     );
+         out.println(">  No any Exception was thrown!");
+         out.println(">  testedAudioFileFormat.getType():");
+         try {
+             AudioFileFormat.Type producedType = testedAudioFileFormat.getType();
+             out.println(">   PASSED: producedType = " + producedType);
+         } catch (Throwable thrown) {
+             out.println("##  FAILED: unexpected Exception was thrown:");
+             thrown.printStackTrace(out);
+             testResult = STATUS_FAILED;
+         }
+         out.println(">  testedAudioFileFormat.toString():");
+         try {
+             String producedString = testedAudioFileFormat.toString();
+             out.println(">   PASSED: producedString = " + producedString);
+         } catch (Throwable thrown) {
+             out.println("##  FAILED: unexpected Exception was thrown:");
+             thrown.printStackTrace(out);
+             testResult = STATUS_FAILED;
+         }
+        } catch (IllegalArgumentException illegArgExcept) {
+         out.println(">   PASSED: expected IllegalArgumentException was thrown:");
+         illegArgExcept.printStackTrace(out);
+        } catch (NullPointerException nullPE) {
+         out.println(">   PASSED: expected NullPointerException was thrown:");
+         nullPE.printStackTrace(out);
+        } catch (Throwable thrown) {
+         out.println("##  FAILED: unexpected Exception was thrown:");
+         thrown.printStackTrace(out);
+         testResult = STATUS_FAILED;
+        }
+
+        out.println("\n>> protected AudioFileFormat constructor for AudioFormat = null: ");
+        try {
+         testedAudioFileFormat =
+             new TestAudioFileFormat(testAudioFileFormatType,  // AudioFileFormat.Type
+                                     (int) 1024, // byteLength
+                                     nullAudioFormat, // AudioFormat
+                                     (int) 1024 // int frameLength
+                                     );
+         out.println(">  No any Exception was thrown!");
+         out.println(">  testedAudioFileFormat.getFormat():");
+         try {
+             AudioFormat producedFormat = testedAudioFileFormat.getFormat();
+             out.println(">   PASSED: producedFormat = " + producedFormat);
+         } catch (Throwable thrown) {
+             out.println("##  FAILED: unexpected Exception was thrown:");
+             thrown.printStackTrace(out);
+             testResult = STATUS_FAILED;
+         }
+         out.println(">  testedAudioFileFormat.toString():");
+         try {
+             String producedString = testedAudioFileFormat.toString();
+             out.println(">   PASSED: producedString = " + producedString);
+         } catch (Throwable thrown) {
+             out.println("##  FAILED: unexpected Exception was thrown:");
+             thrown.printStackTrace(out);
+             testResult = STATUS_FAILED;
+         }
+        } catch (IllegalArgumentException illegArgExcept) {
+         out.println(">   PASSED: expected IllegalArgumentException was thrown:");
+         illegArgExcept.printStackTrace(out);
+        } catch (NullPointerException nullPE) {
+         out.println(">   PASSED: expected NullPointerException was thrown:");
+         nullPE.printStackTrace(out);
+        } catch (Throwable thrown) {
+         out.println("##  FAILED: unexpected Exception was thrown:");
+         thrown.printStackTrace(out);
+         testResult = STATUS_FAILED;
+        }
+
+        if (testResult == STATUS_FAILED) {
+            out.println("\n==> test FAILED!");
+        } else {
+            out.println("\n==> test PASSED!");
+        }
+        return testResult;
+    }
+}
+
+class TestAudioFileFormat extends AudioFileFormat {
+
+    TestAudioFileFormat(AudioFileFormat.Type type, int byteLength,
+                        AudioFormat format, int frameLength) {
+        super(type, byteLength, format, frameLength);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/AudioFileFormat/Properties.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.sound.midi.MidiFileFormat;
+import javax.sound.midi.Sequence;
+import javax.sound.sampled.AudioFileFormat;
+import javax.sound.sampled.AudioFormat;
+
+/**
+ * @test
+ * @bug 4666845
+ * @summary RFE: Add properties to AudioFileFormat and MidiFileFormat
+ */
+public class Properties {
+
+    static boolean g_failed = false;
+
+    // all of p1 need to be in p2
+    static boolean compare(Map p1, Map p2) {
+        boolean failed = false;
+        for(String key: (Set<String>) p1.keySet()) {
+            out("  testing key: "+key);
+            if (!p2.containsKey(key)) {
+                out("  missing property: '"+key+"'. Failed");
+                failed = true;
+            }
+            Object v1 = p1.get(key);
+            Object v2 = p2.get(key);
+            if (((v1 == null) && (v2 != null))
+                || ((v1 != null) && (v2 == null))
+                || !(v1.equals(v2))) {
+                out("  property '"+key+"' is different: "
+                    +"expected='"+v1+"'  "
+                    +"actual='"+v2+"'. Failed");
+                failed = true;
+            }
+        }
+        // test if we can modify p2
+        try {
+             int oldSize = p2.size();
+             p2.clear();
+             if (oldSize > 0 && p2.size() == 0) {
+                 out("  could clear the properties! Failed.");
+                 failed = true;
+             }
+        } catch (Exception e) {
+            // correct
+        }
+        return failed;
+    }
+
+    public static void main(String argv[]) throws Exception {
+        // don't need to catch exceptions: any exception is a
+        // failure of this test
+
+        Map<String, Object> p = new HashMap<String,Object>();
+        p.put("author", "Florian");
+        p.put("duration", new Long(1000));
+        p.put("MyProp", "test");
+
+        out("Testing AudioFileFormat properties:");
+        // create an AudioFileFormat with properties
+        AudioFormat format = new AudioFormat( 44100.0f, 16, 2, true, false);
+        AudioFileFormat aff =
+            new AudioFileFormat(AudioFileFormat.Type.WAVE,
+                                format, 1000, p);
+        // test that it has the properties
+        boolean failed = compare(p, aff.properties());
+        // test getProperty()
+        Object o = aff.getProperty("author");
+        if (o == null || !o.equals("Florian")) {
+            out("  getProperty did not report an existing property!");
+            failed = true;
+        }
+        o = aff.getProperty("does not exist");
+        if (o != null) {
+            out("  getProperty returned something for a non-existing property!");
+            failed = true;
+        }
+        if (!failed) {
+            out("  OK");
+        } else {
+            g_failed = true;
+        }
+
+
+
+        out("Testing MidiFileFormat properties:");
+        // create a MidiFileFormat with properties
+        MidiFileFormat mff =
+            new MidiFileFormat(0, Sequence.PPQ, 240,
+                               1000, 100, p);
+        // test that it has the properties
+        failed = compare(p, mff.properties());
+        // test getProperty()
+        o = mff.getProperty("author");
+        if (o == null || !o.equals("Florian")) {
+            out("  getProperty did not report an existing property!");
+            failed = true;
+        }
+        o = mff.getProperty("does not exist");
+        if (o != null) {
+            out("  getProperty returned something for a non-existing property!");
+            failed = true;
+        }
+        if (!failed) {
+            out("  OK");
+        } else {
+            g_failed = true;
+        }
+
+
+        if (g_failed) throw new Exception("Test FAILED!");
+        System.out.println("Test passed.");
+    }
+
+    static void out(String s) {
+        System.out.println(s);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/AudioFileFormat/TypeEquals.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.sampled.AudioFileFormat;
+
+/**
+ * @test
+ * @bug 4925483
+ * @summary RFE: equals() should compare string in Encoding and Type
+ */
+public class TypeEquals {
+
+    public static void main(String argv[]) throws Exception {
+        // first test that we can create our own type
+        // (the constructor was made public)
+        AudioFileFormat.Type myType = new AudioFileFormat.Type("WAVE", "wav");
+
+        // then check if this one equals this new one
+        // with the static instance in AudioFileFormat.Type
+        if (!myType.equals(AudioFileFormat.Type.WAVE)) {
+         throw new Exception("Types do not equal!");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/AudioFormat/AudioFormatBitSize.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 4754759
+ * @summary AudioFormat does not handle uncommon bit sizes correctly
+ */
+
+import javax.sound.sampled.AudioFormat;
+
+public class AudioFormatBitSize {
+
+    public static void main(String[] args) throws Exception {
+        int bits = 18;
+        AudioFormat format = new AudioFormat(44100.0f, bits, 1, true, false);
+        if (format.getFrameSize() * 8 < bits) {
+            System.out.println("bits = "+bits+" do not fit into a "+format.getFrameSize()+" bytes sample!");
+            throw new Exception("Test failed");
+        } else
+            System.out.println("bits = "+bits+" fit OK into a "+format.getFrameSize()+" bytes sample!");
+            System.out.println("Test passed");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/AudioFormat/EncodingEquals.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.sampled.AudioFormat;
+
+/**
+ * @test
+ * @bug 4925483
+ * @summary RFE: equals() should compare string in Encoding and Type
+ */
+public class EncodingEquals {
+
+    public static void main(String argv[]) throws Exception {
+         // first test that we can create our own encoding
+         // (the constructor was made public)
+         AudioFormat.Encoding myType = new AudioFormat.Encoding("PCM_SIGNED");
+
+         // then check if this one equals this new one
+         // with the static instance in AudioFormat.Encoding
+         if (!myType.equals(AudioFormat.Encoding.PCM_SIGNED)) {
+             throw new Exception("Encodings do not equal!");
+         }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/AudioFormat/Properties.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.sound.sampled.AudioFormat;
+
+/**
+ * @test
+ * @bug 4925767
+ * @summary RFE: Add Properties to AudioFormat
+ */
+public class Properties {
+
+    static boolean g_failed = false;
+
+    // all of p1 need to be in p2
+    static boolean compare(Map p1, Map p2) {
+        boolean failed = false;
+        for(String key: (Set<String>) p1.keySet()) {
+            out("  testing key: "+key);
+            if (!p2.containsKey(key)) {
+                out("  missing property: '"+key+"'. Failed");
+                failed = true;
+            }
+            Object v1 = p1.get(key);
+            Object v2 = p2.get(key);
+            if (((v1 == null) && (v2 != null))
+                || ((v1 != null) && (v2 == null))
+                || !(v1.equals(v2))) {
+                out("  property '"+key+"' is different: "
+                    +"expected='"+v1+"'  "
+                    +"actual='"+v2+"'. Failed");
+                failed = true;
+            }
+        }
+        // test if we can modify p2
+        try {
+             int oldSize = p2.size();
+             p2.clear();
+             if (oldSize > 0 && p2.size() == 0) {
+                 out("  could clear the properties! Failed.");
+                 failed = true;
+             }
+        } catch (Exception e) {
+            // correct
+        }
+        return failed;
+    }
+
+
+    public static void main(String argv[]) throws Exception {
+        // don't need to catch exceptions: any exception is a
+        // failure of this test
+
+        Map<String, Object> p = new HashMap<String,Object>();
+        p.put("bitrate", new Integer(128));
+        p.put("quality", new Integer(10));
+        p.put("MyProp", "test");
+
+        out("Testing AudioFileFormat properties:");
+        // create an AudioFileFormat with properties
+        AudioFormat format =
+            new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
+                            44100.0f, 16, 2, 4, 44100.0f, false, p);
+        // test that it has the properties
+        boolean failed = compare(p, format.properties());
+        // test getProperty()
+        Object o = format.getProperty("MyProp");
+        if (o == null || !o.equals("test")) {
+            out("  getProperty did not report an existing property!");
+            failed = true;
+        }
+        o = format.getProperty("does not exist");
+        if (o != null) {
+            out("  getProperty returned something for a non-existing property!");
+            failed = true;
+        }
+        if (!failed) {
+            out("  OK");
+        } else {
+            g_failed = true;
+        }
+
+        if (g_failed) throw new Exception("Test FAILED!");
+        System.out.println("Test passed.");
+    }
+
+    static void out(String s) {
+        System.out.println(s);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/AudioInputStream/AISReadFraction.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+
+/**
+ * @test
+ * @bug 4948663
+ * @summary AudioInputStream does not use the original stream passed to its constructor
+ */
+public class AISReadFraction {
+
+    static int failed = 0;
+    static byte[] testData = new byte[256];
+    static boolean DEBUG = false;
+
+    static AudioFormat[] formats = {
+        new AudioFormat(44100.0f, 8, 1, false, false), // frameSize = 1
+        new AudioFormat(44100.0f, 8, 2, false, false), // frameSize = 2
+        new AudioFormat(44100.0f, 16, 1, true, false), // frameSize = 2
+        new AudioFormat(44100.0f, 24, 1, true, false), // frameSize = 3
+        new AudioFormat(44100.0f, 16, 2, true, false), // frameSize = 4
+        new AudioFormat(44100.0f, 8, 5, false, false), // frameSize = 5
+        new AudioFormat(44100.0f, 16, 3, true, false), // frameSize = 6
+        new AudioFormat(44100.0f, 8, 7, false, false), // frameSize = 7
+        new AudioFormat(44100.0f, 32, 2, true, false)  // frameSize = 8
+    };
+
+
+    public static void main(String args[]) throws Exception {
+        for (int i = 0; i<testData.length; i++) {
+                testData[i] = (byte) (i % 128);
+        }
+
+        for (int f = 0; f < formats.length; f++) {
+                // first test without marking
+                doTest(formats[f], false);
+                // then with marking
+                doTest(formats[f], true);
+        }
+
+        out(""+failed+" failures.");
+        if (failed>0) throw new Exception("Test FAILED!");
+        out("Test passed.");
+    }
+
+    static void doTest(AudioFormat format, boolean doMark) {
+        out("Test with"+(doMark?"":"out")+" marking. Audio format: "
+            +"sampleSize="+format.getSampleSizeInBits()+"bits "
+            +"channels="+format.getChannels()+" "
+            +"frameSize="+format.getFrameSize()+"byte(s)");
+        int maxReadBytes = (testData.length / format.getFrameSize()) * format.getFrameSize();
+        InputStream is = new FractionalIS(testData, doMark);
+        AudioInputStream ais = new AudioInputStream(is, format, AudioSystem.NOT_SPECIFIED);
+        // first some general tests
+        if (ais.markSupported() && !doMark) {
+                out("  #AIS reports markSupported, but underlying stream cannot! FAILED");
+                failed ++;
+        }
+        if (!ais.markSupported() && doMark) {
+                out("  #AIS does not report markSupported, but underlying stream can mark! FAILED");
+                failed++;
+        }
+        byte[] data = new byte[1000];
+        int frameSize = format.getFrameSize();
+        int counter = 5;
+        int totalReadBytes = 0;
+        boolean hasRead0 = false;
+        boolean hasMarked = false;
+        boolean hasReset = false;
+        int markPos = 0;
+        while (true) {
+            try {
+                int toBeRead = frameSize * counter;
+                counter += 3;
+                if (counter > 14) {
+                        counter -= 14;
+                }
+                int read = ais.read(data, 0, toBeRead);
+                if (DEBUG) out("  -> ais.read(data, 0, "+toBeRead+"): "+read+"  (frameSize="+frameSize+")");
+                if ((totalReadBytes == maxReadBytes) && (read != -1)
+                     && ((read > 0) || hasRead0)) {
+                        if (read == 0) {
+                            out("  #stream was read to the end ("+maxReadBytes+"), but ais.read returned repeatedly 0 bytes. FAILED");
+                        } else {
+                            out("  #stream was read to the end ("+maxReadBytes+"), but ais.read returned "+read+" bytes... FAILED");
+                        }
+                        failed++;
+                        break;
+                }
+                if (read > 0) {
+                        verifyReadBytes(data, totalReadBytes, read);
+                        if ((read % frameSize) != 0) {
+                                out("  #Read non-integral number of frames: "+read+" bytes, frameSize="+frameSize+" bytes. FAILED");
+                                failed++;
+                        }
+                        totalReadBytes += read;
+                        hasRead0 = false;
+                }
+                else if (read == 0) {
+                        //out("  wanted to read "+toBeRead+" at position "+totalReadBytes+", but got 0 bytes!");
+                        if (hasRead0) {
+                                out("  read 0 twice in a row! FAILED");
+                                failed++;
+                                break;
+                        }
+                        hasRead0 = true;
+                } else {
+                        // end of stream
+                        out("  End of stream reached. Total read bytes: "+totalReadBytes);
+                        if (totalReadBytes != maxReadBytes) {
+                                out("  #Failed: should have read "+maxReadBytes+" bytes! FAILED.");
+                                failed++;
+                        }
+                        break;
+                }
+
+                // test marking
+                if (totalReadBytes > 50 && !hasMarked && !hasReset && doMark) {
+                        out("  Marking at position "+totalReadBytes);
+                        hasMarked = true;
+                        ais.mark(0);
+                        markPos = totalReadBytes;
+                }
+                if (totalReadBytes > 100 && hasMarked && !hasReset && doMark) {
+                        out("  Resetting at position "+totalReadBytes+" back to "+markPos);
+                        hasReset = true;
+                        ais.reset();
+                        totalReadBytes = markPos;
+                }
+
+            } catch (IOException e) {
+                out("  #caught unexpected exception:");
+                e.printStackTrace();
+                failed++;
+            }
+        }
+    }
+
+    static void verifyReadBytes(byte[] data, int offset, int len) {
+        int firstWrongByte = -1;
+        for (int i = 0; i < len; i++) {
+                int expected = ((offset + i) % 128);
+                if (data[i] != expected) {
+                        out("  read data is not correct! offset="+offset+"  expected="+expected+"  actual="+data[i]);
+                        failed++;
+                        break;
+                }
+        }
+    }
+
+
+    public static void out(String s) {
+        System.out.println(s);
+    }
+
+
+    static class FractionalIS extends InputStream {
+        byte[] data;
+        int pos = 0;
+        boolean canMark;
+        // a counter how many bytes are not returned
+        int missingBytes = 0;
+        int markPos = -1;
+
+        FractionalIS(byte[] data, boolean canMark) {
+                this.data = data;
+                this.canMark = canMark;
+        }
+
+        public int read() throws IOException {
+                if (pos >= data.length) {
+                        return -1;
+                }
+                return data[pos++] & 0xFF;
+        }
+
+        public int read(byte[] b, int off, int len) throws IOException {
+                if (++missingBytes > 5) {
+                        missingBytes = 0;
+                }
+                int reducedLen = len - missingBytes;
+                if (reducedLen <= 0) reducedLen = 1;
+                if (DEBUG) out("  FIS.read(data, 0, "+len+"): reducing len to "+reducedLen+" bytes.");
+                int ret = super.read(b, off, reducedLen);
+                if (DEBUG) out("                              returning "+ret+" bytes. Now at pos="+pos);
+                return ret;
+        }
+
+        public void mark(int readlimit) {
+                markPos = pos;
+                if (DEBUG) out("  FIS.mark(): marking at "+pos);
+        }
+
+        public void reset() throws IOException {
+                if (!canMark) {
+                        throw new IOException("reset not supported!");
+                }
+                if (markPos == -1) {
+                        throw new IOException("Mark position not set!");
+                }
+                pos = markPos;
+                if (DEBUG) out("  FIS.reset(): now back at "+pos);
+        }
+
+        public boolean markSupported() {
+                return canMark;
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/AudioInputStream/bug6188860.java	Thu Nov 03 13:44:56 2016 -0700
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+
+/**
+ * @test
+ * @bug 6188860
+ * @summary Tests that method AudioInputStream.read() returns right value
+ */
<