Skip to content

Commit 613a3cc

Browse files
Renjithkannathaivanov-jdk
authored andcommitted
8301846: Invalid TargetDataLine after screen lock when using JFileChooser or COM library
Reviewed-by: serb, aivanov
1 parent 613d32c commit 613a3cc

File tree

2 files changed

+167
-1
lines changed

2 files changed

+167
-1
lines changed

src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_DirectSound.cpp

+23-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -184,6 +184,12 @@ INT32 DAUDIO_GetDirectAudioDeviceCount() {
184184
return 0;
185185
}
186186

187+
HRESULT hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
188+
if (FAILED(hr) && hr != RPC_E_CHANGED_MODE) {
189+
DS_unlockCache();
190+
return 0;
191+
}
192+
187193
if (g_lastCacheRefreshTime == 0
188194
|| (UINT64) timeGetTime() > (UINT64) (g_lastCacheRefreshTime + WAIT_BETWEEN_CACHE_REFRESH_MILLIS)) {
189195
/* first, initialize any old cache items */
@@ -224,6 +230,11 @@ INT32 DAUDIO_GetDirectAudioDeviceCount() {
224230

225231
g_lastCacheRefreshTime = (UINT64) timeGetTime();
226232
}
233+
234+
if (hr != RPC_E_CHANGED_MODE) {
235+
::CoUninitialize();
236+
}
237+
227238
DS_unlockCache();
228239
/*TRACE1("DirectSound: %d installed devices\n", g_mixerCount);*/
229240
return g_mixerCount;
@@ -258,6 +269,13 @@ INT32 DAUDIO_GetDirectAudioDeviceDescription(INT32 mixerIndex, DirectAudioDevice
258269
DS_unlockCache();
259270
return FALSE;
260271
}
272+
273+
HRESULT hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
274+
if (FAILED(hr) && hr != RPC_E_CHANGED_MODE) {
275+
DS_unlockCache();
276+
return 0;
277+
}
278+
261279
desc->maxSimulLines = 0;
262280
if (g_audioDeviceCache[desc->deviceID].isSource) {
263281
DirectSoundEnumerateW((LPDSENUMCALLBACKW) DS_GetDescEnum, desc);
@@ -267,6 +285,10 @@ INT32 DAUDIO_GetDirectAudioDeviceDescription(INT32 mixerIndex, DirectAudioDevice
267285
strncpy(desc->description, "DirectSound Capture", DAUDIO_STRING_LENGTH);
268286
}
269287

288+
if (hr != RPC_E_CHANGED_MODE) {
289+
::CoUninitialize();
290+
}
291+
270292
/*desc->vendor;
271293
desc->version;*/
272294

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
/*
2+
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
import java.awt.BorderLayout;
25+
import java.awt.event.WindowAdapter;
26+
import java.awt.event.WindowEvent;
27+
import java.util.Arrays;
28+
import java.util.concurrent.CountDownLatch;
29+
import java.util.concurrent.TimeUnit;
30+
31+
import javax.sound.sampled.AudioSystem;
32+
import javax.sound.sampled.Line;
33+
import javax.sound.sampled.LineUnavailableException;
34+
import javax.sound.sampled.Mixer;
35+
import javax.sound.sampled.TargetDataLine;
36+
import javax.swing.JButton;
37+
import javax.swing.JFileChooser;
38+
import javax.swing.JFrame;
39+
import javax.swing.JScrollPane;
40+
import javax.swing.JTextArea;
41+
42+
import static javax.swing.SwingUtilities.invokeAndWait;
43+
44+
/*
45+
* @test
46+
* @bug 8301846
47+
* @requires (os.family == "windows")
48+
* @summary Sound recording fails after screen lock and unlock.
49+
* @run main/manual OpenLineAfterScreenLock
50+
*/
51+
public class OpenLineAfterScreenLock {
52+
53+
private static final String INSTRUCTIONS = """
54+
This test verifies it can record sound from the first sound capture device after
55+
locking and unlocking the screen. The first part of the test has already completed.
56+
57+
Lock the screen and unlock it. Then click Continue to complete the test.
58+
59+
The test will finish automatically.
60+
""";
61+
62+
private static final CountDownLatch latch = new CountDownLatch(1);
63+
64+
private static JFrame frame;
65+
66+
public static void main(String[] args) throws Exception {
67+
try {
68+
runTest();
69+
70+
// Creating JFileChooser initializes COM
71+
// which affects ability to open audio lines
72+
new JFileChooser();
73+
74+
invokeAndWait(OpenLineAfterScreenLock::createInstructionsUI);
75+
if (!latch.await(2, TimeUnit.MINUTES)) {
76+
throw new RuntimeException("Test failed: Test timed out!!");
77+
}
78+
79+
runTest();
80+
} finally {
81+
invokeAndWait(() -> {
82+
if (frame != null) {
83+
frame.dispose();
84+
}
85+
});
86+
}
87+
System.out.println("Test Passed");
88+
}
89+
90+
private static void runTest() {
91+
try {
92+
Mixer mixer = getMixer();
93+
TargetDataLine line =
94+
(TargetDataLine) mixer.getLine(mixer.getTargetLineInfo()[0]);
95+
line.open();
96+
line.close();
97+
} catch (LineUnavailableException e) {
98+
throw new RuntimeException("Test failed: Line unavailable", e);
99+
}
100+
}
101+
102+
private static Mixer getMixer() {
103+
return Arrays.stream(AudioSystem.getMixerInfo())
104+
.map(AudioSystem::getMixer)
105+
.filter(OpenLineAfterScreenLock::isRecordingDevice)
106+
.skip(1) // Skip the primary driver and choose one directly
107+
.findAny()
108+
.orElseThrow();
109+
}
110+
111+
private static boolean isRecordingDevice(Mixer mixer) {
112+
Line.Info[] lineInfos = mixer.getTargetLineInfo();
113+
return lineInfos.length > 0
114+
&& lineInfos[0].getLineClass() == TargetDataLine.class;
115+
}
116+
117+
private static void createInstructionsUI() {
118+
frame = new JFrame("Instructions for OpenLineAfterScreenLock");
119+
120+
JTextArea textArea = new JTextArea(INSTRUCTIONS);
121+
textArea.setEditable(false);
122+
123+
JScrollPane pane = new JScrollPane(textArea);
124+
frame.getContentPane().add(pane, BorderLayout.NORTH);
125+
126+
JButton button = new JButton("Continue");
127+
button.addActionListener(e -> latch.countDown());
128+
frame.getContentPane().add(button, BorderLayout.PAGE_END);
129+
130+
frame.pack();
131+
frame.setLocationRelativeTo(null);
132+
133+
frame.addWindowListener(new CloseWindowHandler());
134+
frame.setVisible(true);
135+
}
136+
137+
private static class CloseWindowHandler extends WindowAdapter {
138+
@Override
139+
public void windowClosing(WindowEvent e) {
140+
latch.countDown();
141+
throw new RuntimeException("Test window closed abruptly");
142+
}
143+
}
144+
}

0 commit comments

Comments
 (0)