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

Commit 9b314bc9 authored by Hui Wang's avatar Hui Wang Committed by Android (Google) Code Review
Browse files

Merge "Improve the performance to avoid the potential ANR" into main

parents 6d5a6a84 5c9f677b
Loading
Loading
Loading
Loading
+74 −88
Original line number Original line Diff line number Diff line
@@ -31,44 +31,29 @@ import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings;
import android.telecom.DefaultDialerManager;
import android.telecom.DefaultDialerManager;
import android.telecom.Log;
import android.telecom.Log;
import android.util.SparseArray;


import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.IndentingPrintWriter;


import java.util.Objects;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.Executor;
import java.util.function.IntConsumer;
import java.util.function.IntConsumer;


public class DefaultDialerCache {
public class DefaultDialerCache {
    public interface DefaultDialerManagerAdapter {
        String getDefaultDialerApplication(Context context);
        String getDefaultDialerApplication(Context context, int userId);
        boolean setDefaultDialerApplication(Context context, String packageName, int userId);
    }

    static class DefaultDialerManagerAdapterImpl implements DefaultDialerManagerAdapter {
        @Override
        public String getDefaultDialerApplication(Context context) {
            return DefaultDialerManager.getDefaultDialerApplication(context);
        }

        @Override
        public String getDefaultDialerApplication(Context context, int userId) {
            return DefaultDialerManager.getDefaultDialerApplication(context, userId);
        }

        @Override
        public boolean setDefaultDialerApplication(Context context, String packageName,
                int userId) {
            return DefaultDialerManager.setDefaultDialerApplication(context, packageName, userId);
        }
    }

    private static final String LOG_TAG = "DefaultDialerCache";
    private static final String LOG_TAG = "DefaultDialerCache";
    @VisibleForTesting
    public final Handler mHandler = new Handler(Looper.getMainLooper());
    private final Context mContext;
    private final DefaultDialerManagerAdapter mDefaultDialerManagerAdapter;
    private final ComponentName mSystemDialerComponentName;
    private final RoleManagerAdapter mRoleManagerAdapter;
    private final ConcurrentHashMap<Integer, String> mCurrentDefaultDialerPerUser =
            new ConcurrentHashMap<>();
    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        @Override
        public void onReceive(Context context, Intent intent) {
        public void onReceive(Context context, Intent intent) {
            mHandler.post(() -> {
                Log.startSession("DDC.oR");
                Log.startSession("DDC.oR");
                try {
                try {
                    String packageName;
                    String packageName;
@@ -85,16 +70,13 @@ public class DefaultDialerCache {
                        return;
                        return;
                    }
                    }


                synchronized (mLock) {
                    refreshCachesForUsersWithPackage(packageName);
                    refreshCachesForUsersWithPackage(packageName);
                }

                } finally {
                } finally {
                    Log.endSession();
                    Log.endSession();
                }
                }
            });
        }
        }
    };
    };

    private final BroadcastReceiver mUserRemovedReceiver = new BroadcastReceiver() {
    private final BroadcastReceiver mUserRemovedReceiver = new BroadcastReceiver() {
        @Override
        @Override
        public void onReceive(Context context, Intent intent) {
        public void onReceive(Context context, Intent intent) {
@@ -110,8 +92,6 @@ public class DefaultDialerCache {
            }
            }
        }
        }
    };
    };

    private final Handler mHandler = new Handler(Looper.getMainLooper());
    private final ContentObserver mDefaultDialerObserver = new ContentObserver(mHandler) {
    private final ContentObserver mDefaultDialerObserver = new ContentObserver(mHandler) {
        @Override
        @Override
        public void onChange(boolean selfChange) {
        public void onChange(boolean selfChange) {
@@ -119,9 +99,7 @@ public class DefaultDialerCache {
            try {
            try {
                // We don't get the user ID of the user that changed here, so we'll have to
                // We don't get the user ID of the user that changed here, so we'll have to
                // refresh all of the users.
                // refresh all of the users.
                synchronized (mLock) {
                refreshCachesForUsersWithPackage(null);
                refreshCachesForUsersWithPackage(null);
                }
            } finally {
            } finally {
                Log.endSession();
                Log.endSession();
            }
            }
@@ -132,13 +110,6 @@ public class DefaultDialerCache {
            return true;
            return true;
        }
        }
    };
    };

    private final Context mContext;
    private final DefaultDialerManagerAdapter mDefaultDialerManagerAdapter;
    private final TelecomSystem.SyncRoot mLock;
    private final ComponentName mSystemDialerComponentName;
    private final RoleManagerAdapter mRoleManagerAdapter;
    private SparseArray<String> mCurrentDefaultDialerPerUser = new SparseArray<>();
    private ComponentName mOverrideSystemDialerComponentName;
    private ComponentName mOverrideSystemDialerComponentName;


    public DefaultDialerCache(Context context,
    public DefaultDialerCache(Context context,
@@ -148,13 +119,12 @@ public class DefaultDialerCache {
        mContext = context;
        mContext = context;
        mDefaultDialerManagerAdapter = defaultDialerManagerAdapter;
        mDefaultDialerManagerAdapter = defaultDialerManagerAdapter;
        mRoleManagerAdapter = roleManagerAdapter;
        mRoleManagerAdapter = roleManagerAdapter;
        mLock = lock;

        Resources resources = mContext.getResources();
        Resources resources = mContext.getResources();
        mSystemDialerComponentName = new ComponentName(resources.getString(
        mSystemDialerComponentName = new ComponentName(resources.getString(
                com.android.internal.R.string.config_defaultDialer),
                com.android.internal.R.string.config_defaultDialer),
                resources.getString(R.string.incall_default_class));
                resources.getString(R.string.incall_default_class));



        IntentFilter packageIntentFilter = new IntentFilter();
        IntentFilter packageIntentFilter = new IntentFilter();
        packageIntentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
        packageIntentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
        packageIntentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
        packageIntentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
@@ -195,7 +165,7 @@ public class DefaultDialerCache {
        //
        //
        //synchronized (mLock) {
        //synchronized (mLock) {
        //    String defaultDialer = mCurrentDefaultDialerPerUser.get(userId);
        //    String defaultDialer = mCurrentDefaultDialerPerUser.get(userId);
        //    if (defaultDialer != null) {
        //    if (!TextUtils.isEmpty(defaultDialer)) {
        //        return defaultDialer;
        //        return defaultDialer;
        //    }
        //    }
        //}
        //}
@@ -242,10 +212,8 @@ public class DefaultDialerCache {
        boolean isChanged = mDefaultDialerManagerAdapter.setDefaultDialerApplication(
        boolean isChanged = mDefaultDialerManagerAdapter.setDefaultDialerApplication(
                mContext, packageName, userId);
                mContext, packageName, userId);
        if (isChanged) {
        if (isChanged) {
            synchronized (mLock) {
            // Update the cache synchronously so that there is no delay in cache update.
            // Update the cache synchronously so that there is no delay in cache update.
                mCurrentDefaultDialerPerUser.put(userId, packageName);
            mCurrentDefaultDialerPerUser.put(userId, packageName == null ? "" : packageName);
            }
        }
        }
        return isChanged;
        return isChanged;
    }
    }
@@ -253,47 +221,39 @@ public class DefaultDialerCache {
    private String refreshCacheForUser(int userId) {
    private String refreshCacheForUser(int userId) {
        String currentDefaultDialer =
        String currentDefaultDialer =
                mRoleManagerAdapter.getDefaultDialerApp(userId);
                mRoleManagerAdapter.getDefaultDialerApp(userId);
        synchronized (mLock) {
        mCurrentDefaultDialerPerUser.put(userId, currentDefaultDialer == null ? "" :
            mCurrentDefaultDialerPerUser.put(userId, currentDefaultDialer);
                currentDefaultDialer);
        }
        return currentDefaultDialer;
        return currentDefaultDialer;
    }
    }


    /**
    /**
     * Refreshes the cache for users that currently have packageName as their cached default dialer.
     * Refreshes the cache for users that currently have packageName as their cached default dialer.
     * If packageName is null, refresh all caches.
     * If packageName is null, refresh all caches.
     *
     * @param packageName Name of the affected package.
     * @param packageName Name of the affected package.
     */
     */
    private void refreshCachesForUsersWithPackage(String packageName) {
    private void refreshCachesForUsersWithPackage(String packageName) {
        for (int i = 0; i < mCurrentDefaultDialerPerUser.size(); i++) {
        mCurrentDefaultDialerPerUser.forEach((userId, currentName) -> {
            int userId = mCurrentDefaultDialerPerUser.keyAt(i);
            if (packageName == null || Objects.equals(packageName, currentName)) {
            if (packageName == null ||
                    Objects.equals(packageName, mCurrentDefaultDialerPerUser.get(userId))) {
                String newDefaultDialer = refreshCacheForUser(userId);
                String newDefaultDialer = refreshCacheForUser(userId);
                Log.v(LOG_TAG, "Refreshing default dialer for user %d: now %s",
                Log.v(LOG_TAG, "Refreshing default dialer for user %d: now %s",
                        userId, newDefaultDialer);
                        userId, newDefaultDialer);
            }
            }
        }
        });
    }
    }


    public void dumpCache(IndentingPrintWriter pw) {
    public void dumpCache(IndentingPrintWriter pw) {
        synchronized (mLock) {
        mCurrentDefaultDialerPerUser.forEach((k, v) -> pw.printf("User %d: %s\n", k, v));
            for (int i = 0; i < mCurrentDefaultDialerPerUser.size(); i++) {
                pw.printf("User %d: %s\n", mCurrentDefaultDialerPerUser.keyAt(i),
                        mCurrentDefaultDialerPerUser.valueAt(i));
            }
        }
    }
    }


    private void removeUserFromCache(int userId) {
    private void removeUserFromCache(int userId) {
        synchronized (mLock) {
        mCurrentDefaultDialerPerUser.remove(userId);
        mCurrentDefaultDialerPerUser.remove(userId);
    }
    }
    }


    /**
    /**
     * registerContentObserver is really hard to mock out, so here is a getter method for the
     * registerContentObserver is really hard to mock out, so here is a getter method for the
     * content observer for testing instead.
     * content observer for testing instead.
     *
     * @return The content observer
     * @return The content observer
     */
     */
    @VisibleForTesting
    @VisibleForTesting
@@ -304,4 +264,30 @@ public class DefaultDialerCache {
    public RoleManagerAdapter getRoleManagerAdapter() {
    public RoleManagerAdapter getRoleManagerAdapter() {
        return mRoleManagerAdapter;
        return mRoleManagerAdapter;
    }
    }

    public interface DefaultDialerManagerAdapter {
        String getDefaultDialerApplication(Context context);

        String getDefaultDialerApplication(Context context, int userId);

        boolean setDefaultDialerApplication(Context context, String packageName, int userId);
    }

    static class DefaultDialerManagerAdapterImpl implements DefaultDialerManagerAdapter {
        @Override
        public String getDefaultDialerApplication(Context context) {
            return DefaultDialerManager.getDefaultDialerApplication(context);
        }

        @Override
        public String getDefaultDialerApplication(Context context, int userId) {
            return DefaultDialerManager.getDefaultDialerApplication(context, userId);
        }

        @Override
        public boolean setDefaultDialerApplication(Context context, String packageName,
                int userId) {
            return DefaultDialerManager.setDefaultDialerApplication(context, packageName, userId);
        }
    }
}
}
+23 −6
Original line number Original line Diff line number Diff line
@@ -56,14 +56,17 @@ public class DefaultDialerCacheTest extends TelecomTestCase {
    private static final int USER0 = 0;
    private static final int USER0 = 0;
    private static final int USER1 = 1;
    private static final int USER1 = 1;
    private static final int USER2 = 2;
    private static final int USER2 = 2;
    private static final int DELAY_TOLERANCE = 100;


    private DefaultDialerCache mDefaultDialerCache;
    private DefaultDialerCache mDefaultDialerCache;
    private ContentObserver mDefaultDialerSettingObserver;
    private ContentObserver mDefaultDialerSettingObserver;
    private BroadcastReceiver mPackageChangeReceiver;
    private BroadcastReceiver mPackageChangeReceiver;
    private BroadcastReceiver mUserRemovedReceiver;
    private BroadcastReceiver mUserRemovedReceiver;


    @Mock private DefaultDialerCache.DefaultDialerManagerAdapter mMockDefaultDialerManager;
    @Mock
    @Mock private RoleManagerAdapter mRoleManagerAdapter;
    private DefaultDialerCache.DefaultDialerManagerAdapter mMockDefaultDialerManager;
    @Mock
    private RoleManagerAdapter mRoleManagerAdapter;


    @Override
    @Override
    @Before
    @Before
@@ -76,7 +79,8 @@ public class DefaultDialerCacheTest extends TelecomTestCase {


        mDefaultDialerCache = new DefaultDialerCache(
        mDefaultDialerCache = new DefaultDialerCache(
                mContext, mMockDefaultDialerManager, mRoleManagerAdapter,
                mContext, mMockDefaultDialerManager, mRoleManagerAdapter,
                new TelecomSystem.SyncRoot() { });
                new TelecomSystem.SyncRoot() {
                });


        verify(mContext, times(2)).registerReceiverAsUser(
        verify(mContext, times(2)).registerReceiverAsUser(
                packageReceiverCaptor.capture(), eq(UserHandle.ALL), any(IntentFilter.class),
                packageReceiverCaptor.capture(), eq(UserHandle.ALL), any(IntentFilter.class),
@@ -140,7 +144,10 @@ public class DefaultDialerCacheTest extends TelecomTestCase {
        Intent packageChangeIntent = new Intent(Intent.ACTION_PACKAGE_CHANGED,
        Intent packageChangeIntent = new Intent(Intent.ACTION_PACKAGE_CHANGED,
                Uri.fromParts("package", DIALER1, null));
                Uri.fromParts("package", DIALER1, null));
        when(mRoleManagerAdapter.getDefaultDialerApp(eq(USER0))).thenReturn(DIALER2);
        when(mRoleManagerAdapter.getDefaultDialerApp(eq(USER0))).thenReturn(DIALER2);

        mPackageChangeReceiver.onReceive(mContext, packageChangeIntent);
        mPackageChangeReceiver.onReceive(mContext, packageChangeIntent);
        waitForHandlerAction(mDefaultDialerCache.mHandler, DELAY_TOLERANCE);

        verify(mRoleManagerAdapter, times(2)).getDefaultDialerApp(eq(USER0));
        verify(mRoleManagerAdapter, times(2)).getDefaultDialerApp(eq(USER0));
        verify(mRoleManagerAdapter, times(2)).getDefaultDialerApp(eq(USER1));
        verify(mRoleManagerAdapter, times(2)).getDefaultDialerApp(eq(USER1));
        verify(mRoleManagerAdapter, times(2)).getDefaultDialerApp(eq(USER2));
        verify(mRoleManagerAdapter, times(2)).getDefaultDialerApp(eq(USER2));
@@ -158,6 +165,8 @@ public class DefaultDialerCacheTest extends TelecomTestCase {
        Intent packageChangeIntent = new Intent(Intent.ACTION_PACKAGE_CHANGED,
        Intent packageChangeIntent = new Intent(Intent.ACTION_PACKAGE_CHANGED,
                Uri.fromParts("package", "red.orange.blue", null));
                Uri.fromParts("package", "red.orange.blue", null));
        mPackageChangeReceiver.onReceive(mContext, packageChangeIntent);
        mPackageChangeReceiver.onReceive(mContext, packageChangeIntent);
        waitForHandlerAction(mDefaultDialerCache.mHandler, DELAY_TOLERANCE);

        verify(mRoleManagerAdapter, times(2)).getDefaultDialerApp(eq(USER0));
        verify(mRoleManagerAdapter, times(2)).getDefaultDialerApp(eq(USER0));
        verify(mRoleManagerAdapter, times(2)).getDefaultDialerApp(eq(USER1));
        verify(mRoleManagerAdapter, times(2)).getDefaultDialerApp(eq(USER1));
        verify(mRoleManagerAdapter, times(2)).getDefaultDialerApp(eq(USER2));
        verify(mRoleManagerAdapter, times(2)).getDefaultDialerApp(eq(USER2));
@@ -192,6 +201,8 @@ public class DefaultDialerCacheTest extends TelecomTestCase {
        packageChangeIntent.putExtra(Intent.EXTRA_REPLACING, false);
        packageChangeIntent.putExtra(Intent.EXTRA_REPLACING, false);


        mPackageChangeReceiver.onReceive(mContext, packageChangeIntent);
        mPackageChangeReceiver.onReceive(mContext, packageChangeIntent);
        waitForHandlerAction(mDefaultDialerCache.mHandler, DELAY_TOLERANCE);

        verify(mRoleManagerAdapter, times(2)).getDefaultDialerApp(eq(USER0));
        verify(mRoleManagerAdapter, times(2)).getDefaultDialerApp(eq(USER0));
        verify(mRoleManagerAdapter, times(1)).getDefaultDialerApp(eq(USER1));
        verify(mRoleManagerAdapter, times(1)).getDefaultDialerApp(eq(USER1));
        verify(mRoleManagerAdapter, times(1)).getDefaultDialerApp(eq(USER2));
        verify(mRoleManagerAdapter, times(1)).getDefaultDialerApp(eq(USER2));
@@ -208,6 +219,8 @@ public class DefaultDialerCacheTest extends TelecomTestCase {
                Uri.fromParts("package", "ppp.qqq.zzz", null));
                Uri.fromParts("package", "ppp.qqq.zzz", null));


        mPackageChangeReceiver.onReceive(mContext, packageChangeIntent);
        mPackageChangeReceiver.onReceive(mContext, packageChangeIntent);
        waitForHandlerAction(mDefaultDialerCache.mHandler, DELAY_TOLERANCE);

        verify(mRoleManagerAdapter, times(2)).getDefaultDialerApp(eq(USER0));
        verify(mRoleManagerAdapter, times(2)).getDefaultDialerApp(eq(USER0));
        verify(mRoleManagerAdapter, times(2)).getDefaultDialerApp(eq(USER1));
        verify(mRoleManagerAdapter, times(2)).getDefaultDialerApp(eq(USER1));
        verify(mRoleManagerAdapter, times(2)).getDefaultDialerApp(eq(USER2));
        verify(mRoleManagerAdapter, times(2)).getDefaultDialerApp(eq(USER2));
@@ -225,6 +238,8 @@ public class DefaultDialerCacheTest extends TelecomTestCase {
        packageChangeIntent.putExtra(Intent.EXTRA_REPLACING, true);
        packageChangeIntent.putExtra(Intent.EXTRA_REPLACING, true);


        mPackageChangeReceiver.onReceive(mContext, packageChangeIntent);
        mPackageChangeReceiver.onReceive(mContext, packageChangeIntent);
        waitForHandlerAction(mDefaultDialerCache.mHandler, DELAY_TOLERANCE);

        verify(mRoleManagerAdapter, times(1)).getDefaultDialerApp(eq(USER0));
        verify(mRoleManagerAdapter, times(1)).getDefaultDialerApp(eq(USER0));
        verify(mRoleManagerAdapter, times(1)).getDefaultDialerApp(eq(USER1));
        verify(mRoleManagerAdapter, times(1)).getDefaultDialerApp(eq(USER1));
        verify(mRoleManagerAdapter, times(1)).getDefaultDialerApp(eq(USER2));
        verify(mRoleManagerAdapter, times(1)).getDefaultDialerApp(eq(USER2));
@@ -240,7 +255,9 @@ public class DefaultDialerCacheTest extends TelecomTestCase {
        when(mRoleManagerAdapter.getDefaultDialerApp(eq(USER0))).thenReturn(DIALER2);
        when(mRoleManagerAdapter.getDefaultDialerApp(eq(USER0))).thenReturn(DIALER2);
        when(mRoleManagerAdapter.getDefaultDialerApp(eq(USER1))).thenReturn(DIALER2);
        when(mRoleManagerAdapter.getDefaultDialerApp(eq(USER1))).thenReturn(DIALER2);
        when(mRoleManagerAdapter.getDefaultDialerApp(eq(USER2))).thenReturn(DIALER2);
        when(mRoleManagerAdapter.getDefaultDialerApp(eq(USER2))).thenReturn(DIALER2);

        mDefaultDialerSettingObserver.onChange(false);
        mDefaultDialerSettingObserver.onChange(false);
        waitForHandlerAction(mDefaultDialerCache.mHandler, DELAY_TOLERANCE);


        verify(mRoleManagerAdapter, times(2)).getDefaultDialerApp(eq(USER0));
        verify(mRoleManagerAdapter, times(2)).getDefaultDialerApp(eq(USER0));
        verify(mRoleManagerAdapter, times(2)).getDefaultDialerApp(eq(USER2));
        verify(mRoleManagerAdapter, times(2)).getDefaultDialerApp(eq(USER2));