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

Commit 64442c11 authored by Amith Yamasani's avatar Amith Yamasani
Browse files

Fix resource reading for secondary users

Bug: 7086881

Load resources for the correct user.

Also clean up package monitoring and locking.
Added dump method to SearchManagerService.

Sneaking in a change to make crash dialogs visible to current user.

Change-Id: Id56dd15428d66084de995e28be242db27c15fda3
parent 1ad0fd9c
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -1694,7 +1694,8 @@ class ContextImpl extends Context {
    @Override
    public Context createPackageContext(String packageName, int flags)
            throws NameNotFoundException {
        return createPackageContextAsUser(packageName, flags, Process.myUserHandle());
        return createPackageContextAsUser(packageName, flags,
                mUser != null ? mUser : Process.myUserHandle());
    }

    @Override
+14 −3
Original line number Diff line number Diff line
@@ -24,10 +24,12 @@ import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.UserHandle;
import android.text.InputType;
import android.util.AttributeSet;
import android.util.Log;
@@ -510,16 +512,25 @@ public final class SearchableInfo implements Parcelable {
     *
     * @hide For use by SearchManagerService.
     */
    public static SearchableInfo getActivityMetaData(Context context, ActivityInfo activityInfo) {
    public static SearchableInfo getActivityMetaData(Context context, ActivityInfo activityInfo,
            int userId) {
        Context userContext = null;
        try {
            userContext = context.createPackageContextAsUser("system", 0,
                new UserHandle(userId));
        } catch (NameNotFoundException nnfe) {
            Log.e(LOG_TAG, "Couldn't create package context for user " + userId);
            return null;
        }
        // for each component, try to find metadata
        XmlResourceParser xml = 
                activityInfo.loadXmlMetaData(context.getPackageManager(), MD_LABEL_SEARCHABLE);
                activityInfo.loadXmlMetaData(userContext.getPackageManager(), MD_LABEL_SEARCHABLE);
        if (xml == null) {
            return null;
        }
        ComponentName cName = new ComponentName(activityInfo.packageName, activityInfo.name);
        
        SearchableInfo searchable = getActivityMetaData(context, xml, cName);
        SearchableInfo searchable = getActivityMetaData(userContext, xml, cName);
        xml.close();
        
        if (DBG) {
+59 −24
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.server.search;

import com.android.internal.content.PackageMonitor;
import com.android.internal.util.IndentingPrintWriter;

import android.app.ActivityManager;
import android.app.ActivityManagerNative;
@@ -44,6 +45,8 @@ import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.List;

/**
@@ -59,9 +62,7 @@ public class SearchManagerService extends ISearchManager.Stub {
    private final Context mContext;

    // This field is initialized lazily in getSearchables(), and then never modified.
    private SparseArray<Searchables> mSearchables;

    private ContentObserver mGlobalSearchObserver;
    private final SparseArray<Searchables> mSearchables = new SparseArray<Searchables>();

    /**
     * Initializes the Search Manager service in the provided system context.
@@ -73,23 +74,24 @@ public class SearchManagerService extends ISearchManager.Stub {
        mContext = context;
        mContext.registerReceiver(new BootCompletedReceiver(),
                new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
        mGlobalSearchObserver = new GlobalSearchProviderObserver(
                mContext.getContentResolver());
    }

    private synchronized Searchables getSearchables(int userId) {
        if (mSearchables == null) {
            new MyPackageMonitor().register(mContext, null, true);
            mSearchables = new SparseArray<Searchables>();
        mContext.registerReceiver(new UserReceiver(), 
                new IntentFilter(Intent.ACTION_USER_REMOVED));
        new MyPackageMonitor().register(context, null, UserHandle.ALL, true);
    }
        Searchables searchables = mSearchables.get(userId);

    private Searchables getSearchables(int userId) {
        long origId = Binder.clearCallingIdentity();
        try {
            boolean userExists = ((UserManager) mContext.getSystemService(Context.USER_SERVICE))
                    .getUserInfo(userId) != null;
            if (!userExists) return null;
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
        synchronized (mSearchables) {
            Searchables searchables = mSearchables.get(userId);

        if (searchables == null && userExists) {
            if (searchables == null) {
                Log.i(TAG, "Building list of searchable activities for userId=" + userId);
                searchables = new Searchables(mContext, userId);
                searchables.buildSearchableList();
@@ -97,6 +99,15 @@ public class SearchManagerService extends ISearchManager.Stub {
            }
            return searchables;
        }
    }

    private void onUserRemoved(int userId) {
        if (userId != UserHandle.USER_OWNER) {
            synchronized (mSearchables) {
                mSearchables.remove(userId);
            }
        }
    }

    /**
     * Creates the initial searchables list after boot.
@@ -115,6 +126,13 @@ public class SearchManagerService extends ISearchManager.Stub {
        }
    }

    private final class UserReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            onUserRemoved(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_OWNER));
        }
    }

    /**
     * Refreshes the "searchables" list when packages are added/removed.
     */
@@ -131,16 +149,20 @@ public class SearchManagerService extends ISearchManager.Stub {
        }

        private void updateSearchables() {
            synchronized (SearchManagerService.this) {
            final int changingUserId = getChangingUserId();
            synchronized (mSearchables) {
                // Update list of searchable activities
                for (int i = 0; i < mSearchables.size(); i++) {
                    if (changingUserId == mSearchables.keyAt(i)) {
                        getSearchables(mSearchables.keyAt(i)).buildSearchableList();
                        break;
                    }
                }
            }
            // Inform all listeners that the list of searchables has been updated.
            Intent intent = new Intent(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED);
            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
            mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
            mContext.sendBroadcastAsUser(intent, new UserHandle(changingUserId));
        }
    }

@@ -158,7 +180,7 @@ public class SearchManagerService extends ISearchManager.Stub {

        @Override
        public void onChange(boolean selfChange) {
            synchronized (SearchManagerService.this) {
            synchronized (mSearchables) {
                for (int i = 0; i < mSearchables.size(); i++) {
                    getSearchables(mSearchables.keyAt(i)).buildSearchableList();
                }
@@ -258,4 +280,17 @@ public class SearchManagerService extends ISearchManager.Stub {
        }
        return null;
    }

    @Override
    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
        synchronized (mSearchables) {
            for (int i = 0; i < mSearchables.size(); i++) {
                ipw.print("\nUser: "); ipw.println(mSearchables.keyAt(i));
                ipw.increaseIndent();
                mSearchables.valueAt(i).dump(fd, ipw, args);
                ipw.decreaseIndent();
            }
        }
    }
}
+61 −43
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@ import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -211,6 +213,8 @@ public class Searchables {
        List<ResolveInfo> searchList;
        final Intent intent = new Intent(Intent.ACTION_SEARCH);

        long ident = Binder.clearCallingIdentity();
        try {
            searchList = queryIntentActivities(intent, PackageManager.GET_META_DATA);

            List<ResolveInfo> webSearchInfoList;
@@ -222,7 +226,6 @@ public class Searchables {
                int search_count = (searchList == null ? 0 : searchList.size());
                int web_search_count = (webSearchInfoList == null ? 0 : webSearchInfoList.size());
                int count = search_count + web_search_count;
            long token = Binder.clearCallingIdentity();
                for (int ii = 0; ii < count; ii++) {
                    // for each component, try to find metadata
                    ResolveInfo info = (ii < search_count)
@@ -231,7 +234,8 @@ public class Searchables {
                    ActivityInfo ai = info.activityInfo;
                    // Check first to avoid duplicate entries.
                    if (newSearchablesMap.get(new ComponentName(ai.packageName, ai.name)) == null) {
                    SearchableInfo searchable = SearchableInfo.getActivityMetaData(mContext, ai);
                        SearchableInfo searchable = SearchableInfo.getActivityMetaData(mContext, ai,
                                mUserId);
                        if (searchable != null) {
                            newSearchablesList.add(searchable);
                            newSearchablesMap.put(searchable.getSearchActivity(), searchable);
@@ -241,7 +245,6 @@ public class Searchables {
                        }
                    }
                }
            Binder.restoreCallingIdentity(token);
            }

            List<ResolveInfo> newGlobalSearchActivities = findGlobalSearchActivities();
@@ -262,7 +265,11 @@ public class Searchables {
                mCurrentGlobalSearchActivity = newGlobalSearchActivity;
                mWebSearchActivity = newWebSearchActivity;
            }
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    }

    /**
     * Returns a sorted list of installed search providers as per
     * the following heuristics:
@@ -443,4 +450,15 @@ public class Searchables {
    public synchronized ComponentName getWebSearchActivity() {
        return mWebSearchActivity;
    }

    void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        pw.println("Searchable authorities:");
        synchronized (this) {
            if (mSearchablesList != null) {
                for (SearchableInfo info: mSearchablesList) {
                    pw.print("  "); pw.println(info.getSuggestAuthority());
                }
            }
        }
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ class AppErrorDialog extends BaseErrorDialog {
        getWindow().addFlags(FLAG_SYSTEM_ERROR);
        WindowManager.LayoutParams attrs = getWindow().getAttributes();
        attrs.setTitle("Application Error: " + app.info.processName);
        attrs.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
        getWindow().setAttributes(attrs);
        if (app.persistent) {
            getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
Loading