19f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li/* 29f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * ConnectBot: simple, powerful, open-source SSH client for Android 39f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Copyright 2007 Kenny Root, Jeffrey Sharkey 49f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 59f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Licensed under the Apache License, Version 2.0 (the "License"); 69f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * you may not use this file except in compliance with the License. 79f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * You may obtain a copy of the License at 89f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 99f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * http://www.apache.org/licenses/LICENSE-2.0 109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Unless required by applicable law or agreed to in writing, software 129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * distributed under the License is distributed on an "AS IS" BASIS, 139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * See the License for the specific language governing permissions and 159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * limitations under the License. 169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Lipackage org.connectbot.service; 199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.content.Context; 219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.content.Intent; 229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.content.SharedPreferences; 239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.content.SharedPreferences.OnSharedPreferenceChangeListener; 249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.content.res.AssetFileDescriptor; 259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.content.res.Configuration; 269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.content.res.Resources; 279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.media.AudioManager; 289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.media.MediaPlayer; 299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.media.MediaPlayer.OnCompletionListener; 309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.os.Handler; 319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.os.Message; 329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.os.Vibrator; 339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.preference.PreferenceManager; 349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport com.googlecode.android_scripting.Constants; 369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport com.googlecode.android_scripting.Log; 379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport com.googlecode.android_scripting.R; 389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport com.googlecode.android_scripting.activity.ScriptingLayerService; 399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport com.googlecode.android_scripting.exception.Sl4aException; 409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport com.googlecode.android_scripting.interpreter.InterpreterProcess; 419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport org.connectbot.transport.ProcessTransport; 439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport org.connectbot.util.PreferenceConstants; 449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.io.IOException; 469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.lang.ref.WeakReference; 479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.util.List; 489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.util.Map; 499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.util.concurrent.ConcurrentHashMap; 509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.util.concurrent.CopyOnWriteArrayList; 519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li/** 539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Manager for SSH connections that runs as a background service. This service holds a list of 549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * currently connected SSH bridges that are ready for connection up to a GUI if needed. 559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Lipublic class TerminalManager implements OnSharedPreferenceChangeListener { 589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private static final long VIBRATE_DURATION = 30; 609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final List<TerminalBridge> bridges = new CopyOnWriteArrayList<TerminalBridge>(); 629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final Map<Integer, WeakReference<TerminalBridge>> mHostBridgeMap = 649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li new ConcurrentHashMap<Integer, WeakReference<TerminalBridge>>(); 659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private Handler mDisconnectHandler = null; 679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final Resources mResources; 699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final SharedPreferences mPreferences; 719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private boolean hardKeyboardHidden; 739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private Vibrator vibrator; 759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private boolean wantKeyVibration; 769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private boolean wantBellVibration; 779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private boolean wantAudible; 789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private boolean resizeAllowed = false; 799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private MediaPlayer mediaPlayer; 809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final ScriptingLayerService mService; 829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public TerminalManager(ScriptingLayerService service) { 849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mService = service; 859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mPreferences = PreferenceManager.getDefaultSharedPreferences(mService); 869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li registerOnSharedPreferenceChangeListener(this); 879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mResources = mService.getResources(); 889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li hardKeyboardHidden = 899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li (mResources.getConfiguration().hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES); 909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li vibrator = (Vibrator) mService.getSystemService(Context.VIBRATOR_SERVICE); 919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li wantKeyVibration = mPreferences.getBoolean(PreferenceConstants.BUMPY_ARROWS, true); 929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li wantBellVibration = mPreferences.getBoolean(PreferenceConstants.BELL_VIBRATE, true); 939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li wantAudible = mPreferences.getBoolean(PreferenceConstants.BELL, true); 949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (wantAudible) { 959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li enableMediaPlayer(); 969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /** 1009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Disconnect all currently connected bridges. 1019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 1029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private void disconnectAll() { 1039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li TerminalBridge[] bridgesArray = null; 1049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (bridges.size() > 0) { 1059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li bridgesArray = bridges.toArray(new TerminalBridge[bridges.size()]); 1069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (bridgesArray != null) { 1089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // disconnect and dispose of any existing bridges 1099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li for (TerminalBridge bridge : bridgesArray) { 1109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li bridge.dispatchDisconnect(true); 1119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /** 1169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Open a new session using the given parameters. 1179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 1189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * @throws InterruptedException 1199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * @throws Sl4aException 1209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 1219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public TerminalBridge openConnection(int id) throws IllegalArgumentException, IOException, 1229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li InterruptedException, Sl4aException { 1239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // throw exception if terminal already open 1249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (getConnectedBridge(id) != null) { 1259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li throw new IllegalArgumentException("Connection already open"); 1269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li InterpreterProcess process = mService.getProcess(id); 1299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li TerminalBridge bridge = new TerminalBridge(this, process, new ProcessTransport(process)); 1319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li bridge.connect(); 1329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li WeakReference<TerminalBridge> wr = new WeakReference<TerminalBridge>(bridge); 1349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li bridges.add(bridge); 1359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mHostBridgeMap.put(id, wr); 1369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return bridge; 1389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /** 1419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Find a connected {@link TerminalBridge} with the given HostBean. 1429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 1439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * @param id 1449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * the HostBean to search for 1459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * @return TerminalBridge that uses the HostBean 1469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 1479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public TerminalBridge getConnectedBridge(int id) { 1489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li WeakReference<TerminalBridge> wr = mHostBridgeMap.get(id); 1499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (wr != null) { 1509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return wr.get(); 1519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else { 1529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return null; 1539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /** 1579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Called by child bridge when somehow it's been disconnected. 1589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 1599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void closeConnection(TerminalBridge bridge, boolean killProcess) { 1609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (killProcess) { 1619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li bridges.remove(bridge); 1629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mHostBridgeMap.remove(bridge.getId()); 1639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (mService.getProcess(bridge.getId()).isAlive()) { 1649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Intent intent = new Intent(mService, mService.getClass()); 1659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li intent.setAction(Constants.ACTION_KILL_PROCESS); 1669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li intent.putExtra(Constants.EXTRA_PROXY_PORT, bridge.getId()); 1679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mService.startService(intent); 1689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (mDisconnectHandler != null) { 1719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Message.obtain(mDisconnectHandler, -1, bridge).sendToTarget(); 1729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li /** 1769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Allow {@link TerminalBridge} to resize when the parent has changed. 1779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 1789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * @param resizeAllowed 1799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 1809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void setResizeAllowed(boolean resizeAllowed) { 1819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li this.resizeAllowed = resizeAllowed; 1829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public boolean isResizeAllowed() { 1859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return resizeAllowed; 1869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void stop() { 1899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li resizeAllowed = false; 1909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li disconnectAll(); 1919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li disableMediaPlayer(); 1929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public int getIntParameter(String key, int defValue) { 1959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return mPreferences.getInt(key, defValue); 1969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public String getStringParameter(String key, String defValue) { 1999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return mPreferences.getString(key, defValue); 2009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void tryKeyVibrate() { 2039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (wantKeyVibration) { 2049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li vibrate(); 2059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private void vibrate() { 2099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (vibrator != null) { 2109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li vibrator.vibrate(VIBRATE_DURATION); 2119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private void enableMediaPlayer() { 2159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mediaPlayer = new MediaPlayer(); 2169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li float volume = 2189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mPreferences.getFloat(PreferenceConstants.BELL_VOLUME, 2199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li PreferenceConstants.DEFAULT_BELL_VOLUME); 2209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mediaPlayer.setAudioStreamType(AudioManager.STREAM_NOTIFICATION); 2229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mediaPlayer.setOnCompletionListener(new BeepListener()); 2239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li AssetFileDescriptor file = mResources.openRawResourceFd(R.raw.bell); 2259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li try { 2269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mediaPlayer.setDataSource(file.getFileDescriptor(), file.getStartOffset(), file.getLength()); 2279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li file.close(); 2289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mediaPlayer.setVolume(volume, volume); 2299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mediaPlayer.prepare(); 2309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } catch (IOException e) { 2319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.e("Error setting up bell media player", e); 2329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private void disableMediaPlayer() { 2369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (mediaPlayer != null) { 2379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mediaPlayer.release(); 2389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mediaPlayer = null; 2399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void playBeep() { 2439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (mediaPlayer != null) { 2449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mediaPlayer.start(); 2459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (wantBellVibration) { 2479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li vibrate(); 2489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private static class BeepListener implements OnCompletionListener { 2529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void onCompletion(MediaPlayer mp) { 2539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mp.seekTo(0); 2549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public boolean isHardKeyboardHidden() { 2589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return hardKeyboardHidden; 2599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void setHardKeyboardHidden(boolean b) { 2629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li hardKeyboardHidden = b; 2639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 2669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { 2679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (PreferenceConstants.BELL.equals(key)) { 2689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li wantAudible = sharedPreferences.getBoolean(PreferenceConstants.BELL, true); 2699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (wantAudible && mediaPlayer == null) { 2709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li enableMediaPlayer(); 2719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else if (!wantAudible && mediaPlayer != null) { 2729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li disableMediaPlayer(); 2739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else if (PreferenceConstants.BELL_VOLUME.equals(key)) { 2759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (mediaPlayer != null) { 2769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li float volume = 2779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li sharedPreferences.getFloat(PreferenceConstants.BELL_VOLUME, 2789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li PreferenceConstants.DEFAULT_BELL_VOLUME); 2799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mediaPlayer.setVolume(volume, volume); 2809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else if (PreferenceConstants.BELL_VIBRATE.equals(key)) { 2829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li wantBellVibration = sharedPreferences.getBoolean(PreferenceConstants.BELL_VIBRATE, true); 2839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else if (PreferenceConstants.BUMPY_ARROWS.equals(key)) { 2849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li wantKeyVibration = sharedPreferences.getBoolean(PreferenceConstants.BUMPY_ARROWS, true); 2859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void setDisconnectHandler(Handler disconnectHandler) { 2899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mDisconnectHandler = disconnectHandler; 2909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public List<TerminalBridge> getBridgeList() { 2939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return bridges; 2949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public Resources getResources() { 2979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return mResources; 2989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 3009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) { 3019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mPreferences.registerOnSharedPreferenceChangeListener(listener); 3029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 3039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 3049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li} 305