Loading src/com/android/server/telecom/AsyncRingtonePlayer.java +8 −5 Original line number Original line Diff line number Diff line Loading @@ -47,11 +47,11 @@ public class AsyncRingtonePlayer { private Ringtone mRingtone; private Ringtone mRingtone; /** Plays the ringtone. */ /** Plays the ringtone. */ public void play(RingtoneFactory factory, Uri ringtoneUri) { public void play(RingtoneFactory factory, Call incomingCall) { Log.d(this, "Posting play."); Log.d(this, "Posting play."); SomeArgs args = SomeArgs.obtain(); SomeArgs args = SomeArgs.obtain(); args.arg1 = factory; args.arg1 = factory; args.arg2 = ringtoneUri; args.arg2 = incomingCall; postMessage(EVENT_PLAY, true /* shouldCreateHandler */, args); postMessage(EVENT_PLAY, true /* shouldCreateHandler */, args); } } Loading Loading @@ -114,7 +114,7 @@ public class AsyncRingtonePlayer { */ */ private void handlePlay(SomeArgs args) { private void handlePlay(SomeArgs args) { RingtoneFactory factory = (RingtoneFactory) args.arg1; RingtoneFactory factory = (RingtoneFactory) args.arg1; Uri ringtoneUri = (Uri) args.arg2; Call incomingCall = (Call) args.arg2; args.recycle(); args.recycle(); // don't bother with any of this if there is an EVENT_STOP waiting. // don't bother with any of this if there is an EVENT_STOP waiting. if (mHandler.hasMessages(EVENT_STOP)) { if (mHandler.hasMessages(EVENT_STOP)) { Loading @@ -125,10 +125,13 @@ public class AsyncRingtonePlayer { Log.i(this, "Play ringtone."); Log.i(this, "Play ringtone."); if (mRingtone == null) { if (mRingtone == null) { mRingtone = factory.getRingtone(ringtoneUri); mRingtone = factory.getRingtone(incomingCall); if (mRingtone == null) { if (mRingtone == null) { Uri ringtoneUri = incomingCall.getRingtone(); String ringtoneUriString = (ringtoneUri == null) ? "null" : ringtoneUri.toSafeString(); Log.event(null, Log.Events.ERROR_LOG, "Failed to get ringtone from factory. " + Log.event(null, Log.Events.ERROR_LOG, "Failed to get ringtone from factory. " + "Skipping ringing. Uri was: " + ringtoneUri.toSafeString()); "Skipping ringing. Uri was: " + ringtoneUriString); return; return; } } } } Loading src/com/android/server/telecom/CallsManager.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -235,7 +235,7 @@ public class CallsManager extends Call.ListenerBase callAudioRoutePeripheralAdapter, lock); callAudioRoutePeripheralAdapter, lock); SystemSettingsUtil systemSettingsUtil = new SystemSettingsUtil(); SystemSettingsUtil systemSettingsUtil = new SystemSettingsUtil(); RingtoneFactory ringtoneFactory = new RingtoneFactory(context); RingtoneFactory ringtoneFactory = new RingtoneFactory(this, context); SystemVibrator systemVibrator = new SystemVibrator(context); SystemVibrator systemVibrator = new SystemVibrator(context); AsyncRingtonePlayer asyncRingtonePlayer = new AsyncRingtonePlayer(); AsyncRingtonePlayer asyncRingtonePlayer = new AsyncRingtonePlayer(); mInCallController = new InCallController(context, mLock, this, systemStateProvider); mInCallController = new InCallController(context, mLock, this, systemStateProvider); Loading src/com/android/server/telecom/Ringer.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -124,7 +124,7 @@ public final class Ringer { // call (for the purposes of direct-to-voicemail), the information about custom // call (for the purposes of direct-to-voicemail), the information about custom // ringtones should be available by the time this code executes. We can safely // ringtones should be available by the time this code executes. We can safely // request the custom ringtone from the call and expect it to be current. // request the custom ringtone from the call and expect it to be current. mRingtonePlayer.play(mRingtoneFactory, foregroundCall.getRingtone()); mRingtonePlayer.play(mRingtoneFactory, foregroundCall); } else { } else { Log.v(this, "startRingingOrCallWaiting, skipping because volume is 0"); Log.v(this, "startRingingOrCallWaiting, skipping because volume is 0"); } } Loading src/com/android/server/telecom/RingtoneFactory.java +82 −8 Original line number Original line Diff line number Diff line Loading @@ -17,36 +17,110 @@ package com.android.server.telecom; package com.android.server.telecom; import android.content.Context; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.media.AudioManager; import android.media.AudioManager; import android.media.RingtoneManager; import android.media.RingtoneManager; import android.media.Ringtone; import android.media.Ringtone; import android.net.Uri; import android.net.Uri; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import android.provider.Settings; import android.telecom.PhoneAccount; import android.text.TextUtils; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.CallerInfo; import java.util.List; /** /** * Uses a Uri to obtain a {@link Ringtone} from the {@link RingtoneManager} that can be played * Uses the incoming {@link Call}'s ringtone URI (obtained by the Contact Lookup) to obtain a * by the system during an incoming call. * {@link Ringtone} from the {@link RingtoneManager} that can be played by the system during an * incoming call. If the ringtone URI is null, use the default Ringtone for the active user. */ */ @VisibleForTesting @VisibleForTesting public class RingtoneFactory { public class RingtoneFactory { private final Context mContext; private final Context mContext; private final CallsManager mCallsManager; public RingtoneFactory(Context context) { public RingtoneFactory(CallsManager callsManager, Context context) { mContext = context; mContext = context; mCallsManager = callsManager; } } public Ringtone getRingtone(Uri ringtoneUri) { public Ringtone getRingtone(Call incomingCall) { if (ringtoneUri == null) { // Use the default ringtone of the work profile if the contact is a work profile contact. ringtoneUri = Settings.System.DEFAULT_RINGTONE_URI; Context userContext = isWorkContact(incomingCall) ? } getWorkProfileContextForUser(mCallsManager.getCurrentUserHandle()) : getContextForUserHandle(mCallsManager.getCurrentUserHandle()); Uri ringtoneUri = incomingCall.getRingtone(); Ringtone ringtone = null; Ringtone ringtone = RingtoneManager.getRingtone(mContext, ringtoneUri); if(ringtoneUri != null && userContext != null) { // Ringtone URI is explicitly specified. First, try to create a Ringtone with that. ringtone = RingtoneManager.getRingtone(userContext, ringtoneUri); } if(ringtone == null) { // Contact didn't specify ringtone or custom Ringtone creation failed. Get default // ringtone for user or profile. ringtone = RingtoneManager.getRingtone( hasDefaultRingtoneForUser(userContext) ? userContext : mContext, Settings.System.DEFAULT_RINGTONE_URI); } if (ringtone != null) { if (ringtone != null) { ringtone.setStreamType(AudioManager.STREAM_RING); ringtone.setStreamType(AudioManager.STREAM_RING); } } return ringtone; return ringtone; } } private Context getWorkProfileContextForUser(UserHandle userHandle) { // UserManager.getEnabledProfiles returns the enabled profiles along with the user's handle // itself (so we must filter out the user). List<UserInfo> profiles = UserManager.get(mContext).getEnabledProfiles( userHandle.getIdentifier()); UserInfo workprofile = null; int managedProfileCount = 0; for (UserInfo profile : profiles) { UserHandle profileUserHandle = profile.getUserHandle(); if (profileUserHandle != userHandle && profile.isManagedProfile()) { managedProfileCount++; workprofile = profile; } } // There may be many different types of profiles, so only count Managed (Work) Profiles. if(managedProfileCount == 1) { return getContextForUserHandle(workprofile.getUserHandle()); } // There are multiple managed profiles for the associated user and we do not have enough // info to determine which profile is the work profile. Just use the default. return null; } private Context getContextForUserHandle(UserHandle userHandle) { if(userHandle == null) { return null; } try { return mContext.createPackageContextAsUser(mContext.getPackageName(), 0, userHandle); } catch (PackageManager.NameNotFoundException e) { Log.w("RingtoneFactory", "Package name not found: " + e.getMessage()); } return null; } private boolean hasDefaultRingtoneForUser(Context userContext) { if(userContext == null) { return false; } return !TextUtils.isEmpty(Settings.System.getString(userContext.getContentResolver(), Settings.System.RINGTONE)); } private boolean isWorkContact(Call incomingCall) { CallerInfo contactCallerInfo = incomingCall.getCallerInfo(); return (contactCallerInfo != null) && (contactCallerInfo.userType == CallerInfo.USER_TYPE_WORK); } } } Loading
src/com/android/server/telecom/AsyncRingtonePlayer.java +8 −5 Original line number Original line Diff line number Diff line Loading @@ -47,11 +47,11 @@ public class AsyncRingtonePlayer { private Ringtone mRingtone; private Ringtone mRingtone; /** Plays the ringtone. */ /** Plays the ringtone. */ public void play(RingtoneFactory factory, Uri ringtoneUri) { public void play(RingtoneFactory factory, Call incomingCall) { Log.d(this, "Posting play."); Log.d(this, "Posting play."); SomeArgs args = SomeArgs.obtain(); SomeArgs args = SomeArgs.obtain(); args.arg1 = factory; args.arg1 = factory; args.arg2 = ringtoneUri; args.arg2 = incomingCall; postMessage(EVENT_PLAY, true /* shouldCreateHandler */, args); postMessage(EVENT_PLAY, true /* shouldCreateHandler */, args); } } Loading Loading @@ -114,7 +114,7 @@ public class AsyncRingtonePlayer { */ */ private void handlePlay(SomeArgs args) { private void handlePlay(SomeArgs args) { RingtoneFactory factory = (RingtoneFactory) args.arg1; RingtoneFactory factory = (RingtoneFactory) args.arg1; Uri ringtoneUri = (Uri) args.arg2; Call incomingCall = (Call) args.arg2; args.recycle(); args.recycle(); // don't bother with any of this if there is an EVENT_STOP waiting. // don't bother with any of this if there is an EVENT_STOP waiting. if (mHandler.hasMessages(EVENT_STOP)) { if (mHandler.hasMessages(EVENT_STOP)) { Loading @@ -125,10 +125,13 @@ public class AsyncRingtonePlayer { Log.i(this, "Play ringtone."); Log.i(this, "Play ringtone."); if (mRingtone == null) { if (mRingtone == null) { mRingtone = factory.getRingtone(ringtoneUri); mRingtone = factory.getRingtone(incomingCall); if (mRingtone == null) { if (mRingtone == null) { Uri ringtoneUri = incomingCall.getRingtone(); String ringtoneUriString = (ringtoneUri == null) ? "null" : ringtoneUri.toSafeString(); Log.event(null, Log.Events.ERROR_LOG, "Failed to get ringtone from factory. " + Log.event(null, Log.Events.ERROR_LOG, "Failed to get ringtone from factory. " + "Skipping ringing. Uri was: " + ringtoneUri.toSafeString()); "Skipping ringing. Uri was: " + ringtoneUriString); return; return; } } } } Loading
src/com/android/server/telecom/CallsManager.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -235,7 +235,7 @@ public class CallsManager extends Call.ListenerBase callAudioRoutePeripheralAdapter, lock); callAudioRoutePeripheralAdapter, lock); SystemSettingsUtil systemSettingsUtil = new SystemSettingsUtil(); SystemSettingsUtil systemSettingsUtil = new SystemSettingsUtil(); RingtoneFactory ringtoneFactory = new RingtoneFactory(context); RingtoneFactory ringtoneFactory = new RingtoneFactory(this, context); SystemVibrator systemVibrator = new SystemVibrator(context); SystemVibrator systemVibrator = new SystemVibrator(context); AsyncRingtonePlayer asyncRingtonePlayer = new AsyncRingtonePlayer(); AsyncRingtonePlayer asyncRingtonePlayer = new AsyncRingtonePlayer(); mInCallController = new InCallController(context, mLock, this, systemStateProvider); mInCallController = new InCallController(context, mLock, this, systemStateProvider); Loading
src/com/android/server/telecom/Ringer.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -124,7 +124,7 @@ public final class Ringer { // call (for the purposes of direct-to-voicemail), the information about custom // call (for the purposes of direct-to-voicemail), the information about custom // ringtones should be available by the time this code executes. We can safely // ringtones should be available by the time this code executes. We can safely // request the custom ringtone from the call and expect it to be current. // request the custom ringtone from the call and expect it to be current. mRingtonePlayer.play(mRingtoneFactory, foregroundCall.getRingtone()); mRingtonePlayer.play(mRingtoneFactory, foregroundCall); } else { } else { Log.v(this, "startRingingOrCallWaiting, skipping because volume is 0"); Log.v(this, "startRingingOrCallWaiting, skipping because volume is 0"); } } Loading
src/com/android/server/telecom/RingtoneFactory.java +82 −8 Original line number Original line Diff line number Diff line Loading @@ -17,36 +17,110 @@ package com.android.server.telecom; package com.android.server.telecom; import android.content.Context; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.media.AudioManager; import android.media.AudioManager; import android.media.RingtoneManager; import android.media.RingtoneManager; import android.media.Ringtone; import android.media.Ringtone; import android.net.Uri; import android.net.Uri; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import android.provider.Settings; import android.telecom.PhoneAccount; import android.text.TextUtils; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.CallerInfo; import java.util.List; /** /** * Uses a Uri to obtain a {@link Ringtone} from the {@link RingtoneManager} that can be played * Uses the incoming {@link Call}'s ringtone URI (obtained by the Contact Lookup) to obtain a * by the system during an incoming call. * {@link Ringtone} from the {@link RingtoneManager} that can be played by the system during an * incoming call. If the ringtone URI is null, use the default Ringtone for the active user. */ */ @VisibleForTesting @VisibleForTesting public class RingtoneFactory { public class RingtoneFactory { private final Context mContext; private final Context mContext; private final CallsManager mCallsManager; public RingtoneFactory(Context context) { public RingtoneFactory(CallsManager callsManager, Context context) { mContext = context; mContext = context; mCallsManager = callsManager; } } public Ringtone getRingtone(Uri ringtoneUri) { public Ringtone getRingtone(Call incomingCall) { if (ringtoneUri == null) { // Use the default ringtone of the work profile if the contact is a work profile contact. ringtoneUri = Settings.System.DEFAULT_RINGTONE_URI; Context userContext = isWorkContact(incomingCall) ? } getWorkProfileContextForUser(mCallsManager.getCurrentUserHandle()) : getContextForUserHandle(mCallsManager.getCurrentUserHandle()); Uri ringtoneUri = incomingCall.getRingtone(); Ringtone ringtone = null; Ringtone ringtone = RingtoneManager.getRingtone(mContext, ringtoneUri); if(ringtoneUri != null && userContext != null) { // Ringtone URI is explicitly specified. First, try to create a Ringtone with that. ringtone = RingtoneManager.getRingtone(userContext, ringtoneUri); } if(ringtone == null) { // Contact didn't specify ringtone or custom Ringtone creation failed. Get default // ringtone for user or profile. ringtone = RingtoneManager.getRingtone( hasDefaultRingtoneForUser(userContext) ? userContext : mContext, Settings.System.DEFAULT_RINGTONE_URI); } if (ringtone != null) { if (ringtone != null) { ringtone.setStreamType(AudioManager.STREAM_RING); ringtone.setStreamType(AudioManager.STREAM_RING); } } return ringtone; return ringtone; } } private Context getWorkProfileContextForUser(UserHandle userHandle) { // UserManager.getEnabledProfiles returns the enabled profiles along with the user's handle // itself (so we must filter out the user). List<UserInfo> profiles = UserManager.get(mContext).getEnabledProfiles( userHandle.getIdentifier()); UserInfo workprofile = null; int managedProfileCount = 0; for (UserInfo profile : profiles) { UserHandle profileUserHandle = profile.getUserHandle(); if (profileUserHandle != userHandle && profile.isManagedProfile()) { managedProfileCount++; workprofile = profile; } } // There may be many different types of profiles, so only count Managed (Work) Profiles. if(managedProfileCount == 1) { return getContextForUserHandle(workprofile.getUserHandle()); } // There are multiple managed profiles for the associated user and we do not have enough // info to determine which profile is the work profile. Just use the default. return null; } private Context getContextForUserHandle(UserHandle userHandle) { if(userHandle == null) { return null; } try { return mContext.createPackageContextAsUser(mContext.getPackageName(), 0, userHandle); } catch (PackageManager.NameNotFoundException e) { Log.w("RingtoneFactory", "Package name not found: " + e.getMessage()); } return null; } private boolean hasDefaultRingtoneForUser(Context userContext) { if(userContext == null) { return false; } return !TextUtils.isEmpty(Settings.System.getString(userContext.getContentResolver(), Settings.System.RINGTONE)); } private boolean isWorkContact(Call incomingCall) { CallerInfo contactCallerInfo = incomingCall.getCallerInfo(); return (contactCallerInfo != null) && (contactCallerInfo.userType == CallerInfo.USER_TYPE_WORK); } } }