Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c9286f49 authored by Brad Ebinger's avatar Brad Ebinger
Browse files

Update the Ringer to ring based on User/profile

The Telecom Ringer used to ignore the default ringer of secondary
users. We will now use the default ringer of the secondary users as well
as support custom contact ringtones for secondary users.

Bug: 18206079
Bug: 27568161
Change-Id: I31b8b226f852a84b11939ab77f6a8cb0e35e88b6
parent ddad9e0d
Loading
Loading
Loading
Loading
+8 −5
Original line number Diff line number Diff line
@@ -47,11 +47,11 @@ public class AsyncRingtonePlayer {
    private Ringtone mRingtone;

    /** Plays the ringtone. */
    public void play(RingtoneFactory factory, Uri ringtoneUri) {
    public void play(RingtoneFactory factory, Call incomingCall) {
        Log.d(this, "Posting play.");
        SomeArgs args = SomeArgs.obtain();
        args.arg1 = factory;
        args.arg2 = ringtoneUri;
        args.arg2 = incomingCall;
        postMessage(EVENT_PLAY, true /* shouldCreateHandler */, args);
    }

@@ -114,7 +114,7 @@ public class AsyncRingtonePlayer {
     */
    private void handlePlay(SomeArgs args) {
        RingtoneFactory factory = (RingtoneFactory) args.arg1;
        Uri ringtoneUri = (Uri) args.arg2;
        Call incomingCall = (Call) args.arg2;
        args.recycle();
        // don't bother with any of this if there is an EVENT_STOP waiting.
        if (mHandler.hasMessages(EVENT_STOP)) {
@@ -125,10 +125,13 @@ public class AsyncRingtonePlayer {
        Log.i(this, "Play ringtone.");

        if (mRingtone == null) {
            mRingtone = factory.getRingtone(ringtoneUri);
            mRingtone = factory.getRingtone(incomingCall);
            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. " +
                        "Skipping ringing. Uri was: " + ringtoneUri.toSafeString());
                        "Skipping ringing. Uri was: " + ringtoneUriString);
                return;
            }
        }
+1 −1
Original line number Diff line number Diff line
@@ -235,7 +235,7 @@ public class CallsManager extends Call.ListenerBase
                callAudioRoutePeripheralAdapter, lock);

        SystemSettingsUtil systemSettingsUtil = new SystemSettingsUtil();
        RingtoneFactory ringtoneFactory = new RingtoneFactory(context);
        RingtoneFactory ringtoneFactory = new RingtoneFactory(this, context);
        SystemVibrator systemVibrator = new SystemVibrator(context);
        AsyncRingtonePlayer asyncRingtonePlayer = new AsyncRingtonePlayer();
        mInCallController = new InCallController(context, mLock, this, systemStateProvider);
+1 −1
Original line number Diff line number Diff line
@@ -124,7 +124,7 @@ public final class Ringer {
            // 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
            // request the custom ringtone from the call and expect it to be current.
            mRingtonePlayer.play(mRingtoneFactory, foregroundCall.getRingtone());
            mRingtonePlayer.play(mRingtoneFactory, foregroundCall);
        } else {
            Log.v(this, "startRingingOrCallWaiting, skipping because volume is 0");
        }
+82 −8
Original line number Diff line number Diff line
@@ -17,36 +17,110 @@
package com.android.server.telecom;

import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.media.AudioManager;
import android.media.RingtoneManager;
import android.media.Ringtone;
import android.net.Uri;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.telecom.PhoneAccount;
import android.text.TextUtils;

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
 * by the system during an incoming call.
 * Uses the incoming {@link Call}'s ringtone URI (obtained by the Contact Lookup) to obtain a
 * {@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
public class RingtoneFactory {

    private final Context mContext;
    private final CallsManager mCallsManager;

    public RingtoneFactory(Context context) {
    public RingtoneFactory(CallsManager callsManager, Context context) {
        mContext = context;
        mCallsManager = callsManager;
    }

    public Ringtone getRingtone(Uri ringtoneUri) {
        if (ringtoneUri == null) {
            ringtoneUri = Settings.System.DEFAULT_RINGTONE_URI;
        }
    public Ringtone getRingtone(Call incomingCall) {
        // Use the default ringtone of the work profile if the contact is a work profile contact.
        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) {
            ringtone.setStreamType(AudioManager.STREAM_RING);
        }
        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);
    }
}