1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.support.v4.media;
18 
19 import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
20 
21 import android.os.Build;
22 import android.support.annotation.IntDef;
23 import android.support.annotation.RestrictTo;
24 import android.support.v4.media.session.MediaSessionCompat;
25 
26 import java.lang.annotation.Retention;
27 import java.lang.annotation.RetentionPolicy;
28 
29 /**
30  * Handles requests to adjust or set the volume on a session. This is also used
31  * to push volume updates back to the session after a request has been handled.
32  * You can set a volume provider on a session by calling
33  * {@link MediaSessionCompat#setPlaybackToRemote}.
34  */
35 public abstract class VolumeProviderCompat {
36 
37     /**
38      * @hide
39      */
40     @RestrictTo(LIBRARY_GROUP)
41     @IntDef({VOLUME_CONTROL_FIXED, VOLUME_CONTROL_RELATIVE, VOLUME_CONTROL_ABSOLUTE})
42     @Retention(RetentionPolicy.SOURCE)
43     public @interface ControlType {}
44 
45     /**
46      * The volume is fixed and can not be modified. Requests to change volume
47      * should be ignored.
48      */
49     public static final int VOLUME_CONTROL_FIXED = 0;
50 
51     /**
52      * The volume control uses relative adjustment via
53      * {@link #onAdjustVolume(int)}. Attempts to set the volume to a specific
54      * value should be ignored.
55      */
56     public static final int VOLUME_CONTROL_RELATIVE = 1;
57 
58     /**
59      * The volume control uses an absolute value. It may be adjusted using
60      * {@link #onAdjustVolume(int)} or set directly using
61      * {@link #onSetVolumeTo(int)}.
62      */
63     public static final int VOLUME_CONTROL_ABSOLUTE = 2;
64 
65     private final int mControlType;
66     private final int mMaxVolume;
67     private int mCurrentVolume;
68     private Callback mCallback;
69 
70     private Object mVolumeProviderObj;
71 
72     /**
73      * Create a new volume provider for handling volume events. You must specify
74      * the type of volume control and the maximum volume that can be used.
75      *
76      * @param volumeControl The method for controlling volume that is used by
77      *            this provider.
78      * @param maxVolume The maximum allowed volume.
79      * @param currentVolume The current volume.
80      */
VolumeProviderCompat(@ontrolType int volumeControl, int maxVolume, int currentVolume)81     public VolumeProviderCompat(@ControlType int volumeControl, int maxVolume, int currentVolume) {
82         mControlType = volumeControl;
83         mMaxVolume = maxVolume;
84         mCurrentVolume = currentVolume;
85     }
86 
87     /**
88      * Get the current volume of the provider.
89      *
90      * @return The current volume.
91      */
getCurrentVolume()92     public final int getCurrentVolume() {
93         return mCurrentVolume;
94     }
95 
96     /**
97      * Get the volume control type that this volume provider uses.
98      *
99      * @return The volume control type for this volume provider
100      */
101     @ControlType
getVolumeControl()102     public final int getVolumeControl() {
103         return mControlType;
104     }
105 
106     /**
107      * Get the maximum volume this provider allows.
108      *
109      * @return The max allowed volume.
110      */
getMaxVolume()111     public final int getMaxVolume() {
112         return mMaxVolume;
113     }
114 
115     /**
116      * Set the current volume and notify the system that the volume has been
117      * changed.
118      *
119      * @param currentVolume The current volume of the output.
120      */
setCurrentVolume(int currentVolume)121     public final void setCurrentVolume(int currentVolume) {
122         mCurrentVolume = currentVolume;
123         Object volumeProviderObj = getVolumeProvider();
124         if (volumeProviderObj != null && Build.VERSION.SDK_INT >= 21) {
125             VolumeProviderCompatApi21.setCurrentVolume(volumeProviderObj, currentVolume);
126         }
127         if (mCallback != null) {
128             mCallback.onVolumeChanged(this);
129         }
130     }
131 
132     /**
133      * Override to handle requests to set the volume of the current output.
134      *
135      * @param volume The volume to set the output to.
136      */
onSetVolumeTo(int volume)137     public void onSetVolumeTo(int volume) {
138     }
139 
140     /**
141      * Override to handle requests to adjust the volume of the current output.
142      *
143      * @param direction The direction to adjust the volume in.
144      */
onAdjustVolume(int direction)145     public void onAdjustVolume(int direction) {
146     }
147 
148     /**
149      * Sets a callback to receive volume changes.
150      * <p>
151      * Used internally by the support library.
152      * <p>
153      */
setCallback(Callback callback)154     public void setCallback(Callback callback) {
155         mCallback = callback;
156     }
157 
158     /**
159      * Gets the underlying framework {@link android.media.VolumeProvider} object.
160      * <p>
161      * This method is only supported on API 21+.
162      * </p>
163      *
164      * @return An equivalent {@link android.media.VolumeProvider} object, or null if none.
165      */
getVolumeProvider()166     public Object getVolumeProvider() {
167         if (mVolumeProviderObj == null && Build.VERSION.SDK_INT >= 21) {
168             mVolumeProviderObj = VolumeProviderCompatApi21.createVolumeProvider(
169                     mControlType, mMaxVolume, mCurrentVolume,
170                     new VolumeProviderCompatApi21.Delegate() {
171 
172                         @Override
173                         public void onSetVolumeTo(int volume) {
174                             VolumeProviderCompat.this.onSetVolumeTo(volume);
175                         }
176 
177                         @Override
178                         public void onAdjustVolume(int direction) {
179                             VolumeProviderCompat.this.onAdjustVolume(direction);
180                         }
181                     });
182         }
183         return mVolumeProviderObj;
184     }
185 
186     /**
187      * Listens for changes to the volume.
188      */
189     public static abstract class Callback {
onVolumeChanged(VolumeProviderCompat volumeProvider)190         public abstract void onVolumeChanged(VolumeProviderCompat volumeProvider);
191     }
192 }
193