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

Commit 1aed5c41 authored by Tyler Gunn's avatar Tyler Gunn
Browse files

Support for multiple car-mode InCallServices.

Add support for the new UiModeManager prioritized car mode API in Telecom.
Modified the InCallController so that it can support changes to the current
car mode ICS.
Removed some old companion app code that isn't needed.
Removed car mode override code that isn't needed since we're not using
RoleManager for this.
Added CarModeTracker class to encapsulate tracking which app is in car
mode; this is used by InCallController to manage the current car mode
state.

Test: Created new unit tests and updated existing.
Test: Added new CTS tests.
Test: Manual verification with test apps.
Bug: 144345414
Change-Id: I4cb5c1616cc54dfda97ea1f59271bff57eb1c2ff
parent 44a7e4f1
Loading
Loading
Loading
Loading
+209 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.telecom;

import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.UiModeManager;
import android.telecom.Log;
import android.util.LocalLog;

import com.android.internal.util.IndentingPrintWriter;

import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.PriorityQueue;
import java.util.stream.Collectors;

/**
 * Tracks the package names of apps which enter end exit car mode.
 */
public class CarModeTracker {
    /**
     * Data class holding information about apps which have requested to enter car mode.
     */
    private class CarModeApp {
        private @IntRange(from = 0) int mPriority;
        private @NonNull String mPackageName;

        public CarModeApp(int priority, @NonNull String packageName) {
            mPriority = priority;
            mPackageName = Objects.requireNonNull(packageName);
        }

        /**
         * The priority at which the app requested to enter car mode.
         * Will be the same as the one specified when {@link UiModeManager#enableCarMode(int, int)}
         * was called, or {@link UiModeManager#DEFAULT_PRIORITY} if no priority was specifeid.
         * @return The priority.
         */
        public int getPriority() {
            return mPriority;
        }

        public void setPriority(int priority) {
            mPriority = priority;
        }

        /**
         * @return The package name of the app which requested to enter car mode.
         */
        public String getPackageName() {
            return mPackageName;
        }

        public void setPackageName(String packageName) {
            mPackageName = packageName;
        }
    }

    /**
     * Comparator used to maintain the car mode priority queue ordering.
     */
    private class CarModeAppComparator implements Comparator<CarModeApp> {
        @Override
        public int compare(CarModeApp o1, CarModeApp o2) {
            // highest priority takes precedence.
            return Integer.compare(o2.getPriority(), o1.getPriority());
        }
    }

    /**
     * Priority list of apps which have entered or exited car mode, ordered with the highest
     * priority app at the top of the queue.  Where items have the same priority, they are ordered
     * by insertion time.
     */
    private PriorityQueue<CarModeApp> mCarModeApps = new PriorityQueue<>(2,
            new CarModeAppComparator());

    private final LocalLog mCarModeChangeLog = new LocalLog(20);

    /**
     * Handles a request to enter car mode by a package name.
     * @param priority The priority at which car mode is entered.
     * @param packageName The package name of the app entering car mode.
     */
    public void handleEnterCarMode(@IntRange(from = 0) int priority, @NonNull String packageName) {
        if (mCarModeApps.stream().anyMatch(c -> c.getPriority() == priority)) {
            Log.w(this, "handleEnterCarMode: already in car mode at priority %d (apps: %s)",
                    priority, getCarModePriorityString());
            return;
        }

        if (mCarModeApps.stream().anyMatch(c -> c.getPackageName().equals(packageName))) {
            Log.w(this, "handleEnterCarMode: %s is already in car mode (apps: %s)",
                    packageName, getCarModePriorityString());
            return;
        }

        Log.i(this, "handleEnterCarMode: packageName=%s, priority=%d", packageName, priority);
        mCarModeChangeLog.log("enterCarMode: packageName=" + packageName + ", priority="
                + priority);
        mCarModeApps.add(new CarModeApp(priority, packageName));
    }

    /**
     * Handles a request to exist car mode at a priority level.
     * @param priority The priority level.
     * @param packageName The packagename of the app requesting the change.
     */
    public void handleExitCarMode(@IntRange(from = 0) int priority, @NonNull String packageName) {
        if (!mCarModeApps.stream().anyMatch(c -> c.getPriority() == priority)) {
            Log.w(this, "handleExitCarMode: not in car mode at priority %d (apps=%s)",
                    priority, getCarModePriorityString());
            return;
        }

        if (priority != UiModeManager.DEFAULT_PRIORITY && !mCarModeApps.stream().anyMatch(
                c -> c.getPackageName().equals(packageName) && c.getPriority() == priority)) {
            Log.w(this, "handleExitCarMode: %s didn't enter car mode at priority %d (apps=%s)",
                    packageName, priority, getCarModePriorityString());
            return;
        }

        Log.i(this, "handleExitCarMode: packageName=%s, priority=%d", packageName, priority);
        mCarModeChangeLog.log("exitCarMode: packageName=" + packageName + ", priority="
                + priority);
        mCarModeApps.removeIf(c -> c.getPriority() == priority);
    }

    /**
     * Retrieves a list of the apps which are currently in car mode, ordered by priority such that
     * the highest priority app is first.
     * @return List of apps in car mode.
     */
    public @NonNull List<String> getCarModeApps() {
        return mCarModeApps
                .stream()
                .sorted(mCarModeApps.comparator())
                .map(cma -> cma.getPackageName())
                .collect(Collectors.toList());
    }

    private @NonNull String getCarModePriorityString() {
        return mCarModeApps
                .stream()
                .sorted(mCarModeApps.comparator())
                .map(cma -> "[" + cma.getPriority() + ", " + cma.getPackageName() + "]")
                .collect(Collectors.joining(", "));
    }

    /**
     * Gets the app which is currently in car mode.  This is the highest priority app which has
     * entered car mode.
     * @return The app which is in car mode.
     */
    public @Nullable String getCurrentCarModePackage() {
        CarModeApp app = mCarModeApps.peek();
        return app == null ? null : app.getPackageName();
    }

    /**
     * @return {@code true} if the device is in car mode, {@code false} otherwise.
     */
    public boolean isInCarMode() {
        return !mCarModeApps.isEmpty();
    }

    /**
     * Dumps the state of the car mode tracker to the specified print writer.
     * @param pw
     */
    public void dump(IndentingPrintWriter pw) {
        pw.println("CarModeTracker:");
        pw.increaseIndent();

        pw.println("Current car mode apps:");
        pw.increaseIndent();
        for (CarModeApp app : mCarModeApps) {
            pw.print("[");
            pw.print(app.getPriority());
            pw.print("] ");
            pw.println(app.getPackageName());
        }
        pw.decreaseIndent();

        pw.println("Car mode history:");
        pw.increaseIndent();
        mCarModeChangeLog.dump(pw);
        pw.decreaseIndent();

        pw.decreaseIndent();
    }
}
+147 −49
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.telecom;

import android.Manifest;
import android.annotation.NonNull;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -48,6 +49,7 @@ import com.android.internal.util.IndentingPrintWriter;
import com.android.server.telecom.SystemStateHelper.SystemStateListener;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
@@ -55,6 +57,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * Binds to {@link IInCallService} and provides the service to {@link CallsManager} through which it
@@ -256,9 +259,13 @@ public class InCallController extends CallsManagerListenerBase {
        @Override
        public void disconnect() {
            if (mIsConnected) {
                Log.i(InCallController.this, "ICSBC#disconnect: unbinding; %s",
                        mInCallServiceInfo);
                mContext.unbindService(mServiceConnection);
                mIsConnected = false;
            } else {
                Log.i(InCallController.this, "ICSBC#disconnect: already disconnected; %s",
                        mInCallServiceInfo);
                Log.addEvent(null, LogUtils.Events.INFO, "Already disconnected, ignoring request.");
            }
        }
@@ -270,9 +277,13 @@ public class InCallController extends CallsManagerListenerBase {

        @Override
        public void dump(IndentingPrintWriter pw) {
            pw.append("BindingConnection [");
            pw.append(mIsConnected ? "" : "not ").append("connected, ");
            pw.append(mIsBound ? "" : "not ").append("bound]\n");
            pw.print("BindingConnection [");
            pw.print(mIsConnected ? "" : "not ");
            pw.print("connected, ");
            pw.print(mIsBound ? "" : "not ");
            pw.print("bound, ");
            pw.print(mInCallServiceInfo);
            pw.println("\n");
        }

        protected void onConnected(IBinder service) {
@@ -436,7 +447,7 @@ public class InCallController extends CallsManagerListenerBase {
     */
    private class CarSwappingInCallServiceConnection extends InCallServiceConnection {
        private final InCallServiceConnection mDialerConnection;
        private final InCallServiceConnection mCarModeConnection;
        private InCallServiceConnection mCarModeConnection;
        private InCallServiceConnection mCurrentConnection;
        private boolean mIsCarMode = false;
        private boolean mIsConnected = false;
@@ -449,8 +460,13 @@ public class InCallController extends CallsManagerListenerBase {
            mCurrentConnection = getCurrentConnection();
        }

        public synchronized void setCarMode(boolean isCarMode) {
            Log.i(this, "carmodechange: " + mIsCarMode + " => " + isCarMode);
        /**
         * Called when we move to a state where calls are present on the device.  Chooses the
         * {@link InCallService} to which we should connect.
         * @param isCarMode {@code true} if device is in car mode, {@code false} otherwise.
         */
        public synchronized void chooseInitialInCallService(boolean isCarMode) {
            Log.i(this, "chooseInitialInCallService: " + mIsCarMode + " => " + isCarMode);
            if (isCarMode != mIsCarMode) {
                mIsCarMode = isCarMode;
                InCallServiceConnection newConnection = getCurrentConnection();
@@ -465,6 +481,63 @@ public class InCallController extends CallsManagerListenerBase {
            }
        }

        /**
         * Invoked when {@link CarModeTracker} has determined that the device is no longer in car
         * mode (i.e. has no car mode {@link InCallService}).
         *
         * Switches back to the default dialer app.
         */
        public synchronized void disableCarMode() {
            mIsCarMode = false;
            if (mIsConnected) {
                mCurrentConnection.disconnect();
            }

            mCurrentConnection = mDialerConnection;
            int result = mDialerConnection.connect(null);
            mIsConnected = result == CONNECTION_SUCCEEDED;
        }

        /**
         * Changes the active {@link InCallService} to a car mode app.  Called whenever the device
         * changes to car mode or the currently active car mode app changes.
         * @param packageName The package name of the car mode app.
         */
        public synchronized void changeCarModeApp(String packageName) {
            Log.i(this, "changeCarModeApp: isCarModeNow=" + mIsCarMode);

            InCallServiceInfo currentConnectionInfo = mCurrentConnection == null ? null
                    : mCurrentConnection.getInfo();
            InCallServiceInfo carModeConnectionInfo =
                    getInCallServiceComponent(packageName, IN_CALL_SERVICE_TYPE_CAR_MODE_UI);

            if (!Objects.equals(currentConnectionInfo, carModeConnectionInfo)) {
                Log.i(this, "changeCarModeApp: " + currentConnectionInfo + " => "
                        + carModeConnectionInfo);
                if (mIsConnected) {
                    mCurrentConnection.disconnect();
                }

                if (carModeConnectionInfo != null) {
                    // Valid car mode app.
                    mCarModeConnection = mCurrentConnection =
                            new InCallServiceBindingConnection(carModeConnectionInfo);
                    mIsCarMode = true;
                } else {
                    // Invalid car mode app; don't expect this but should handle it gracefully.
                    mCarModeConnection = null;
                    mIsCarMode = false;
                    mCurrentConnection = mDialerConnection;
                }

                int result = mCurrentConnection.connect(null);
                mIsConnected = result == CONNECTION_SUCCEEDED;
            } else {
                Log.i(this, "changeCarModeApp: unchanged; " + currentConnectionInfo + " => "
                        + carModeConnectionInfo);
            }
        }

        @Override
        public int connect(Call call) {
            if (mIsConnected) {
@@ -484,6 +557,7 @@ public class InCallController extends CallsManagerListenerBase {
        @Override
        public void disconnect() {
            if (mIsConnected) {
                Log.i(InCallController.this, "CSICSC: disconnect %s", mCurrentConnection);
                mCurrentConnection.disconnect();
                mIsConnected = false;
            } else {
@@ -699,18 +773,9 @@ public class InCallController extends CallsManagerListenerBase {
        }
    };

    private final SystemStateListener mSystemStateListener = new SystemStateListener() {
        @Override
        public void onCarModeChanged(boolean isCarMode) {
            if (mInCallServiceConnection != null) {
                mInCallServiceConnection.setCarMode(shouldUseCarModeUI());
            }
        }

        @Override
        public void onCarModeChanged(int priority, String packageName, boolean isCarMode) {
        }
    };
    private final SystemStateListener mSystemStateListener =
            (priority, packageName, isCarMode) -> InCallController.this.handleCarModeChange(
                    priority, packageName, isCarMode);

    private static final int IN_CALL_SERVICE_TYPE_INVALID = 0;
    private static final int IN_CALL_SERVICE_TYPE_DIALER_UI = 1;
@@ -739,10 +804,12 @@ public class InCallController extends CallsManagerListenerBase {
    // The future will complete with true if binding succeeds, false if it timed out.
    private CompletableFuture<Boolean> mBindingFuture = CompletableFuture.completedFuture(true);

    private final CarModeTracker mCarModeTracker;

    public InCallController(Context context, TelecomSystem.SyncRoot lock, CallsManager callsManager,
            SystemStateHelper systemStateHelper,
            DefaultDialerCache defaultDialerCache, Timeouts.Adapter timeoutsAdapter,
            EmergencyCallHelper emergencyCallHelper) {
            EmergencyCallHelper emergencyCallHelper, CarModeTracker carModeTracker) {
        mContext = context;
        mLock = lock;
        mCallsManager = callsManager;
@@ -750,7 +817,7 @@ public class InCallController extends CallsManagerListenerBase {
        mTimeoutsAdapter = timeoutsAdapter;
        mDefaultDialerCache = defaultDialerCache;
        mEmergencyCallHelper = emergencyCallHelper;

        mCarModeTracker = carModeTracker;
        mSystemStateHelper.addListener(mSystemStateListener);
    }

@@ -1113,7 +1180,7 @@ public class InCallController extends CallsManagerListenerBase {
            systemInCall.setHasEmergency(mCallsManager.isInEmergencyCall());

            InCallServiceConnection carModeInCall = null;
            InCallServiceInfo carModeComponentInfo = getCarModeComponent();
            InCallServiceInfo carModeComponentInfo = getCurrentCarModeComponent();
            if (carModeComponentInfo != null &&
                    !carModeComponentInfo.getComponentName().equals(
                            mDefaultDialerCache.getSystemDialerComponent())) {
@@ -1124,7 +1191,7 @@ public class InCallController extends CallsManagerListenerBase {
                    new CarSwappingInCallServiceConnection(systemInCall, carModeInCall);
        }

        mInCallServiceConnection.setCarMode(shouldUseCarModeUI());
        mInCallServiceConnection.chooseInitialInCallService(shouldUseCarModeUI());

        // Actually try binding to the UI InCallService.  If the response
        if (mInCallServiceConnection.connect(call) ==
@@ -1171,11 +1238,9 @@ public class InCallController extends CallsManagerListenerBase {
        return getInCallServiceComponent(packageName, IN_CALL_SERVICE_TYPE_DIALER_UI);
    }

    private InCallServiceInfo getCarModeComponent() {
        // The signatures of getInCallServiceComponent differ in the types of the first parameter,
        // and passing in null is inherently ambiguous. (If no car mode component found)
        String defaultCarMode = mCallsManager.getRoleManagerAdapter().getCarModeDialerApp();
        return getInCallServiceComponent(defaultCarMode, IN_CALL_SERVICE_TYPE_CAR_MODE_UI);
    private InCallServiceInfo getCurrentCarModeComponent() {
        return getInCallServiceComponent(mCarModeTracker.getCurrentCarModePackage(),
                IN_CALL_SERVICE_TYPE_CAR_MODE_UI);
    }

    private InCallServiceInfo getInCallServiceComponent(ComponentName componentName, int type) {
@@ -1257,7 +1322,7 @@ public class InCallController extends CallsManagerListenerBase {
    }

    private boolean shouldUseCarModeUI() {
        return mSystemStateHelper.isCarMode();
        return mCarModeTracker.isInCarMode();
    }

    /**
@@ -1285,27 +1350,25 @@ public class InCallController extends CallsManagerListenerBase {
        // Check to see if the service holds permissions or metadata for third party apps.
        boolean isUIService = serviceInfo.metaData != null &&
                serviceInfo.metaData.getBoolean(TelecomManager.METADATA_IN_CALL_SERVICE_UI);
        boolean isThirdPartyCompanionApp = packageManager.checkPermission(
                Manifest.permission.CALL_COMPANION_APP,
                serviceInfo.packageName) == PackageManager.PERMISSION_GRANTED &&
                !isUIService;

        // Check to see if the service is a car-mode UI type by checking that it has the
        // CONTROL_INCALL_EXPERIENCE (to verify it is a system app) and that it has the
        // car-mode UI metadata.
        boolean hasControlInCallPermission = packageManager.checkPermission(
        // We check the permission grant on all of the packages contained in the InCallService's
        // same UID to see if any of them have been granted the permission.  This accomodates the
        // CTS tests, which have some shared UID stuff going on in order to work.  It also still
        // obeys the permission model since a single APK typically normally only has a single UID.
        String[] uidPackages = packageManager.getPackagesForUid(serviceInfo.applicationInfo.uid);
        boolean hasControlInCallPermission = Arrays.stream(uidPackages).anyMatch(
                p -> packageManager.checkPermission(
                        Manifest.permission.CONTROL_INCALL_EXPERIENCE,
                serviceInfo.packageName) == PackageManager.PERMISSION_GRANTED;
                        p) == PackageManager.PERMISSION_GRANTED);
        boolean isCarModeUIService = serviceInfo.metaData != null &&
                serviceInfo.metaData.getBoolean(
                        TelecomManager.METADATA_IN_CALL_SERVICE_CAR_MODE_UI, false);
        if (isCarModeUIService) {
            // ThirdPartyInCallService shouldn't be used when role manager hasn't assigned any car
            // mode role holders, i.e. packageName is null.
            if (hasControlInCallPermission || (isThirdPartyCompanionApp && packageName != null)) {
        if (isCarModeUIService && hasControlInCallPermission) {
            return IN_CALL_SERVICE_TYPE_CAR_MODE_UI;
        }
        }

        // Check to see that it is the default dialer package
        boolean isDefaultDialerPackage = Objects.equals(serviceInfo.packageName,
@@ -1317,15 +1380,9 @@ public class InCallController extends CallsManagerListenerBase {

        // Also allow any in-call service that has the control-experience permission (to ensure
        // that it is a system app) and doesn't claim to show any UI.
        if (!isUIService && !isCarModeUIService) {
            if (hasControlInCallPermission && !isThirdPartyCompanionApp) {
        if (!isUIService && !isCarModeUIService && hasControlInCallPermission) {
            return IN_CALL_SERVICE_TYPE_NON_UI;
        }
            // Third party companion alls without CONTROL_INCALL_EXPERIENCE permission.
            if (!hasControlInCallPermission && isThirdPartyCompanionApp) {
                return IN_CALL_SERVICE_TYPE_COMPANION;
            }
        }

        // Anything else that remains, we will not bind to.
        Log.i(this, "Skipping binding to %s:%s, control: %b, car-mode: %b, ui: %b",
@@ -1518,6 +1575,8 @@ public class InCallController extends CallsManagerListenerBase {
            mInCallServiceConnection.dump(pw);
        }
        pw.decreaseIndent();

        mCarModeTracker.dump(pw);
    }

    /**
@@ -1599,4 +1658,43 @@ public class InCallController extends CallsManagerListenerBase {
    public Handler getHandler() {
        return mHandler;
    }

    /**
     * Determines if the specified package is a valid car mode {@link InCallService}.
     * @param packageName The package name to check.
     * @return {@code true} if the package has a valid car mode {@link InCallService} defined,
     * {@code false} otherwise.
     */
    private boolean isCarModeInCallService(@NonNull String packageName) {
        InCallServiceInfo info =
                getInCallServiceComponent(packageName, IN_CALL_SERVICE_TYPE_CAR_MODE_UI);
        return info != null && info.getType() == IN_CALL_SERVICE_TYPE_CAR_MODE_UI;
    }

    public void handleCarModeChange(int priority, String packageName, boolean isCarMode) {
        Log.i(this, "handleCarModeChange: packageName=%s, priority=%d, isCarMode=%b",
                packageName, priority, isCarMode);
        if (!isCarModeInCallService(packageName)) {
            Log.i(this, "handleCarModeChange: not a valid InCallService; packageName=%s",
                    packageName);
            return;
        }

        if (isCarMode) {
            mCarModeTracker.handleEnterCarMode(priority, packageName);
        } else {
            mCarModeTracker.handleExitCarMode(priority, packageName);
        }

        if (mInCallServiceConnection != null) {
            Log.i(this, "handleCarModeChange: car mode apps: %s",
                    mCarModeTracker.getCarModeApps().stream().collect(Collectors.joining(", ")));
            if (shouldUseCarModeUI()) {
                mInCallServiceConnection.changeCarModeApp(
                        mCarModeTracker.getCurrentCarModePackage());
            } else {
                mInCallServiceConnection.disableCarMode();
            }
        }
    }
}
+0 −12
Original line number Diff line number Diff line
@@ -101,18 +101,6 @@ public interface RoleManagerAdapter {
     */
    void addOrRemoveTestCallCompanionApp(String packageName, boolean isAdded);

    /**
     * @return Package name of the car more app or {@code null} if there are no apps that match.
     */
    String getCarModeDialerApp();

    /**
     * Override the automotive app with another value. Used for testing purposes only.
     * @param packageName Package name of the automotive app. Where
     *                    {@code null}, the override is removed.
     */
    void setTestAutoModeApp(String packageName);

    /**
     * Using role manager needs to know the current user handle.  Need to make sure the role manager
     * adapter can pass this to role manager.  As it changes, we'll pass it in.
+0 −28
Original line number Diff line number Diff line
@@ -38,7 +38,6 @@ public class RoleManagerAdapterImpl implements RoleManagerAdapter {

    private String mOverrideDefaultCallRedirectionApp = null;
    private String mOverrideDefaultCallScreeningApp = null;
    private String mOverrideDefaultCarModeApp = null;
    private String mOverrideDefaultDialerApp = null;
    private List<String> mOverrideCallCompanionApps = new ArrayList<>();
    private Context mContext;
@@ -111,19 +110,6 @@ public class RoleManagerAdapterImpl implements RoleManagerAdapter {
        }
    }

    @Override
    public String getCarModeDialerApp() {
        if (mOverrideDefaultCarModeApp != null) {
            return mOverrideDefaultCarModeApp;
        }
        return getRoleManagerCarModeDialerApp();
    }

    @Override
    public void setTestAutoModeApp(String packageName) {
        mOverrideDefaultCarModeApp = packageName;
    }

    @Override
    public void setCurrentUserHandle(UserHandle currentUserHandle) {
        mCurrentUserHandle = currentUserHandle;
@@ -147,11 +133,6 @@ public class RoleManagerAdapterImpl implements RoleManagerAdapter {
        return roleHolders.get(0);
    }

    // TODO in R: query and return car mode apps
    private String getRoleManagerCarModeDialerApp() {
        return null;
    }

    // TODO in R: Use companion app manager
    private List<String> getRoleManagerCallCompanionApps() {
        return new ArrayList<>();
@@ -213,15 +194,6 @@ public class RoleManagerAdapterImpl implements RoleManagerAdapter {
        }
        pw.println();

        pw.print("DefaultCarModeDialerApp: ");
        if (mOverrideDefaultCarModeApp != null) {
            pw.print("(override ");
            pw.print(mOverrideDefaultCarModeApp);
            pw.print(") ");
            pw.print(getRoleManagerCarModeDialerApp());
        }
        pw.println();

        pw.print("DefaultCallCompanionApps: ");
        if (mOverrideCallCompanionApps != null) {
            pw.print("(override ");
+5 −34

File changed.

Preview size limit exceeded, changes collapsed.

Loading