am 9c2a38ed: Merge "Fix resource reading for secondary users" into jb-mr1-dev
* commit '9c2a38ed10592a54d9bb753ef882632f7a8cd446': Fix resource reading for secondary users
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -218,7 +218,7 @@ public class PackageItemInfo {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
protected void dumpFront(Printer pw, String prefix) {
|
||||
if (name != null) {
|
||||
pw.println(prefix + "name=" + name);
|
||||
|
||||
@@ -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,29 +74,39 @@ public class SearchManagerService extends ISearchManager.Stub {
|
||||
mContext = context;
|
||||
mContext.registerReceiver(new BootCompletedReceiver(),
|
||||
new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
|
||||
mGlobalSearchObserver = new GlobalSearchProviderObserver(
|
||||
mContext.getContentResolver());
|
||||
mContext.registerReceiver(new UserReceiver(),
|
||||
new IntentFilter(Intent.ACTION_USER_REMOVED));
|
||||
new MyPackageMonitor().register(context, null, UserHandle.ALL, true);
|
||||
}
|
||||
|
||||
private synchronized Searchables getSearchables(int userId) {
|
||||
if (mSearchables == null) {
|
||||
new MyPackageMonitor().register(mContext, null, true);
|
||||
mSearchables = new SparseArray<Searchables>();
|
||||
}
|
||||
Searchables searchables = mSearchables.get(userId);
|
||||
|
||||
private Searchables getSearchables(int userId) {
|
||||
long origId = Binder.clearCallingIdentity();
|
||||
boolean userExists = ((UserManager) mContext.getSystemService(Context.USER_SERVICE))
|
||||
.getUserInfo(userId) != null;
|
||||
Binder.restoreCallingIdentity(origId);
|
||||
|
||||
if (searchables == null && userExists) {
|
||||
Log.i(TAG, "Building list of searchable activities for userId=" + userId);
|
||||
searchables = new Searchables(mContext, userId);
|
||||
searchables.buildSearchableList();
|
||||
mSearchables.append(userId, searchables);
|
||||
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) {
|
||||
Log.i(TAG, "Building list of searchable activities for userId=" + userId);
|
||||
searchables = new Searchables(mContext, userId);
|
||||
searchables.buildSearchableList();
|
||||
mSearchables.append(userId, searchables);
|
||||
}
|
||||
return searchables;
|
||||
}
|
||||
}
|
||||
|
||||
private void onUserRemoved(int userId) {
|
||||
if (userId != UserHandle.USER_OWNER) {
|
||||
synchronized (mSearchables) {
|
||||
mSearchables.remove(userId);
|
||||
}
|
||||
}
|
||||
return searchables;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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++) {
|
||||
getSearchables(mSearchables.keyAt(i)).buildSearchableList();
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -210,59 +212,64 @@ public class Searchables {
|
||||
// Use intent resolver to generate list of ACTION_SEARCH & ACTION_WEB_SEARCH receivers.
|
||||
List<ResolveInfo> searchList;
|
||||
final Intent intent = new Intent(Intent.ACTION_SEARCH);
|
||||
|
||||
searchList = queryIntentActivities(intent, PackageManager.GET_META_DATA);
|
||||
|
||||
List<ResolveInfo> webSearchInfoList;
|
||||
final Intent webSearchIntent = new Intent(Intent.ACTION_WEB_SEARCH);
|
||||
webSearchInfoList = queryIntentActivities(webSearchIntent, PackageManager.GET_META_DATA);
|
||||
long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
searchList = queryIntentActivities(intent, PackageManager.GET_META_DATA);
|
||||
|
||||
// analyze each one, generate a Searchables record, and record
|
||||
if (searchList != null || webSearchInfoList != null) {
|
||||
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)
|
||||
? searchList.get(ii)
|
||||
: webSearchInfoList.get(ii - search_count);
|
||||
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);
|
||||
if (searchable != null) {
|
||||
newSearchablesList.add(searchable);
|
||||
newSearchablesMap.put(searchable.getSearchActivity(), searchable);
|
||||
if (searchable.shouldIncludeInGlobalSearch()) {
|
||||
newSearchablesInGlobalSearchList.add(searchable);
|
||||
List<ResolveInfo> webSearchInfoList;
|
||||
final Intent webSearchIntent = new Intent(Intent.ACTION_WEB_SEARCH);
|
||||
webSearchInfoList = queryIntentActivities(webSearchIntent, PackageManager.GET_META_DATA);
|
||||
|
||||
// analyze each one, generate a Searchables record, and record
|
||||
if (searchList != null || webSearchInfoList != null) {
|
||||
int search_count = (searchList == null ? 0 : searchList.size());
|
||||
int web_search_count = (webSearchInfoList == null ? 0 : webSearchInfoList.size());
|
||||
int count = search_count + web_search_count;
|
||||
for (int ii = 0; ii < count; ii++) {
|
||||
// for each component, try to find metadata
|
||||
ResolveInfo info = (ii < search_count)
|
||||
? searchList.get(ii)
|
||||
: webSearchInfoList.get(ii - search_count);
|
||||
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,
|
||||
mUserId);
|
||||
if (searchable != null) {
|
||||
newSearchablesList.add(searchable);
|
||||
newSearchablesMap.put(searchable.getSearchActivity(), searchable);
|
||||
if (searchable.shouldIncludeInGlobalSearch()) {
|
||||
newSearchablesInGlobalSearchList.add(searchable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
|
||||
List<ResolveInfo> newGlobalSearchActivities = findGlobalSearchActivities();
|
||||
List<ResolveInfo> newGlobalSearchActivities = findGlobalSearchActivities();
|
||||
|
||||
// Find the global search activity
|
||||
ComponentName newGlobalSearchActivity = findGlobalSearchActivity(
|
||||
newGlobalSearchActivities);
|
||||
// Find the global search activity
|
||||
ComponentName newGlobalSearchActivity = findGlobalSearchActivity(
|
||||
newGlobalSearchActivities);
|
||||
|
||||
// Find the web search activity
|
||||
ComponentName newWebSearchActivity = findWebSearchActivity(newGlobalSearchActivity);
|
||||
// Find the web search activity
|
||||
ComponentName newWebSearchActivity = findWebSearchActivity(newGlobalSearchActivity);
|
||||
|
||||
// Store a consistent set of new values
|
||||
synchronized (this) {
|
||||
mSearchablesMap = newSearchablesMap;
|
||||
mSearchablesList = newSearchablesList;
|
||||
mSearchablesInGlobalSearchList = newSearchablesInGlobalSearchList;
|
||||
mGlobalSearchActivities = newGlobalSearchActivities;
|
||||
mCurrentGlobalSearchActivity = newGlobalSearchActivity;
|
||||
mWebSearchActivity = newWebSearchActivity;
|
||||
// Store a consistent set of new values
|
||||
synchronized (this) {
|
||||
mSearchablesMap = newSearchablesMap;
|
||||
mSearchablesList = newSearchablesList;
|
||||
mSearchablesInGlobalSearchList = newSearchablesInGlobalSearchList;
|
||||
mGlobalSearchActivities = newGlobalSearchActivities;
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -97,6 +97,7 @@ class AppNotRespondingDialog extends BaseErrorDialog {
|
||||
getWindow().addFlags(FLAG_SYSTEM_ERROR);
|
||||
WindowManager.LayoutParams attrs = getWindow().getAttributes();
|
||||
attrs.setTitle("Application Not Responding: " + app.info.processName);
|
||||
attrs.privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
|
||||
getWindow().setAttributes(attrs);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user