1 /***
2 * Ambient - A music player for the Android platform
3 Copyright (C) 2007 Martin Vysny
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 package sk.baka.ambient;
20
21 import sk.baka.ambient.collection.TrackMetadataBean;
22 import sk.baka.ambient.commons.Interval;
23 import sk.baka.ambient.playerservice.PlayerStateEnum;
24 import sk.baka.ambient.playlist.PlaylistItem;
25 import sk.baka.ambient.playlist.Random;
26 import sk.baka.ambient.playlist.Repeat;
27 import android.content.BroadcastReceiver;
28 import android.content.Context;
29 import android.content.Intent;
30 import android.content.IntentFilter;
31 import android.net.ConnectivityManager;
32 import android.net.NetworkInfo;
33 import android.net.wifi.WifiManager;
34 import android.net.wifi.WifiManager.WifiLock;
35 import android.util.Log;
36
37 /***
38 * Ensures that the WiFi is not turned off while playing an online content.
39 * Thread-unsafe, should be invoked from the main Handler instance only.
40 *
41 * @author Martin Vysny
42 */
43 final class PowerHandler extends BroadcastReceiver implements
44 IPlaylistPlayerListener {
45
46 private final AmbientApplication app;
47
48 /***
49 * Creates new power handler.
50 *
51 * @param app
52 * owner application.
53 */
54 public PowerHandler(final AmbientApplication app) {
55 this.app = app;
56 app.getBus().addHandler(this);
57 app.registerReceiver(this, new IntentFilter(
58 ConnectivityManager.CONNECTIVITY_ACTION));
59 }
60
61 public void playbackStateChanged(PlayerStateEnum state) {
62 if (state == PlayerStateEnum.Stopped) {
63 freeWifiLock();
64 } else if (state == PlayerStateEnum.Playing) {
65 lockWifiIfNecessary(null, false);
66 }
67 }
68
69 public void playlistChanged(Interval target) {
70
71 }
72
73 public void randomChanged(Random random) {
74
75 }
76
77 public void repeatChanged(Repeat repeat) {
78
79 }
80
81 public void trackChanged(PlaylistItem track, boolean play,
82 int positionMillis) {
83 if (play) {
84 if (track.getTrack().isLocal()) {
85 freeWifiLock();
86 return;
87 }
88 lockWifiIfNecessary(track.getTrack(), false);
89 }
90 }
91
92 private void lockWifiIfNecessary(final TrackMetadataBean track,
93 final boolean wifiConnected) {
94 if (wifiLock != null) {
95
96 return;
97 }
98 if (track == null) {
99 final TrackMetadataBean t = app.getPlaylist()
100 .getCurrentlyPlayingTrack();
101 if (t != null) {
102 lockWifiIfNecessary(t, wifiConnected);
103 }
104 return;
105 }
106 if (track.isLocal()) {
107 return;
108 }
109 if (!wifiConnected && !isWifiConnected()) {
110 return;
111 }
112
113 final WifiManager wifiMan = (WifiManager) app
114 .getSystemService(Context.WIFI_SERVICE);
115 wifiLock = wifiMan.createWifiLock(PowerHandler.class.getName());
116 Log.i(PowerHandler.class.getSimpleName(), "Acquiring WiFi lock");
117 wifiLock.acquire();
118 }
119
120 private boolean isWifiConnected() {
121 final ConnectivityManager manager = (ConnectivityManager) app
122 .getSystemService(Context.CONNECTIVITY_SERVICE);
123 final NetworkInfo info = manager
124 .getNetworkInfo(ConnectivityManager.TYPE_WIFI);
125 return info != null && info.isConnected();
126 }
127
128 private WifiLock wifiLock = null;
129
130 public void trackPositionChanged(int position, boolean playing) {
131
132 }
133
134 /***
135 * Destroys this handler and drops any power locks being held.
136 */
137 void destroy() {
138 app.unregisterReceiver(this);
139 freeWifiLock();
140 }
141
142 private void freeWifiLock() {
143 if (wifiLock != null) {
144 Log.i(PowerHandler.class.getSimpleName(), "Dropping WiFi lock");
145 wifiLock.release();
146 wifiLock = null;
147 }
148 }
149
150 @Override
151 public void onReceive(Context context, Intent intent) {
152 if (intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY,
153 false)) {
154 freeWifiLock();
155 return;
156 }
157 if (intent
158 .getBooleanExtra(ConnectivityManager.EXTRA_IS_FAILOVER, false)) {
159 final boolean isPlaying = app.getPlaylist().getPlaybackState() == PlayerStateEnum.Playing;
160 if (!isPlaying) {
161
162 return;
163 }
164 final NetworkInfo newInfo = intent
165 .getParcelableExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO);
166 if (newInfo == null) {
167
168 return;
169 }
170 if (newInfo.getType() == ConnectivityManager.TYPE_WIFI) {
171 lockWifiIfNecessary(null, true);
172 return;
173 }
174
175
176 if (!isWifiConnected()) {
177 freeWifiLock();
178 }
179 }
180 }
181 }