[go: nahoru, domu]

1098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey/*
2098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey * Copyright (C) 2012 The Android Open Source Project
3098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey *
4098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
5098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey * you may not use this file except in compliance with the License.
6098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey * You may obtain a copy of the License at
7098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey *
8098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
9098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey *
10098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey * Unless required by applicable law or agreed to in writing, software
11098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
12098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey * See the License for the specific language governing permissions and
14098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey * limitations under the License.
15098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey */
16098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey
17098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkeypackage com.android.systemui.media;
18098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey
19783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkeyimport android.content.ContentResolver;
20098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkeyimport android.content.Context;
2165c4a2b26cd8776b0927e9b0e07ecf53bd31b627Jeff Sharkeyimport android.content.pm.PackageManager.NameNotFoundException;
22783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkeyimport android.database.Cursor;
2381f871e2b96125d57b76c07169e868e516443794Jean-Michel Triviimport android.media.AudioAttributes;
24098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkeyimport android.media.IAudioService;
25098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkeyimport android.media.IRingtonePlayer;
26098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkeyimport android.media.Ringtone;
27098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkeyimport android.net.Uri;
28098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkeyimport android.os.Binder;
29098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkeyimport android.os.IBinder;
30783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkeyimport android.os.ParcelFileDescriptor;
31098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkeyimport android.os.Process;
32098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkeyimport android.os.RemoteException;
33098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkeyimport android.os.ServiceManager;
3465c4a2b26cd8776b0927e9b0e07ecf53bd31b627Jeff Sharkeyimport android.os.UserHandle;
35783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkeyimport android.provider.MediaStore;
36783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkeyimport android.provider.MediaStore.Audio.AudioColumns;
37cd686b5b6d4166b510df8e32138479a9559bc117John Spurlockimport android.util.Log;
38098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey
39783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkeyimport com.android.internal.util.Preconditions;
40098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkeyimport com.android.systemui.SystemUI;
41098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey
42098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkeyimport java.io.FileDescriptor;
43783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkeyimport java.io.IOException;
44098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkeyimport java.io.PrintWriter;
45098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkeyimport java.util.HashMap;
46098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey
47098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey/**
48098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey * Service that offers to play ringtones by {@link Uri}, since our process has
49098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE}.
50098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey */
51098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkeypublic class RingtonePlayer extends SystemUI {
52098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey    private static final String TAG = "RingtonePlayer";
53b6e404a95f31f4681265eb53d2b7969f900151ccJeff Sharkey    private static final boolean LOGD = false;
54098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey
55098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey    // TODO: support Uri switching under same IBinder
56098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey
57098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey    private IAudioService mAudioService;
58098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey
59098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey    private final NotificationPlayer mAsyncPlayer = new NotificationPlayer(TAG);
60b8bacccfc159fe204e5b09b52de55f8ba853f713John Spurlock    private final HashMap<IBinder, Client> mClients = new HashMap<IBinder, Client>();
61098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey
62098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey    @Override
63098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey    public void start() {
64098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey        mAsyncPlayer.setUsesWakeLock(mContext);
65098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey
66098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey        mAudioService = IAudioService.Stub.asInterface(
67098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey                ServiceManager.getService(Context.AUDIO_SERVICE));
68098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey        try {
69098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey            mAudioService.setRingtonePlayer(mCallback);
70098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey        } catch (RemoteException e) {
71cd686b5b6d4166b510df8e32138479a9559bc117John Spurlock            Log.e(TAG, "Problem registering RingtonePlayer: " + e);
72098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey        }
73098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey    }
74098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey
75098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey    /**
76098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey     * Represents an active remote {@link Ringtone} client.
77098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey     */
78098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey    private class Client implements IBinder.DeathRecipient {
79098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey        private final IBinder mToken;
80098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey        private final Ringtone mRingtone;
81098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey
8281f871e2b96125d57b76c07169e868e516443794Jean-Michel Trivi        public Client(IBinder token, Uri uri, UserHandle user, AudioAttributes aa) {
83098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey            mToken = token;
8465c4a2b26cd8776b0927e9b0e07ecf53bd31b627Jeff Sharkey
8565c4a2b26cd8776b0927e9b0e07ecf53bd31b627Jeff Sharkey            mRingtone = new Ringtone(getContextForUser(user), false);
8681f871e2b96125d57b76c07169e868e516443794Jean-Michel Trivi            mRingtone.setAudioAttributes(aa);
87098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey            mRingtone.setUri(uri);
88098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey        }
89098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey
90098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey        @Override
91098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey        public void binderDied() {
92cd686b5b6d4166b510df8e32138479a9559bc117John Spurlock            if (LOGD) Log.d(TAG, "binderDied() token=" + mToken);
93098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey            synchronized (mClients) {
94098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey                mClients.remove(mToken);
95098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey            }
96098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey            mRingtone.stop();
97098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey        }
98098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey    }
99098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey
100098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey    private IRingtonePlayer mCallback = new IRingtonePlayer.Stub() {
101098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey        @Override
102462045e89aed0163a4681b8221f0df3f26900136Jean-Michel Trivi        public void play(IBinder token, Uri uri, AudioAttributes aa, float volume, boolean looping)
103462045e89aed0163a4681b8221f0df3f26900136Jean-Michel Trivi                throws RemoteException {
10465c4a2b26cd8776b0927e9b0e07ecf53bd31b627Jeff Sharkey            if (LOGD) {
105cd686b5b6d4166b510df8e32138479a9559bc117John Spurlock                Log.d(TAG, "play(token=" + token + ", uri=" + uri + ", uid="
10665c4a2b26cd8776b0927e9b0e07ecf53bd31b627Jeff Sharkey                        + Binder.getCallingUid() + ")");
10765c4a2b26cd8776b0927e9b0e07ecf53bd31b627Jeff Sharkey            }
108098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey            Client client;
109098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey            synchronized (mClients) {
110098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey                client = mClients.get(token);
111098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey                if (client == null) {
11265c4a2b26cd8776b0927e9b0e07ecf53bd31b627Jeff Sharkey                    final UserHandle user = Binder.getCallingUserHandle();
11381f871e2b96125d57b76c07169e868e516443794Jean-Michel Trivi                    client = new Client(token, uri, user, aa);
114098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey                    token.linkToDeath(client, 0);
115098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey                    mClients.put(token, client);
116098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey                }
117098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey            }
118462045e89aed0163a4681b8221f0df3f26900136Jean-Michel Trivi            client.mRingtone.setLooping(looping);
119462045e89aed0163a4681b8221f0df3f26900136Jean-Michel Trivi            client.mRingtone.setVolume(volume);
120098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey            client.mRingtone.play();
121098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey        }
122098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey
123098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey        @Override
124098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey        public void stop(IBinder token) {
125cd686b5b6d4166b510df8e32138479a9559bc117John Spurlock            if (LOGD) Log.d(TAG, "stop(token=" + token + ")");
126098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey            Client client;
127098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey            synchronized (mClients) {
128098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey                client = mClients.remove(token);
129098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey            }
130098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey            if (client != null) {
131098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey                client.mToken.unlinkToDeath(client, 0);
132098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey                client.mRingtone.stop();
133098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey            }
134098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey        }
135098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey
136098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey        @Override
137098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey        public boolean isPlaying(IBinder token) {
138cd686b5b6d4166b510df8e32138479a9559bc117John Spurlock            if (LOGD) Log.d(TAG, "isPlaying(token=" + token + ")");
139098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey            Client client;
140098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey            synchronized (mClients) {
141098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey                client = mClients.get(token);
142098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey            }
143098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey            if (client != null) {
144098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey                return client.mRingtone.isPlaying();
145098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey            } else {
146098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey                return false;
147098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey            }
148098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey        }
149098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey
150098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey        @Override
151462045e89aed0163a4681b8221f0df3f26900136Jean-Michel Trivi        public void setPlaybackProperties(IBinder token, float volume, boolean looping) {
152462045e89aed0163a4681b8221f0df3f26900136Jean-Michel Trivi            Client client;
153462045e89aed0163a4681b8221f0df3f26900136Jean-Michel Trivi            synchronized (mClients) {
154462045e89aed0163a4681b8221f0df3f26900136Jean-Michel Trivi                client = mClients.get(token);
155462045e89aed0163a4681b8221f0df3f26900136Jean-Michel Trivi            }
156462045e89aed0163a4681b8221f0df3f26900136Jean-Michel Trivi            if (client != null) {
157462045e89aed0163a4681b8221f0df3f26900136Jean-Michel Trivi                client.mRingtone.setVolume(volume);
158462045e89aed0163a4681b8221f0df3f26900136Jean-Michel Trivi                client.mRingtone.setLooping(looping);
159462045e89aed0163a4681b8221f0df3f26900136Jean-Michel Trivi            }
160462045e89aed0163a4681b8221f0df3f26900136Jean-Michel Trivi            // else no client for token when setting playback properties but will be set at play()
161462045e89aed0163a4681b8221f0df3f26900136Jean-Michel Trivi        }
162462045e89aed0163a4681b8221f0df3f26900136Jean-Michel Trivi
163462045e89aed0163a4681b8221f0df3f26900136Jean-Michel Trivi        @Override
16481f871e2b96125d57b76c07169e868e516443794Jean-Michel Trivi        public void playAsync(Uri uri, UserHandle user, boolean looping, AudioAttributes aa) {
165cd686b5b6d4166b510df8e32138479a9559bc117John Spurlock            if (LOGD) Log.d(TAG, "playAsync(uri=" + uri + ", user=" + user + ")");
166098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey            if (Binder.getCallingUid() != Process.SYSTEM_UID) {
167098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey                throw new SecurityException("Async playback only available from system UID.");
168098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey            }
1694a05bbcd38604cbbcbac66af1abc69ecffddad8bSungmin Choi            if (UserHandle.ALL.equals(user)) {
170e4de5a0d3b6e0c897c1cea0912b58e11db962365Xiaohui Chen                user = UserHandle.SYSTEM;
1714a05bbcd38604cbbcbac66af1abc69ecffddad8bSungmin Choi            }
17281f871e2b96125d57b76c07169e868e516443794Jean-Michel Trivi            mAsyncPlayer.play(getContextForUser(user), uri, looping, aa);
173098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey        }
174098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey
175098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey        @Override
176098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey        public void stopAsync() {
177cd686b5b6d4166b510df8e32138479a9559bc117John Spurlock            if (LOGD) Log.d(TAG, "stopAsync()");
178098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey            if (Binder.getCallingUid() != Process.SYSTEM_UID) {
179098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey                throw new SecurityException("Async playback only available from system UID.");
180098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey            }
181098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey            mAsyncPlayer.stop();
182098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey        }
18368de157b7810be72a283b9e0db292895d96988a9Todd Kennedy
18468de157b7810be72a283b9e0db292895d96988a9Todd Kennedy        @Override
18568de157b7810be72a283b9e0db292895d96988a9Todd Kennedy        public String getTitle(Uri uri) {
18668de157b7810be72a283b9e0db292895d96988a9Todd Kennedy            final UserHandle user = Binder.getCallingUserHandle();
18768de157b7810be72a283b9e0db292895d96988a9Todd Kennedy            return Ringtone.getTitle(getContextForUser(user), uri,
18868de157b7810be72a283b9e0db292895d96988a9Todd Kennedy                    false /*followSettingsUri*/, false /*allowRemote*/);
18968de157b7810be72a283b9e0db292895d96988a9Todd Kennedy        }
190783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkey
191783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkey        @Override
192783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkey        public ParcelFileDescriptor openRingtone(Uri uri) {
193783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkey            final UserHandle user = Binder.getCallingUserHandle();
194783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkey            final ContentResolver resolver = getContextForUser(user).getContentResolver();
195783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkey
196783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkey            // Only open the requested Uri if it's a well-known ringtone or
197783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkey            // other sound from the platform media store, otherwise this opens
198783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkey            // up arbitrary access to any file on external storage.
199783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkey            if (uri.toString().startsWith(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI.toString())) {
200783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkey                try (Cursor c = resolver.query(uri, new String[] {
201783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkey                        MediaStore.Audio.AudioColumns.IS_RINGTONE,
202783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkey                        MediaStore.Audio.AudioColumns.IS_ALARM,
203783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkey                        MediaStore.Audio.AudioColumns.IS_NOTIFICATION
204783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkey                }, null, null, null)) {
205783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkey                    if (c.moveToFirst()) {
206783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkey                        if (c.getInt(0) != 0 || c.getInt(1) != 0 || c.getInt(2) != 0) {
207783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkey                            try {
208783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkey                                return resolver.openFileDescriptor(uri, "r");
209783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkey                            } catch (IOException e) {
210783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkey                                throw new SecurityException(e);
211783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkey                            }
212783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkey                        }
213783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkey                    }
214783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkey                }
215783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkey            }
216783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkey            throw new SecurityException("Uri is not ringtone, alarm, or notification: " + uri);
217783ee0ca8707a4e2977d1afd42cd01a3885a06e6Jeff Sharkey        }
218098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey    };
219098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey
22065c4a2b26cd8776b0927e9b0e07ecf53bd31b627Jeff Sharkey    private Context getContextForUser(UserHandle user) {
22165c4a2b26cd8776b0927e9b0e07ecf53bd31b627Jeff Sharkey        try {
22265c4a2b26cd8776b0927e9b0e07ecf53bd31b627Jeff Sharkey            return mContext.createPackageContextAsUser(mContext.getPackageName(), 0, user);
22365c4a2b26cd8776b0927e9b0e07ecf53bd31b627Jeff Sharkey        } catch (NameNotFoundException e) {
22465c4a2b26cd8776b0927e9b0e07ecf53bd31b627Jeff Sharkey            throw new RuntimeException(e);
22565c4a2b26cd8776b0927e9b0e07ecf53bd31b627Jeff Sharkey        }
22665c4a2b26cd8776b0927e9b0e07ecf53bd31b627Jeff Sharkey    }
22765c4a2b26cd8776b0927e9b0e07ecf53bd31b627Jeff Sharkey
228098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey    @Override
229098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
230098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey        pw.println("Clients:");
231098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey        synchronized (mClients) {
232098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey            for (Client client : mClients.values()) {
233098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey                pw.print("  mToken=");
234098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey                pw.print(client.mToken);
235098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey                pw.print(" mUri=");
236098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey                pw.println(client.mRingtone.getUri());
237098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey            }
238098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey        }
239098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey    }
240098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey}
241