diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java index 900544220ccec..5ea6cfa73fcda 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java +++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java @@ -69,7 +69,7 @@ public class DocumentsApplication extends Application { final int memoryClassBytes = am.getMemoryClass() * 1024 * 1024; mRoots = new RootsCache(this); - mRoots.updateAsync(); + mRoots.updateAsync(false); mThumbnails = new ThumbnailCache(memoryClassBytes / 4); @@ -105,7 +105,7 @@ public class DocumentsApplication extends Application { final String packageName = data.getSchemeSpecificPart(); mRoots.updatePackageAsync(packageName); } else { - mRoots.updateAsync(); + mRoots.updateAsync(true); } } }; diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java index 09fadc98a7e0d..594e02f0a01d8 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java +++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java @@ -122,7 +122,7 @@ public class RootsCache { /** * Gather roots from all known storage providers. */ - public void updateAsync() { + public void updateAsync(boolean forceRefreshAll) { // NOTE: This method is called when the UI language changes. // For that reason we update our RecentsRoot to reflect @@ -139,14 +139,15 @@ public class RootsCache { | Root.FLAG_SUPPORTS_CREATE)); assert(mRecentsRoot.availableBytes == -1); - new UpdateTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + new UpdateTask(forceRefreshAll, null) + .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } /** * Gather roots from storage providers belonging to given package name. */ public void updatePackageAsync(String packageName) { - new UpdateTask(packageName).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + new UpdateTask(false, packageName).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } /** @@ -223,23 +224,22 @@ public class RootsCache { } private class UpdateTask extends AsyncTask { + private final boolean mForceRefreshAll; private final String mForceRefreshPackage; private final Multimap mTaskRoots = ArrayListMultimap.create(); private final HashSet mTaskStoppedAuthorities = new HashSet<>(); /** - * Update all roots. + * Create task to update roots cache. + * + * @param forceRefreshAll when true, all previously cached values for + * all packages should be ignored. + * @param forceRefreshPackage when non-null, all previously cached + * values for this specific package should be ignored. */ - public UpdateTask() { - this(null); - } - - /** - * Force update roots belonging to given package name. Other roots will - * be copied from cached {@link #mRoots} values. - */ - public UpdateTask(String forceRefreshPackage) { + public UpdateTask(boolean forceRefreshAll, String forceRefreshPackage) { + mForceRefreshAll = forceRefreshAll; mForceRefreshPackage = forceRefreshPackage; } @@ -247,14 +247,6 @@ public class RootsCache { protected Void doInBackground(Void... params) { final long start = SystemClock.elapsedRealtime(); - if (mForceRefreshPackage != null) { - // We must have previously cached values to fill in non-matching - // packages, so wait around for successful first load. - if (!waitForFirstLoad()) { - return null; - } - } - mTaskRoots.put(mRecentsRoot.authority, mRecentsRoot); final ContentResolver resolver = mContext.getContentResolver(); @@ -300,7 +292,8 @@ public class RootsCache { return; } - final boolean forceRefresh = Objects.equals(mForceRefreshPackage, info.packageName); + final boolean forceRefresh = mForceRefreshAll + || Objects.equals(info.packageName, mForceRefreshPackage); mTaskRoots.putAll(info.authority, loadRootsForAuthority(mContext.getContentResolver(), info.authority, forceRefresh)); } diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java index 7f7ea9d8060c8..e9d962827632e 100644 --- a/services/core/java/com/android/server/content/ContentService.java +++ b/services/core/java/com/android/server/content/ContentService.java @@ -42,10 +42,10 @@ import android.database.sqlite.SQLiteException; import android.net.Uri; import android.os.Binder; import android.os.Bundle; +import android.os.FactoryTest; import android.os.IBinder; import android.os.Parcel; import android.os.RemoteException; -import android.os.ServiceManager; import android.os.SystemProperties; import android.os.UserHandle; import android.text.TextUtils; @@ -59,6 +59,7 @@ import android.util.SparseIntArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.IndentingPrintWriter; import com.android.server.LocalServices; +import com.android.server.SystemService; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -74,6 +75,29 @@ import java.util.List; public final class ContentService extends IContentService.Stub { private static final String TAG = "ContentService"; + public static class Lifecycle extends SystemService { + private ContentService mContentService; + + public Lifecycle(Context context) { + super(context); + } + + @Override + public void onStart() { + final boolean factoryTest = (FactoryTest + .getMode() == FactoryTest.FACTORY_TEST_LOW_LEVEL); + mContentService = new ContentService(getContext(), factoryTest); + publishBinderService(ContentResolver.CONTENT_SERVICE_NAME, mContentService); + } + + @Override + public void onCleanupUser(int userHandle) { + synchronized (mContentService.mCache) { + mContentService.mCache.remove(userHandle); + } + } + } + private Context mContext; private boolean mFactoryTest; @@ -94,12 +118,18 @@ public final class ContentService extends IContentService.Stub { private BroadcastReceiver mCacheReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - final Uri data = intent.getData(); - if (data != null) { - final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, - UserHandle.USER_NULL); - final String packageName = data.getSchemeSpecificPart(); - invalidateCacheLocked(userId, packageName, null); + synchronized (mCache) { + if (Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) { + mCache.clear(); + } else { + final Uri data = intent.getData(); + if (data != null) { + final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, + UserHandle.USER_NULL); + final String packageName = data.getSchemeSpecificPart(); + invalidateCacheLocked(userId, packageName, null); + } + } } } }; @@ -227,6 +257,11 @@ public final class ContentService extends IContentService.Stub { packageFilter.addDataScheme("package"); mContext.registerReceiverAsUser(mCacheReceiver, UserHandle.ALL, packageFilter, null, null); + + final IntentFilter localeFilter = new IntentFilter(); + localeFilter.addAction(Intent.ACTION_LOCALE_CHANGED); + mContext.registerReceiverAsUser(mCacheReceiver, UserHandle.ALL, + localeFilter, null, null); } public void systemReady() { @@ -1080,12 +1115,6 @@ public final class ContentService extends IContentService.Stub { } } - public static ContentService main(Context context, boolean factoryTest) { - ContentService service = new ContentService(context, factoryTest); - ServiceManager.addService(ContentResolver.CONTENT_SERVICE_NAME, service); - return service; - } - /** * Checks if the request is from the system or an app that has INTERACT_ACROSS_USERS_FULL * permission, if the userHandle is not for the caller. diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 659450efcce39..81e43fd54fc2e 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -157,6 +157,8 @@ public final class SystemServer { "com.google.android.clockwork.ThermalObserver"; private static final String WEAR_BLUETOOTH_SERVICE_CLASS = "com.google.android.clockwork.bluetooth.WearBluetoothService"; + private static final String CONTENT_SERVICE_CLASS = + "com.android.server.content.ContentService$Lifecycle"; private static final String PERSISTENT_DATA_BLOCK_PROP = "ro.frp.pst"; @@ -574,8 +576,7 @@ public final class SystemServer { Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); traceBeginAndSlog("StartContentService"); - contentService = ContentService.main(context, - mFactoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL); + mSystemServiceManager.startService(CONTENT_SERVICE_CLASS); Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); traceBeginAndSlog("InstallSystemProviders"); @@ -1324,7 +1325,7 @@ public final class SystemServer { reportWtf("starting System UI", e); } Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); - Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakeMountServiceReady"); + Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakeNetworkScoreReady"); try { if (networkScoreF != null) networkScoreF.systemReady(); } catch (Throwable e) {