diff options
Diffstat (limited to 'core/java')
25 files changed, 563 insertions, 222 deletions
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 83acb4d..bb62c9e 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -1772,6 +1772,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM IUserSwitchObserver observer = IUserSwitchObserver.Stub.asInterface( data.readStrongBinder()); registerUserSwitchObserver(observer); + reply.writeNoException(); return true; } @@ -1780,12 +1781,24 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM IUserSwitchObserver observer = IUserSwitchObserver.Stub.asInterface( data.readStrongBinder()); unregisterUserSwitchObserver(observer); + reply.writeNoException(); return true; } case REQUEST_BUG_REPORT_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); requestBugReport(); + reply.writeNoException(); + return true; + } + + case INPUT_DISPATCHING_TIMED_OUT_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + int pid = data.readInt(); + boolean aboveSystem = data.readInt() != 0; + long res = inputDispatchingTimedOut(pid, aboveSystem); + reply.writeNoException(); + reply.writeLong(res); return true; } @@ -4082,5 +4095,19 @@ class ActivityManagerProxy implements IActivityManager reply.recycle(); } + public long inputDispatchingTimedOut(int pid, boolean aboveSystem) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeInt(pid); + data.writeInt(aboveSystem ? 1 : 0); + mRemote.transact(INPUT_DISPATCHING_TIMED_OUT_TRANSACTION, data, reply, 0); + reply.readException(); + long res = reply.readInt(); + data.recycle(); + reply.recycle(); + return res; + } + private IBinder mRemote; } diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 59fa1e0..c324da9 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -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 @@ -1702,8 +1703,8 @@ class ContextImpl extends Context { throws NameNotFoundException { if (packageName.equals("system") || packageName.equals("android")) { final ContextImpl context = new ContextImpl(mMainThread.getSystemContext()); - context.mBasePackageName = mBasePackageName; - context.mUser = user; + context.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED; + context.init(mPackageInfo, null, mMainThread, mResources, mBasePackageName, user); return context; } diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 3124671..da844ef 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -363,6 +363,8 @@ public interface IActivityManager extends IInterface { public void requestBugReport() throws RemoteException; + public long inputDispatchingTimedOut(int pid, boolean aboveSystem) throws RemoteException; + /* * Private non-Binder interfaces */ @@ -616,4 +618,5 @@ public interface IActivityManager extends IInterface { int UNREGISTER_USER_SWITCH_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+155; int GET_RUNNING_USER_IDS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+156; int REQUEST_BUG_REPORT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+157; + int INPUT_DISPATCHING_TIMED_OUT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+158; } diff --git a/core/java/android/app/SearchableInfo.java b/core/java/android/app/SearchableInfo.java index 5482f60..922ebdd 100644 --- a/core/java/android/app/SearchableInfo.java +++ b/core/java/android/app/SearchableInfo.java @@ -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) { diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java index f258f17..fcecd04 100644 --- a/core/java/android/appwidget/AppWidgetHostView.java +++ b/core/java/android/appwidget/AppWidgetHostView.java @@ -161,7 +161,7 @@ public class AppWidgetHostView extends FrameLayout { * @param component the component name of the widget * @param padding Rect in which to place the output, if null, a new Rect will be allocated and * returned - * @return default padding for this widget + * @return default padding for this widget, in pixels */ public static Rect getDefaultPaddingForWidget(Context context, ComponentName component, Rect padding) { @@ -241,7 +241,7 @@ public class AppWidgetHostView extends FrameLayout { * AppWidget options and causes a callback to the AppWidgetProvider. * @see AppWidgetProvider#onAppWidgetOptionsChanged(Context, AppWidgetManager, int, Bundle) * - * @param options The bundle of options, in addition to the size information, + * @param newOptions The bundle of options, in addition to the size information, * can be null. * @param minWidth The minimum width that the widget will be displayed at. * @param minHeight The maximum height that the widget will be displayed at. @@ -249,10 +249,10 @@ public class AppWidgetHostView extends FrameLayout { * @param maxHeight The maximum height that the widget will be displayed at. * */ - public void updateAppWidgetSize(Bundle options, int minWidth, int minHeight, int maxWidth, + public void updateAppWidgetSize(Bundle newOptions, int minWidth, int minHeight, int maxWidth, int maxHeight) { - if (options == null) { - options = new Bundle(); + if (newOptions == null) { + newOptions = new Bundle(); } Rect padding = new Rect(); @@ -264,11 +264,30 @@ public class AppWidgetHostView extends FrameLayout { int xPaddingDips = (int) ((padding.left + padding.right) / density); int yPaddingDips = (int) ((padding.top + padding.bottom) / density); - options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, minWidth - xPaddingDips); - options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, minHeight - yPaddingDips); - options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, maxWidth - xPaddingDips); - options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, maxHeight - yPaddingDips); - updateAppWidgetOptions(options); + int newMinWidth = minWidth - xPaddingDips; + int newMinHeight = minHeight - yPaddingDips; + int newMaxWidth = maxWidth - xPaddingDips; + int newMaxHeight = maxHeight - yPaddingDips; + + AppWidgetManager widgetManager = AppWidgetManager.getInstance(mContext); + + // We get the old options to see if the sizes have changed + Bundle oldOptions = widgetManager.getAppWidgetOptions(mAppWidgetId); + boolean needsUpdate = false; + if (newMinWidth != oldOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH) || + newMinHeight != oldOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT) || + newMaxWidth != oldOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH) || + newMaxHeight != oldOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT)) { + needsUpdate = true; + } + + if (needsUpdate) { + newOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, newMinWidth); + newOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, newMinHeight); + newOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, newMaxWidth); + newOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, newMaxHeight); + updateAppWidgetOptions(newOptions); + } } /** diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index b884b98..e2ca1dd 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -155,6 +155,12 @@ public class ActivityInfo extends ComponentInfo */ public static final int FLAG_HARDWARE_ACCELERATED = 0x0200; /** + * Value for {@link #flags}: true when the application can be displayed over the lockscreen + * and consequently over all users' windows. + * @hide + */ + public static final int FLAG_SHOW_ON_LOCK_SCREEN = 0x0400; + /** * @hide * Bit in {@link #flags} corresponding to an immersive activity * that wishes not to be interrupted by notifications. @@ -170,7 +176,7 @@ public class ActivityInfo extends ComponentInfo * "toast" window). * {@see android.app.Notification#FLAG_HIGH_PRIORITY} */ - public static final int FLAG_IMMERSIVE = 0x0400; + public static final int FLAG_IMMERSIVE = 0x0800; /** * @hide Bit in {@link #flags}: If set, this component will only be seen * by the primary user. Only works with broadcast receivers. Set from the diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java index d73aaf6..a67326e 100644 --- a/core/java/android/content/pm/PackageItemInfo.java +++ b/core/java/android/content/pm/PackageItemInfo.java @@ -218,7 +218,7 @@ public class PackageItemInfo { } return null; } - + protected void dumpFront(Printer pw, String prefix) { if (name != null) { pw.println(prefix + "name=" + name); diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index c2b75f4..3e8c2a8 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -2160,11 +2160,17 @@ public class PackageParser { } if (sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestActivity_showOnLockScreen, + false)) { + a.info.flags |= ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN; + } + + if (sa.getBoolean( com.android.internal.R.styleable.AndroidManifestActivity_immersive, false)) { a.info.flags |= ActivityInfo.FLAG_IMMERSIVE; } - + if (!receiver) { if (sa.getBoolean( com.android.internal.R.styleable.AndroidManifestActivity_hardwareAccelerated, diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index fb02c0a..7e11c22 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -178,6 +178,16 @@ public final class PowerManager { /** * Wake lock level: Turns the screen off when the proximity sensor activates. * <p> + * If the proximity sensor detects that an object is nearby, the screen turns off + * immediately. Shortly after the object moves away, the screen turns on again. + * </p><p> + * A proximity wake lock does not prevent the device from falling asleep + * unlike {@link #FULL_WAKE_LOCK}, {@link #SCREEN_BRIGHT_WAKE_LOCK} and + * {@link #SCREEN_DIM_WAKE_LOCK}. If there is no user activity and no other + * wake locks are held, then the device will fall asleep (and lock) as usual. + * However, the device will not fall asleep while the screen has been turned off + * by the proximity sensor because it effectively counts as ongoing user activity. + * </p><p> * Since not all devices have proximity sensors, use {@link #isWakeLockLevelSupported} * to determine whether this wake lock level is supported. * </p> diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 96c96d7..83a0c78 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -98,6 +98,32 @@ public class UserManager { } /** + * Return the serial number for a user. This is a device-unique + * number assigned to that user; if the user is deleted and new users + * created, the new users will not be given the same serial number. + * @param user The user whose serial number is to be retrieved. + * @return The serial number of the given user. + * @see #getUserForSerialNumber(long) + */ + public long getSerialNumberForUser(UserHandle user) { + return getUserSerialNumber(user.getIdentifier()); + } + + /** + * Return the user associated with a serial number previously + * returned by {@link #getSerialNumberForUser(UserHandle)}. + * @param serialNumber The serial number of the user that is being + * retrieved. + * @return Return the user associated with the serial number, or null + * if there is not one. + * @see #getSerialNumberForUser(UserHandle) + */ + public UserHandle getUserForSerialNumber(long serialNumber) { + int ident = getUserHandle((int)serialNumber); + return ident >= 0 ? new UserHandle(ident) : null; + } + + /** * Creates a user with the specified name and options. * Requires {@link android.Manifest.permission#MANAGE_USERS} permission. * diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java index bc3efdd..de4dd88 100644 --- a/core/java/android/server/search/SearchManagerService.java +++ b/core/java/android/server/search/SearchManagerService.java @@ -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>(); + 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); } - Searchables searchables = mSearchables.get(userId); + synchronized (mSearchables) { + Searchables searchables = mSearchables.get(userId); - long origId = Binder.clearCallingIdentity(); - boolean userExists = ((UserManager) mContext.getSystemService(Context.USER_SERVICE)) - .getUserInfo(userId) != null; - Binder.restoreCallingIdentity(origId); + 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; + } + } - 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); + 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(); + } + } + } } diff --git a/core/java/android/server/search/Searchables.java b/core/java/android/server/search/Searchables.java index 30ca340..a0095d6 100644 --- a/core/java/android/server/search/Searchables.java +++ b/core/java/android/server/search/Searchables.java @@ -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); - - // 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); + + long ident = Binder.clearCallingIdentity(); + try { + 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); + + // 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()); + } + } + } + } } diff --git a/core/java/android/service/dreams/Dream.java b/core/java/android/service/dreams/Dream.java deleted file mode 100644 index 4e8b05b..0000000 --- a/core/java/android/service/dreams/Dream.java +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright (C) 2012 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 android.service.dreams; - -/** - * @hide - * Temporarily needed to not break existing apps. - */ -public class Dream extends DreamService { -} diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java index 03b685b..cb78763 100644 --- a/core/java/android/service/dreams/DreamService.java +++ b/core/java/android/service/dreams/DreamService.java @@ -15,10 +15,14 @@ */ package android.service.dreams; +import java.io.FileDescriptor; +import java.io.PrintWriter; + import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.app.Service; import android.content.Intent; +import android.graphics.PixelFormat; import android.graphics.drawable.ColorDrawable; import android.os.Handler; import android.os.IBinder; @@ -39,13 +43,24 @@ import android.view.accessibility.AccessibilityEvent; import com.android.internal.policy.PolicyManager; /** - * Extend this class to implement a custom Dream. + * Extend this class to implement a custom Dream (displayed to the user as a "Sleep Mode"). * * <p>Dreams are interactive screensavers launched when a charging device is idle, or docked in a * desk dock. Dreams provide another modality for apps to express themselves, tailored for * an exhibition/lean-back experience.</p> * - * <p>Dreams should be declared in the manifest as follows:</p> + * <p>The Dream lifecycle is as follows:</p> + * <ul> + * <li>onAttachedToWindow</li> + * <li>onDreamingStarted</li> + * <li>onDreamingStopped</li> + * <li>onDetachedFromWindow</li> + * </ul> + * + * <p>In addition, onCreate and onDestroy (from the Service interface) will also be called, but + * initialization and teardown should be done by overriding the hooks above.</p> + * + * <p>To be available to the system, Dreams should be declared in the manifest as follows:</p> * <pre> * <service * android:name=".MyDream" @@ -74,7 +89,6 @@ import com.android.internal.policy.PolicyManager; * </pre> */ public class DreamService extends Service implements Window.Callback { - private final static boolean DEBUG = true; private final String TAG = DreamService.class.getSimpleName() + "[" + getClass().getSimpleName() + "]"; /** @@ -109,17 +123,26 @@ public class DreamService extends Service implements Window.Callback { private boolean mScreenBright = false; private boolean mFinished; + private boolean mDebug = false; + + /** + * @hide + */ + public void setDebug(boolean dbg) { + mDebug = dbg; + } + // begin Window.Callback methods /** {@inheritDoc} */ @Override public boolean dispatchKeyEvent(KeyEvent event) { // TODO: create more flexible version of mInteractive that allows use of KEYCODE_BACK if (!mInteractive) { - if (DEBUG) Slog.v(TAG, "Finishing on keyEvent"); + if (mDebug) Slog.v(TAG, "Finishing on keyEvent"); safelyFinish(); return true; } else if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) { - if (DEBUG) Slog.v(TAG, "Finishing on back key"); + if (mDebug) Slog.v(TAG, "Finishing on back key"); safelyFinish(); return true; } @@ -129,8 +152,8 @@ public class DreamService extends Service implements Window.Callback { /** {@inheritDoc} */ @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) { - if (!mInteractive) { - if (DEBUG) Slog.v(TAG, "Finishing on keyShortcutEvent"); + if (!mInteractive) { + if (mDebug) Slog.v(TAG, "Finishing on keyShortcutEvent"); safelyFinish(); return true; } @@ -140,10 +163,10 @@ public class DreamService extends Service implements Window.Callback { /** {@inheritDoc} */ @Override public boolean dispatchTouchEvent(MotionEvent event) { - // TODO: create more flexible version of mInteractive that allows clicks + // TODO: create more flexible version of mInteractive that allows clicks // but finish()es on any other kind of activity - if (!mInteractive) { - if (DEBUG) Slog.v(TAG, "Finishing on touchEvent"); + if (!mInteractive) { + if (mDebug) Slog.v(TAG, "Finishing on touchEvent"); safelyFinish(); return true; } @@ -154,7 +177,7 @@ public class DreamService extends Service implements Window.Callback { @Override public boolean dispatchTrackballEvent(MotionEvent event) { if (!mInteractive) { - if (DEBUG) Slog.v(TAG, "Finishing on trackballEvent"); + if (mDebug) Slog.v(TAG, "Finishing on trackballEvent"); safelyFinish(); return true; } @@ -164,8 +187,8 @@ public class DreamService extends Service implements Window.Callback { /** {@inheritDoc} */ @Override public boolean dispatchGenericMotionEvent(MotionEvent event) { - if (!mInteractive) { - if (DEBUG) Slog.v(TAG, "Finishing on genericMotionEvent"); + if (!mInteractive) { + if (mDebug) Slog.v(TAG, "Finishing on genericMotionEvent"); safelyFinish(); return true; } @@ -289,7 +312,7 @@ public class DreamService extends Service implements Window.Callback { * <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p> * * @param layoutResID Resource ID to be inflated. - * + * * @see #setContentView(android.view.View) * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams) */ @@ -314,7 +337,7 @@ public class DreamService extends Service implements Window.Callback { /** * Sets a view to be the content view for this Dream. - * Behaves similarly to + * Behaves similarly to * {@link android.app.Activity#setContentView(android.view.View, android.view.ViewGroup.LayoutParams)}. * * <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p> @@ -379,6 +402,9 @@ public class DreamService extends Service implements Window.Callback { * Sets View.SYSTEM_UI_FLAG_LOW_PROFILE on the content view. * * @param lowProfile True to set View.SYSTEM_UI_FLAG_LOW_PROFILE + * @hide There is no reason to have this -- dreams can set this flag + * on their own content view, and from there can actually do the + * correct interactions with it (seeing when it is cleared etc). */ public void setLowProfile(boolean lowProfile) { mLowProfile = lowProfile; @@ -390,20 +416,23 @@ public class DreamService extends Service implements Window.Callback { * Returns whether or not this dream is in low profile mode. Defaults to true. * * @see #setLowProfile(boolean) + * @hide */ public boolean isLowProfile() { return getSystemUiVisibilityFlagValue(View.SYSTEM_UI_FLAG_LOW_PROFILE, mLowProfile); } /** - * Sets View.SYSTEM_UI_FLAG_FULLSCREEN on the content view. + * Controls {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN} + * on the dream's window. * - * @param fullscreen True to set View.SYSTEM_UI_FLAG_FULLSCREEN + * @param fullscreen If true, the fullscreen flag will be set; else it + * will be cleared. */ public void setFullscreen(boolean fullscreen) { mFullscreen = fullscreen; - int flag = View.SYSTEM_UI_FLAG_FULLSCREEN; - applySystemUiVisibilityFlags(mFullscreen ? flag : 0, flag); + int flag = WindowManager.LayoutParams.FLAG_FULLSCREEN; + applyWindowFlags(mFullscreen ? flag : 0, flag); } /** @@ -412,7 +441,7 @@ public class DreamService extends Service implements Window.Callback { * @see #setFullscreen(boolean) */ public boolean isFullscreen() { - return getSystemUiVisibilityFlagValue(View.SYSTEM_UI_FLAG_FULLSCREEN, mFullscreen); + return mFullscreen; } /** @@ -437,68 +466,105 @@ public class DreamService extends Service implements Window.Callback { } /** - * Called when this Dream is constructed. Place your initialization here. - * - * <p>Subclasses must call through to the superclass implementation.</p> + * Called when this Dream is constructed. */ @Override public void onCreate() { - if (DEBUG) Slog.v(TAG, "onCreate() on thread " + Thread.currentThread().getId()); + if (mDebug) Slog.v(TAG, "onCreate() on thread " + Thread.currentThread().getId()); super.onCreate(); - loadSandman(); } /** - * Called when this Dream is started. The window is created and visible at this point. + * Called when the dream's window has been created and is visible and animation may now begin. */ - public void onStart() { - if (DEBUG) Slog.v(TAG, "onStart()"); + public void onDreamingStarted() { + if (mDebug) Slog.v(TAG, "onDreamingStarted()"); + // hook for subclasses + } + + /** + * Called when this Dream is stopped, either by external request or by calling finish(), + * before the window has been removed. + */ + public void onDreamingStopped() { + if (mDebug) Slog.v(TAG, "onDreamingStopped()"); // hook for subclasses } /** {@inheritDoc} */ @Override public final IBinder onBind(Intent intent) { - if (DEBUG) Slog.v(TAG, "onBind() intent = " + intent); + if (mDebug) Slog.v(TAG, "onBind() intent = " + intent); return new DreamServiceWrapper(); } /** * Stops the dream, detaches from the window, and wakes up. - * - * <p>Subclasses must call through to the superclass implementation.</p> - * - * <p>After this method is called, the service will be stopped.</p> */ - public void finish() { - if (DEBUG) Slog.v(TAG, "finish()"); + public final void finish() { + if (mDebug) Slog.v(TAG, "finish()"); finishInternal(); } /** {@inheritDoc} */ @Override public void onDestroy() { - if (DEBUG) Slog.v(TAG, "onDestroy()"); + if (mDebug) Slog.v(TAG, "onDestroy()"); super.onDestroy(); + // hook for subclasses + } + + // end public api - if (DEBUG) Slog.v(TAG, "Removing window"); + private void loadSandman() { + mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE)); + } + + /** + * Called when the Dream is about to be unbound and destroyed. + * + * Must run on mHandler. + */ + private final void detach() { + if (mWindow == null) { + Slog.e(TAG, "detach() called when not attached"); + return; + } + + try { + onDreamingStopped(); + } catch (Throwable t) { + Slog.w(TAG, "Crashed in onDreamingStopped()", t); + // we were going to stop anyway + } + + if (mDebug) Slog.v(TAG, "detach(): Removing window from window manager"); try { mWindowManager.removeView(mWindow.getDecorView()); } catch (Throwable t) { Slog.w(TAG, "Crashed removing window view", t); } - } - // end public api - private void loadSandman() { - mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE)); + mWindow = null; + mWindowToken = null; } + /** + * Called when the Dream is ready to be shown. + * + * Must run on mHandler. + * + * @param windowToken A window token that will allow a window to be created in the correct layer. + */ private final void attach(IBinder windowToken) { - if (DEBUG) Slog.v(TAG, "Attached on thread " + Thread.currentThread().getId()); + if (mWindowToken != null) { + Slog.e(TAG, "attach() called when already attached with token=" + mWindowToken); + return; + } + + if (mDebug) Slog.v(TAG, "Attached on thread " + Thread.currentThread().getId()); if (mSandman == null) { - Slog.w(TAG, "No dream manager found, super.onCreate may not have been called"); loadSandman(); } mWindowToken = windowToken; @@ -506,55 +572,53 @@ public class DreamService extends Service implements Window.Callback { mWindow.setCallback(this); mWindow.requestFeature(Window.FEATURE_NO_TITLE); mWindow.setBackgroundDrawable(new ColorDrawable(0xFF000000)); + mWindow.setFormat(PixelFormat.OPAQUE); - if (DEBUG) Slog.v(TAG, String.format("Attaching window token: %s to window of type %s", + if (mDebug) Slog.v(TAG, String.format("Attaching window token: %s to window of type %s", windowToken, WindowManager.LayoutParams.TYPE_DREAM)); WindowManager.LayoutParams lp = mWindow.getAttributes(); lp.type = WindowManager.LayoutParams.TYPE_DREAM; lp.token = windowToken; lp.windowAnimations = com.android.internal.R.style.Animation_Dream; - lp.flags |= ( WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED + lp.flags |= ( WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN + | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR + | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON + | (mFullscreen ? WindowManager.LayoutParams.FLAG_FULLSCREEN : 0) | (mScreenBright ? WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON : 0) ); mWindow.setAttributes(lp); - if (DEBUG) Slog.v(TAG, "Created and attached window: " + mWindow); + if (mDebug) Slog.v(TAG, "Created and attached window: " + mWindow); mWindow.setWindowManager(null, windowToken, "dream", true); mWindowManager = mWindow.getWindowManager(); - // now make it visible (on the ui thread) - mHandler.post(new Runnable(){ - @Override - public void run() { - if (DEBUG) Slog.v(TAG, "Window added on thread " + Thread.currentThread().getId()); - try { - applySystemUiVisibilityFlags( - (mLowProfile ? View.SYSTEM_UI_FLAG_LOW_PROFILE : 0) - | (mFullscreen ? View.SYSTEM_UI_FLAG_FULLSCREEN : 0), - View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_FULLSCREEN); - getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes()); - } catch (Throwable t) { - Slog.w("Crashed adding window view", t); - safelyFinish(); - return; - } + if (mDebug) Slog.v(TAG, "Window added on thread " + Thread.currentThread().getId()); + try { + applySystemUiVisibilityFlags( + (mLowProfile ? View.SYSTEM_UI_FLAG_LOW_PROFILE : 0), + View.SYSTEM_UI_FLAG_LOW_PROFILE); + getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes()); + } catch (Throwable t) { + Slog.w("Crashed adding window view", t); + safelyFinish(); + return; + } - // start it up - try { - onStart(); - } catch (Throwable t) { - Slog.w("Crashed in onStart()", t); - safelyFinish(); - } - }}); + // start it up + try { + onDreamingStarted(); + } catch (Throwable t) { + Slog.w("Crashed in onDreamingStarted()", t); + safelyFinish(); + } } private void safelyFinish() { - if (DEBUG) Slog.v(TAG, "safelyFinish()"); + if (mDebug) Slog.v(TAG, "safelyFinish()"); try { finish(); } catch (Throwable t) { @@ -570,7 +634,7 @@ public class DreamService extends Service implements Window.Callback { } private void finishInternal() { - if (DEBUG) Slog.v(TAG, "finishInternal() mFinished = " + mFinished); + if (mDebug) Slog.v(TAG, "finishInternal() mFinished = " + mFinished); if (mFinished) return; try { mFinished = true; @@ -616,9 +680,41 @@ public class DreamService extends Service implements Window.Callback { return (oldFlags&~mask) | (flags&mask); } + @Override + protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + super.dump(fd, pw, args); + + pw.print(TAG + ": "); + if (mWindowToken == null) { + pw.println("stopped"); + } else { + pw.println("running (token=" + mWindowToken + ")"); + } + pw.println(" window: " + mWindow); + pw.print(" flags:"); + if (isInteractive()) pw.print(" interactive"); + if (isLowProfile()) pw.print(" lowprofile"); + if (isFullscreen()) pw.print(" fullscreen"); + if (isScreenBright()) pw.print(" bright"); + pw.println(); + } + private class DreamServiceWrapper extends IDreamService.Stub { - public void attach(IBinder windowToken) { - DreamService.this.attach(windowToken); + public void attach(final IBinder windowToken) { + mHandler.post(new Runnable() { + @Override + public void run() { + DreamService.this.attach(windowToken); + } + }); + } + public void detach() { + mHandler.post(new Runnable() { + @Override + public void run() { + DreamService.this.detach(); + } + }); } } diff --git a/core/java/android/service/dreams/IDreamService.aidl b/core/java/android/service/dreams/IDreamService.aidl index 1bb241a..99dc0b7 100644 --- a/core/java/android/service/dreams/IDreamService.aidl +++ b/core/java/android/service/dreams/IDreamService.aidl @@ -21,4 +21,5 @@ package android.service.dreams; */ oneway interface IDreamService { void attach(IBinder windowToken); + void detach(); } diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 86bbc55..6d5705d 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -574,7 +574,8 @@ public abstract class WallpaperService extends Service { final boolean flagsChanged = mCurWindowFlags != mWindowFlags || mCurWindowPrivateFlags != mWindowPrivateFlags; if (forceRelayout || creating || surfaceCreating || formatChanged || sizeChanged - || typeChanged || flagsChanged || redrawNeeded) { + || typeChanged || flagsChanged || redrawNeeded + || !mIWallpaperEngine.mShownReported) { if (DEBUG) Log.v(TAG, "Changes: creating=" + creating + " format=" + formatChanged + " size=" + sizeChanged); @@ -739,6 +740,7 @@ public abstract class WallpaperService extends Service { if (redrawNeeded) { mSession.finishDrawing(mWindow); } + mIWallpaperEngine.reportShown(); } } catch (RemoteException ex) { } @@ -950,6 +952,7 @@ public abstract class WallpaperService extends Service { final IBinder mWindowToken; final int mWindowType; final boolean mIsPreview; + boolean mShownReported; int mReqWidth; int mReqHeight; @@ -1002,6 +1005,18 @@ public abstract class WallpaperService extends Service { } } + public void reportShown() { + if (!mShownReported) { + mShownReported = true; + try { + mConnection.engineShown(this); + } catch (RemoteException e) { + Log.w(TAG, "Wallpaper host disappeared", e); + return; + } + } + } + public void destroy() { Message msg = mCaller.obtainMessage(DO_DETACH); mCaller.sendMessage(msg); @@ -1020,12 +1035,6 @@ public abstract class WallpaperService extends Service { mEngine = engine; mActiveEngines.add(engine); engine.attach(this); - try { - mConnection.engineShown(this); - } catch (RemoteException e) { - Log.w(TAG, "Wallpaper host disappeared", e); - return; - } return; } case DO_DETACH: { diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java index fe05634..fb04150 100644 --- a/core/java/android/view/DisplayInfo.java +++ b/core/java/android/view/DisplayInfo.java @@ -233,7 +233,7 @@ public final class DisplayInfo implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(layerStack); - dest.writeInt(flags); + dest.writeInt(this.flags); dest.writeString(name); dest.writeInt(appWidth); dest.writeInt(appHeight); diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index a64cbf7..5f598b1 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -24,6 +24,7 @@ import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.Point; import android.graphics.Rect; +import android.os.Bundle; import android.os.IRemoteCallback; import android.view.IApplicationToken; import android.view.IDisplayContentChangeListener; @@ -74,7 +75,7 @@ interface IWindowManager void addWindowToken(IBinder token, int type); void removeWindowToken(IBinder token); void addAppToken(int addPos, IApplicationToken token, - int groupId, int requestedOrientation, boolean fullscreen); + int groupId, int requestedOrientation, boolean fullscreen, boolean showWhenLocked); void setAppGroupId(IBinder token, int groupId); void setAppOrientation(IApplicationToken token, int requestedOrientation); int getAppOrientation(IApplicationToken token); @@ -200,8 +201,9 @@ interface IWindowManager /** * Block until the given window has been drawn to the screen. + * Returns true if really waiting, false if the window does not exist. */ - void waitForWindowDrawn(IBinder token, in IRemoteCallback callback); + boolean waitForWindowDrawn(IBinder token, in IRemoteCallback callback); /** * Device has a software navigation bar (separate from the status bar). @@ -209,9 +211,9 @@ interface IWindowManager boolean hasNavigationBar(); /** - * Lock the device immediately. + * Lock the device immediately with the specified options (can be null). */ - void lockNow(); + void lockNow(in Bundle options); /** * Gets the token for the focused window. diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java index 876b7d84..230f426 100644 --- a/core/java/android/view/TextureView.java +++ b/core/java/android/view/TextureView.java @@ -189,7 +189,7 @@ public class TextureView extends View { if (opaque != mOpaque) { mOpaque = opaque; if (mLayer != null) { - updateLayer(); + updateLayerAndInvalidate(); } } } @@ -224,6 +224,8 @@ public class TextureView extends View { private void destroySurface() { if (mLayer != null) { mSurface.detachFromGLContext(); + // SurfaceTexture owns the texture name and detachFromGLContext + // should have deleted it mLayer.clearStorage(); boolean shouldRelease = true; @@ -291,6 +293,9 @@ public class TextureView extends View { */ @Override public final void draw(Canvas canvas) { + // NOTE: Maintain this carefully (see View.java) + mPrivateFlags = (mPrivateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN; + applyUpdate(); applyTransformMatrix(); } @@ -310,6 +315,7 @@ public class TextureView extends View { super.onSizeChanged(w, h, oldw, oldh); if (mSurface != null) { nSetDefaultBufferSize(mSurface, getWidth(), getHeight()); + updateLayer(); if (mListener != null) { mListener.onSurfaceTextureSizeChanged(mSurface, getWidth(), getHeight()); } @@ -334,6 +340,10 @@ public class TextureView extends View { @Override HardwareLayer getHardwareLayer() { + // NOTE: Maintain these two lines very carefully (see View.java) + mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID; + mPrivateFlags &= ~PFLAG_DIRTY_MASK; + if (mLayer == null) { if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) { return null; @@ -352,9 +362,7 @@ public class TextureView extends View { public void onFrameAvailable(SurfaceTexture surfaceTexture) { // Per SurfaceTexture's documentation, the callback may be invoked // from an arbitrary thread - synchronized (mLock) { - mUpdateLayer = true; - } + updateLayer(); if (Looper.myLooper() == Looper.getMainLooper()) { invalidate(); @@ -379,9 +387,7 @@ public class TextureView extends View { // Since we are updating the layer, force an update to ensure its // parameters are correct (width, height, transform, etc.) - synchronized (mLock) { - mUpdateLayer = true; - } + updateLayer(); mMatrixChanged = true; mAttachInfo.mHardwareRenderer.setSurfaceTexture(mLayer, mSurface); @@ -404,7 +410,7 @@ public class TextureView extends View { // updates listener if (visibility == VISIBLE) { mSurface.setOnFrameAvailableListener(mUpdateListener); - updateLayer(); + updateLayerAndInvalidate(); } else { mSurface.setOnFrameAvailableListener(null); } @@ -412,7 +418,15 @@ public class TextureView extends View { } private void updateLayer() { - mUpdateLayer = true; + synchronized (mLock) { + mUpdateLayer = true; + } + } + + private void updateLayerAndInvalidate() { + synchronized (mLock) { + mUpdateLayer = true; + } invalidate(); } @@ -768,6 +782,7 @@ public class TextureView extends View { * Invoked when the specified {@link SurfaceTexture} is about to be destroyed. * If returns true, no rendering should happen inside the surface texture after this method * is invoked. If returns false, the client needs to call {@link SurfaceTexture#release()}. + * Most applications should return true. * * @param surface The surface about to be destroyed */ diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index be2d5b3..0475283 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -2322,7 +2322,13 @@ public final class ViewRootImpl implements ViewParent, mAccessibilityFocusedHost.getDrawingRect(bounds); if (mView instanceof ViewGroup) { ViewGroup viewGroup = (ViewGroup) mView; - viewGroup.offsetDescendantRectToMyCoords(mAccessibilityFocusedHost, bounds); + try { + viewGroup.offsetDescendantRectToMyCoords(mAccessibilityFocusedHost, bounds); + } catch (IllegalArgumentException iae) { + Log.e(TAG, "Temporary detached view that was neither removed not reattached: " + + mAccessibilityFocusedHost); + return; + } } } else { if (mAccessibilityFocusedVirtualView == null) { diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 6e51270..4c97414 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -219,12 +219,14 @@ public interface WindowManager extends ViewManager { * Window type: an application window that serves as the "base" window * of the overall application; all other application windows will * appear on top of it. + * In multiuser systems shows only on the owning user's window. */ public static final int TYPE_BASE_APPLICATION = 1; /** * Window type: a normal application window. The {@link #token} must be * an Activity token identifying who the window belongs to. + * In multiuser systems shows only on the owning user's window. */ public static final int TYPE_APPLICATION = 2; @@ -233,6 +235,7 @@ public interface WindowManager extends ViewManager { * application is starting. Not for use by applications themselves; * this is used by the system to display something until the * application can show its own windows. + * In multiuser systems shows on all users' windows. */ public static final int TYPE_APPLICATION_STARTING = 3; @@ -298,12 +301,14 @@ public interface WindowManager extends ViewManager { * Window type: the status bar. There can be only one status bar * window; it is placed at the top of the screen, and all other * windows are shifted down so they are below it. + * In multiuser systems shows on all users' windows. */ public static final int TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW; /** * Window type: the search bar. There can be only one search bar * window; it is placed at the top of the screen. + * In multiuser systems shows on all users' windows. */ public static final int TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1; @@ -312,22 +317,26 @@ public interface WindowManager extends ViewManager { * user interaction with the phone (in particular incoming calls). * These windows are normally placed above all applications, but behind * the status bar. + * In multiuser systems shows on all users' windows. */ public static final int TYPE_PHONE = FIRST_SYSTEM_WINDOW+2; /** * Window type: system window, such as low power alert. These windows * are always on top of application windows. + * In multiuser systems shows only on the owning user's window. */ public static final int TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3; /** * Window type: keyguard window. + * In multiuser systems shows on all users' windows. */ public static final int TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4; /** * Window type: transient notifications. + * In multiuser systems shows only on the owning user's window. */ public static final int TYPE_TOAST = FIRST_SYSTEM_WINDOW+5; @@ -335,6 +344,7 @@ public interface WindowManager extends ViewManager { * Window type: system overlay windows, which need to be displayed * on top of everything else. These windows must not take input * focus, or they will interfere with the keyguard. + * In multiuser systems shows only on the owning user's window. */ public static final int TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6; @@ -342,22 +352,26 @@ public interface WindowManager extends ViewManager { * Window type: priority phone UI, which needs to be displayed even if * the keyguard is active. These windows must not take input * focus, or they will interfere with the keyguard. + * In multiuser systems shows on all users' windows. */ public static final int TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7; /** * Window type: panel that slides out from the status bar + * In multiuser systems shows on all users' windows. */ public static final int TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW+8; /** * Window type: dialogs that the keyguard shows + * In multiuser systems shows on all users' windows. */ public static final int TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW+9; /** * Window type: internal system error windows, appear on top of * everything they can. + * In multiuser systems shows only on the owning user's window. */ public static final int TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW+10; @@ -365,23 +379,27 @@ public interface WindowManager extends ViewManager { * Window type: internal input methods windows, which appear above * the normal UI. Application windows may be resized or panned to keep * the input focus visible while this window is displayed. + * In multiuser systems shows only on the owning user's window. */ public static final int TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11; /** * Window type: internal input methods dialog windows, which appear above * the current input method window. + * In multiuser systems shows only on the owning user's window. */ public static final int TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12; /** * Window type: wallpaper window, placed behind any window that wants * to sit on top of the wallpaper. + * In multiuser systems shows only on the owning user's window. */ public static final int TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13; /** * Window type: panel that slides out from over the status bar + * In multiuser systems shows on all users' windows. */ public static final int TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+14; @@ -393,6 +411,8 @@ public interface WindowManager extends ViewManager { * This is exactly like {@link #TYPE_SYSTEM_OVERLAY} except that only the * system itself is allowed to create these overlays. Applications cannot * obtain permission to create secure system overlays. + * + * In multiuser systems shows only on the owning user's window. * @hide */ public static final int TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15; @@ -400,24 +420,28 @@ public interface WindowManager extends ViewManager { /** * Window type: the drag-and-drop pseudowindow. There is only one * drag layer (at most), and it is placed on top of all other windows. + * In multiuser systems shows only on the owning user's window. * @hide */ public static final int TYPE_DRAG = FIRST_SYSTEM_WINDOW+16; /** * Window type: panel that slides out from under the status bar + * In multiuser systems shows on all users' windows. * @hide */ public static final int TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW+17; /** * Window type: (mouse) pointer + * In multiuser systems shows on all users' windows. * @hide */ public static final int TYPE_POINTER = FIRST_SYSTEM_WINDOW+18; /** * Window type: Navigation bar (when distinct from status bar) + * In multiuser systems shows on all users' windows. * @hide */ public static final int TYPE_NAVIGATION_BAR = FIRST_SYSTEM_WINDOW+19; @@ -425,6 +449,7 @@ public interface WindowManager extends ViewManager { /** * Window type: The volume level overlay/dialog shown when the user * changes the system volume. + * In multiuser systems shows on all users' windows. * @hide */ public static final int TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW+20; @@ -432,6 +457,7 @@ public interface WindowManager extends ViewManager { /** * Window type: The boot progress dialog, goes on top of everything * in the world. + * In multiuser systems shows on all users' windows. * @hide */ public static final int TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW+21; @@ -439,30 +465,35 @@ public interface WindowManager extends ViewManager { /** * Window type: Fake window to consume touch events when the navigation * bar is hidden. + * In multiuser systems shows on all users' windows. * @hide */ public static final int TYPE_HIDDEN_NAV_CONSUMER = FIRST_SYSTEM_WINDOW+22; /** * Window type: Dreams (screen saver) window, just above keyguard. + * In multiuser systems shows only on the owning user's window. * @hide */ public static final int TYPE_DREAM = FIRST_SYSTEM_WINDOW+23; /** * Window type: Navigation bar panel (when navigation bar is distinct from status bar) + * In multiuser systems shows on all users' windows. * @hide */ public static final int TYPE_NAVIGATION_BAR_PANEL = FIRST_SYSTEM_WINDOW+24; /** * Window type: Behind the universe of the real windows. + * In multiuser systems shows on all users' windows. * @hide */ public static final int TYPE_UNIVERSE_BACKGROUND = FIRST_SYSTEM_WINDOW+25; /** * Window type: Display overlay window. Used to simulate secondary display devices. + * In multiuser systems shows on all users' windows. * @hide */ public static final int TYPE_DISPLAY_OVERLAY = FIRST_SYSTEM_WINDOW+26; @@ -470,11 +501,20 @@ public interface WindowManager extends ViewManager { /** * Window type: Magnification overlay window. Used to highlight the magnified * portion of a display when accessibility magnification is enabled. + * In multiuser systems shows on all users' windows. * @hide */ public static final int TYPE_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW+27; /** + * Window type: Recents. Same layer as {@link #TYPE_SYSTEM_DIALOG} but only appears on + * one user's screen. + * In multiuser systems shows on all users' windows. + * @hide + */ + public static final int TYPE_RECENTS_OVERLAY = FIRST_SYSTEM_WINDOW+28; + + /** * End of types of system windows. */ public static final int LAST_SYSTEM_WINDOW = 2999; @@ -879,6 +919,14 @@ public interface WindowManager extends ViewManager { */ public static final int PRIVATE_FLAG_SET_NEEDS_MENU_KEY = 0x00000008; + /** In a multiuser system if this flag is set and the owner is a system process then this + * window will appear on all user screens. This overrides the default behavior of window + * types that normally only appear on the owning user's screen. Refer to each window type + * to determine its default behavior. + * + * {@hide} */ + public static final int PRIVATE_FLAG_SHOW_FOR_ALL_USERS = 0x00000010; + /** * Control flags that are private to the platform. * @hide diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index 82f07c7..4ccb502 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -21,6 +21,7 @@ import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.graphics.Rect; import android.graphics.RectF; +import android.os.Bundle; import android.os.IBinder; import android.os.Looper; import android.view.animation.Animation; @@ -500,6 +501,16 @@ public interface WindowManagerPolicy { public int checkAddPermission(WindowManager.LayoutParams attrs); /** + * Check permissions when adding a window. + * + * @param attrs The window's LayoutParams. + * + * @return True if the window may only be shown to the current user, false if the window can + * be shown on all users' windows. + */ + public boolean checkShowToOwnerOnly(WindowManager.LayoutParams attrs); + + /** * Sanitize the layout parameters coming from a client. Allows the policy * to do things like ensure that windows of a specific type can't take * input focus. @@ -1057,18 +1068,13 @@ public interface WindowManagerPolicy { * Called when we have started keeping the screen on because a window * requesting this has become visible. */ - public void screenOnStartedLw(); + public void keepScreenOnStartedLw(); /** * Called when we have stopped keeping the screen on because the last window * requesting this is no longer visible. */ - public void screenOnStoppedLw(); - - /** - * Return false to disable key repeat events from being generated. - */ - public boolean allowKeyRepeat(); + public void keepScreenOnStoppedLw(); /** * Inform the policy that the user has chosen a preferred orientation ("rotation lock"). @@ -1096,7 +1102,7 @@ public interface WindowManagerPolicy { /** * Lock the device now. */ - public void lockNow(); + public void lockNow(Bundle options); /** * Set the last used input method window state. This state is used to make IME transition diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 871f752..33a8531 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -1077,8 +1077,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te checkedStateChanged = true; } else if (mChoiceMode == CHOICE_MODE_SINGLE) { boolean checked = !mCheckStates.get(position, false); - mCheckStates.clear(); if (checked) { + mCheckStates.clear(); mCheckStates.put(position, true); if (mCheckedIdStates != null && mAdapter.hasStableIds()) { mCheckedIdStates.clear(); diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index 4ad0819..e63c57f 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -150,8 +150,7 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte resizeGrid(); } else if (count == 1) { - startActivityAsUser(mAdapter.intentForPosition(0), - new UserHandle(UserHandle.getUserId(mLaunchedFromUid))); + startActivity(mAdapter.intentForPosition(0)); mPackageMonitor.unregister(); mRegistered = false; finish(); @@ -364,12 +363,12 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte if (r.match > bestMatch) bestMatch = r.match; } getPackageManager().addPreferredActivity(filter, bestMatch, set, - intent.getComponent(), UserHandle.getUserId(mLaunchedFromUid)); + intent.getComponent()); } } if (intent != null) { - startActivityAsUser(intent, new UserHandle(UserHandle.getUserId(mLaunchedFromUid))); + startActivity(intent); } } @@ -377,7 +376,7 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte Intent in = new Intent().setAction("android.settings.APPLICATION_DETAILS_SETTINGS") .setData(Uri.fromParts("package", ri.activityInfo.packageName, null)) .addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); - startActivityAsUser(in, new UserHandle(UserHandle.getUserId(mLaunchedFromUid))); + startActivity(in); } private final class DisplayResolveInfo { @@ -436,10 +435,9 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte if (mBaseResolveList != null) { mCurrentResolveList = mBaseResolveList; } else { - mCurrentResolveList = mPm.queryIntentActivitiesAsUser( + mCurrentResolveList = mPm.queryIntentActivities( mIntent, PackageManager.MATCH_DEFAULT_ONLY - | (mAlwaysUseOption ? PackageManager.GET_RESOLVED_FILTER : 0), - UserHandle.getUserId(mLaunchedFromUid)); + | (mAlwaysUseOption ? PackageManager.GET_RESOLVED_FILTER : 0)); // Filter out any activities that the launched uid does not // have permission for. We don't do this when we have an explicit // list of resolved activities, because that only happens when diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index f987fc5..d14b1ee 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -27,6 +27,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Binder; +import android.os.Bundle; import android.os.IBinder; import android.os.Process; import android.os.RemoteException; @@ -99,6 +100,26 @@ public class LockPatternUtils { public static final int MIN_PATTERN_REGISTER_FAIL = MIN_LOCK_PATTERN_SIZE; /** + * Tells the keyguard to show the user switcher when the keyguard is created. + */ + public static final String KEYGUARD_SHOW_USER_SWITCHER = "showuserswitcher"; + + /** + * Tells the keyguard to show the security challenge when the keyguard is created. + */ + public static final String KEYGUARD_SHOW_SECURITY_CHALLENGE = "showsecuritychallenge"; + + /** + * Options used to lock the device upon user switch. + */ + public static final Bundle USER_SWITCH_LOCK_OPTIONS = new Bundle(); + + static { + USER_SWITCH_LOCK_OPTIONS.putBoolean(KEYGUARD_SHOW_USER_SWITCHER, true); + USER_SWITCH_LOCK_OPTIONS.putBoolean(KEYGUARD_SHOW_SECURITY_CHALLENGE, true); + } + + /** * The bit in LOCK_BIOMETRIC_WEAK_FLAGS to be used to indicate whether liveliness should * be used */ |