diff options
Diffstat (limited to 'core/java')
50 files changed, 1117 insertions, 214 deletions
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java index 4d34349..72f8c77 100644 --- a/core/java/android/app/ActionBar.java +++ b/core/java/android/app/ActionBar.java @@ -1057,6 +1057,11 @@ public abstract class ActionBar { } /** @hide */ + public boolean onKeyShortcut(int keyCode, KeyEvent event) { + return false; + } + + /** @hide */ public boolean collapseActionView() { return false; } diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index d07238a..e782fb8 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -2469,7 +2469,9 @@ public class Activity extends ContextThemeWrapper * @return True if the key shortcut was handled. */ public boolean onKeyShortcut(int keyCode, KeyEvent event) { - return false; + // Let the Action Bar have a chance at handling the shortcut. + ActionBar actionBar = getActionBar(); + return (actionBar != null && actionBar.onKeyShortcut(keyCode, event)); } /** @@ -3769,6 +3771,11 @@ public class Activity extends ContextThemeWrapper /** * Callback for the result from requesting permissions. This method * is invoked for every call on {@link #requestPermissions(String[], int)}. + * <p> + * <strong>Note:</strong> It is possible that the permissions request interaction + * with the user is interrupted. In this case you will receive empty permissions + * and results arrays which should be treated as a cancellation. + * </p> * * @param requestCode The request code passed in {@link #requestPermissions(String[], int)}. * @param permissions The requested permissions. Never null. @@ -3975,16 +3982,24 @@ public class Activity extends ContextThemeWrapper * as intermediaries that dispatch their intent to the target the user selects -- to * do this, they must perform all security checks including permission grants as if * their launch had come from the original activity. + * @param intent The Intent to start. + * @param options ActivityOptions or null. + * @param ignoreTargetSecurity If true, the activity manager will not check whether the + * caller it is doing the start is, is actually allowed to start the target activity. + * If you set this to true, you must set an explicit component in the Intent and do any + * appropriate security checks yourself. + * @param userId The user the new activity should run as. * @hide */ - public void startActivityAsCaller(Intent intent, @Nullable Bundle options, int userId) { + public void startActivityAsCaller(Intent intent, @Nullable Bundle options, + boolean ignoreTargetSecurity, int userId) { if (mParent != null) { throw new RuntimeException("Can't be called from a child"); } Instrumentation.ActivityResult ar = mInstrumentation.execStartActivityAsCaller( this, mMainThread.getApplicationThread(), mToken, this, - intent, -1, options, userId); + intent, -1, options, ignoreTargetSecurity, userId); if (ar != null) { mMainThread.sendActivityResult( mToken, mEmbeddedID, -1, ar.getResultCode(), diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index cc93ac9..bfb92c4 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -206,9 +206,11 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM ? ProfilerInfo.CREATOR.createFromParcel(data) : null; Bundle options = data.readInt() != 0 ? Bundle.CREATOR.createFromParcel(data) : null; + boolean ignoreTargetSecurity = data.readInt() != 0; int userId = data.readInt(); int result = startActivityAsCaller(app, callingPackage, intent, resolvedType, - resultTo, resultWho, requestCode, startFlags, profilerInfo, options, userId); + resultTo, resultWho, requestCode, startFlags, profilerInfo, options, + ignoreTargetSecurity, userId); reply.writeNoException(); reply.writeInt(result); return true; @@ -456,14 +458,14 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM int resultCode = data.readInt(); String resultData = data.readString(); Bundle resultExtras = data.readBundle(); - String perm = data.readString(); + String[] perms = data.readStringArray(); int appOp = data.readInt(); Bundle options = data.readBundle(); boolean serialized = data.readInt() != 0; boolean sticky = data.readInt() != 0; int userId = data.readInt(); int res = broadcastIntent(app, intent, resolvedType, resultTo, - resultCode, resultData, resultExtras, perm, appOp, + resultCode, resultData, resultExtras, perms, appOp, options, serialized, sticky, userId); reply.writeNoException(); reply.writeInt(res); @@ -2675,7 +2677,8 @@ class ActivityManagerProxy implements IActivityManager } public int startActivityAsCaller(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, - int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) throws RemoteException { + int startFlags, ProfilerInfo profilerInfo, Bundle options, boolean ignoreTargetSecurity, + int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); @@ -2699,6 +2702,7 @@ class ActivityManagerProxy implements IActivityManager } else { data.writeInt(0); } + data.writeInt(ignoreTargetSecurity ? 1 : 0); data.writeInt(userId); mRemote.transact(START_ACTIVITY_AS_CALLER_TRANSACTION, data, reply, 0); reply.readException(); @@ -3007,7 +3011,7 @@ class ActivityManagerProxy implements IActivityManager public int broadcastIntent(IApplicationThread caller, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle map, - String requiredPermission, int appOp, Bundle options, boolean serialized, + String[] requiredPermissions, int appOp, Bundle options, boolean serialized, boolean sticky, int userId) throws RemoteException { Parcel data = Parcel.obtain(); @@ -3020,7 +3024,7 @@ class ActivityManagerProxy implements IActivityManager data.writeInt(resultCode); data.writeString(resultData); data.writeBundle(map); - data.writeString(requiredPermission); + data.writeStringArray(requiredPermissions); data.writeInt(appOp); data.writeBundle(options); data.writeInt(serialized ? 1 : 0); diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java index fa81412..e28fb20 100644 --- a/core/java/android/app/ActivityTransitionCoordinator.java +++ b/core/java/android/app/ActivityTransitionCoordinator.java @@ -217,11 +217,6 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { } protected void viewsReady(ArrayMap<String, View> sharedElements) { - final View decor = getDecor(); - final ViewRootImpl viewRoot = decor == null ? null : decor.getViewRootImpl(); - if (viewRoot != null) { - viewRoot.setPausedForTransition(true); - } sharedElements.retainAll(mAllSharedElementNames); if (mListener != null) { mListener.onMapSharedElements(mAllSharedElementNames, sharedElements); @@ -905,6 +900,14 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { } } + protected void pauseInput() { + final View decor = getDecor(); + final ViewRootImpl viewRoot = decor == null ? null : decor.getViewRootImpl(); + if (viewRoot != null) { + viewRoot.setPausedForTransition(true); + } + } + protected void onTransitionsComplete() {} protected class ContinueTransitionListener extends Transition.TransitionListenerAdapter { diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index bf3bfae..08e1696 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -233,8 +233,10 @@ public class AppOpsManager { public static final int OP_READ_EXTERNAL_STORAGE = 59; /** @hide Write external storage. */ public static final int OP_WRITE_EXTERNAL_STORAGE = 60; + /** @hide Turned on the screen. */ + public static final int OP_TURN_SCREEN_ON = 61; /** @hide */ - public static final int _NUM_OP = 61; + public static final int _NUM_OP = 62; /** Access to coarse location information. */ public static final String OPSTR_COARSE_LOCATION = "android:coarse_location"; @@ -393,7 +395,8 @@ public class AppOpsManager { OP_READ_CELL_BROADCASTS, OP_MOCK_LOCATION, OP_READ_EXTERNAL_STORAGE, - OP_WRITE_EXTERNAL_STORAGE + OP_WRITE_EXTERNAL_STORAGE, + OP_TURN_SCREEN_ON, }; /** @@ -461,7 +464,8 @@ public class AppOpsManager { OPSTR_READ_CELL_BROADCASTS, OPSTR_MOCK_LOCATION, OPSTR_READ_EXTERNAL_STORAGE, - OPSTR_WRITE_EXTERNAL_STORAGE + OPSTR_WRITE_EXTERNAL_STORAGE, + null, }; /** @@ -528,8 +532,9 @@ public class AppOpsManager { "BODY_SENSORS", "READ_CELL_BROADCASTS", "MOCK_LOCATION", - "OPSTR_READ_EXTERNAL_STORAGE", - "OPSTR_WRITE_EXTERNAL_STORAGE", + "READ_EXTERNAL_STORAGE", + "WRITE_EXTERNAL_STORAGE", + "TURN_ON_SCREEN", }; /** @@ -598,6 +603,7 @@ public class AppOpsManager { null, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, + null, // no permission for turning the screen on }; /** @@ -666,7 +672,8 @@ public class AppOpsManager { null, // READ_CELL_BROADCASTS null, // MOCK_LOCATION null, // READ_EXTERNAL_STORAGE - null // WRITE_EXTERNAL_STORAGE + null, // WRITE_EXTERNAL_STORAGE + null, // TURN_ON_SCREEN }; /** @@ -734,7 +741,8 @@ public class AppOpsManager { false, // READ_CELL_BROADCASTS false, // MOCK_LOCATION false, // READ_EXTERNAL_STORAGE - false // WRITE_EXTERNAL_STORAGE + false, // WRITE_EXTERNAL_STORAGE + false, // TURN_ON_SCREEN }; /** @@ -765,7 +773,7 @@ public class AppOpsManager { AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, - AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_DEFAULT, // OP_SYSTEM_ALERT_WINDOW AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, @@ -801,7 +809,8 @@ public class AppOpsManager { AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ERRORED, // OP_MOCK_LOCATION AppOpsManager.MODE_ALLOWED, - AppOpsManager.MODE_ALLOWED + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, // OP_TURN_ON_SCREEN }; /** @@ -872,7 +881,8 @@ public class AppOpsManager { false, false, false, - false + false, + false, }; /** diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 75dd35c..235f294 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -180,7 +180,7 @@ class ContextImpl extends Context { @GuardedBy("mSync") private File[] mExternalMediaDirs; - private static final String[] EMPTY_FILE_LIST = {}; + private static final String[] EMPTY_STRING_ARRAY = {}; // The system service cache for the system services that are cached per-ContextImpl. final Object[] mServiceCache = SystemServiceRegistry.createServiceCache(); @@ -552,7 +552,7 @@ class ContextImpl extends Context { @Override public String[] fileList() { final String[] list = getFilesDir().list(); - return (list != null) ? list : EMPTY_FILE_LIST; + return (list != null) ? list : EMPTY_STRING_ARRAY; } @Override @@ -591,7 +591,7 @@ class ContextImpl extends Context { @Override public String[] databaseList() { final String[] list = getDatabasesDir().list(); - return (list != null) ? list : EMPTY_FILE_LIST; + return (list != null) ? list : EMPTY_STRING_ARRAY; } @@ -777,11 +777,28 @@ class ContextImpl extends Context { public void sendBroadcast(Intent intent, String receiverPermission) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); + String[] receiverPermissions = receiverPermission == null ? null + : new String[] {receiverPermission}; try { intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, - Activity.RESULT_OK, null, null, receiverPermission, AppOpsManager.OP_NONE, + Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE, + null, false, false, getUserId()); + } catch (RemoteException e) { + throw new RuntimeException("Failure from system", e); + } + } + + @Override + public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions) { + warnIfCallingFromSystemProcess(); + String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); + try { + intent.prepareToLeaveProcess(); + ActivityManagerNative.getDefault().broadcastIntent( + mMainThread.getApplicationThread(), intent, resolvedType, null, + Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE, null, false, false, getUserId()); } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); @@ -792,11 +809,13 @@ class ContextImpl extends Context { public void sendBroadcast(Intent intent, String receiverPermission, Bundle options) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); + String[] receiverPermissions = receiverPermission == null ? null + : new String[] {receiverPermission}; try { intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, - Activity.RESULT_OK, null, null, receiverPermission, AppOpsManager.OP_NONE, + Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE, options, false, false, getUserId()); } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); @@ -807,11 +826,13 @@ class ContextImpl extends Context { public void sendBroadcast(Intent intent, String receiverPermission, int appOp) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); + String[] receiverPermissions = receiverPermission == null ? null + : new String[] {receiverPermission}; try { intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, - Activity.RESULT_OK, null, null, receiverPermission, appOp, null, false, false, + Activity.RESULT_OK, null, null, receiverPermissions, appOp, null, false, false, getUserId()); } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); @@ -822,11 +843,13 @@ class ContextImpl extends Context { public void sendOrderedBroadcast(Intent intent, String receiverPermission) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); + String[] receiverPermissions = receiverPermission == null ? null + : new String[] {receiverPermission}; try { intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, - Activity.RESULT_OK, null, null, receiverPermission, AppOpsManager.OP_NONE, + Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE, null, true, false, getUserId()); } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); @@ -883,11 +906,13 @@ class ContextImpl extends Context { } } String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); + String[] receiverPermissions = receiverPermission == null ? null + : new String[] {receiverPermission}; try { intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, rd, - initialCode, initialData, initialExtras, receiverPermission, appOp, + initialCode, initialData, initialExtras, receiverPermissions, appOp, options, true, false, getUserId()); } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); @@ -917,11 +942,13 @@ class ContextImpl extends Context { public void sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, int appOp) { String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); + String[] receiverPermissions = receiverPermission == null ? null + : new String[] {receiverPermission}; try { intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, - Activity.RESULT_OK, null, null, receiverPermission, appOp, null, false, false, + Activity.RESULT_OK, null, null, receiverPermissions, appOp, null, false, false, user.getIdentifier()); } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); @@ -933,14 +960,21 @@ class ContextImpl extends Context { String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { sendOrderedBroadcastAsUser(intent, user, receiverPermission, AppOpsManager.OP_NONE, - resultReceiver, scheduler, initialCode, initialData, initialExtras); + null, resultReceiver, scheduler, initialCode, initialData, initialExtras); } @Override public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, int appOp, BroadcastReceiver resultReceiver, - Handler scheduler, - int initialCode, String initialData, Bundle initialExtras) { + Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { + sendOrderedBroadcastAsUser(intent, user, receiverPermission, appOp, + null, resultReceiver, scheduler, initialCode, initialData, initialExtras); + } + + @Override + public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, + String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver, + Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { IIntentReceiver rd = null; if (resultReceiver != null) { if (mPackageInfo != null) { @@ -954,17 +988,19 @@ class ContextImpl extends Context { if (scheduler == null) { scheduler = mMainThread.getHandler(); } - rd = new LoadedApk.ReceiverDispatcher( - resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver(); + rd = new LoadedApk.ReceiverDispatcher(resultReceiver, getOuterContext(), + scheduler, null, false).getIIntentReceiver(); } } String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); + String[] receiverPermissions = receiverPermission == null ? null + : new String[] {receiverPermission}; try { intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, rd, - initialCode, initialData, initialExtras, receiverPermission, - appOp, null, true, false, user.getIdentifier()); + initialCode, initialData, initialExtras, receiverPermissions, + appOp, options, true, false, user.getIdentifier()); } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); } diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java index 05cf1d4..0745537 100644 --- a/core/java/android/app/EnterTransitionCoordinator.java +++ b/core/java/android/app/EnterTransitionCoordinator.java @@ -333,6 +333,7 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { boolean startSharedElementTransition = true; setGhostVisibility(View.INVISIBLE); scheduleGhostVisibilityChange(View.INVISIBLE); + pauseInput(); Transition transition = beginTransition(decorView, startEnterTransition, startSharedElementTransition); scheduleGhostVisibilityChange(View.VISIBLE); diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java index 9ddebb0..7fbb99a 100644 --- a/core/java/android/app/ExitTransitionCoordinator.java +++ b/core/java/android/app/ExitTransitionCoordinator.java @@ -25,6 +25,7 @@ import android.graphics.Matrix; import android.graphics.RectF; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; +import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.Handler; import android.os.Message; @@ -203,6 +204,7 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator { public void startExit() { if (!mIsExitStarted) { mIsExitStarted = true; + pauseInput(); ViewGroup decorView = getDecor(); if (decorView != null) { decorView.suppressLayout(true); @@ -220,6 +222,7 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator { public void startExit(int resultCode, Intent data) { if (!mIsExitStarted) { mIsExitStarted = true; + pauseInput(); ViewGroup decorView = getDecor(); if (decorView != null) { decorView.suppressLayout(true); @@ -236,8 +239,12 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator { if (decorView != null && decorView.getBackground() == null) { getWindow().setBackgroundDrawable(new ColorDrawable(Color.BLACK)); } + final boolean targetsM = decorView == null || decorView.getContext() + .getApplicationInfo().targetSdkVersion >= VERSION_CODES.MNC; + ArrayList<String> sharedElementNames = targetsM ? mSharedElementNames : + mAllSharedElementNames; ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(mActivity, this, - mSharedElementNames, resultCode, data); + sharedElementNames, resultCode, data); mActivity.convertToTranslucent(new Activity.TranslucentConversionListener() { @Override public void onTranslucentConversionComplete(boolean drawComplete) { diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java index 5490fe7..82206ea 100644 --- a/core/java/android/app/Fragment.java +++ b/core/java/android/app/Fragment.java @@ -1213,6 +1213,11 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene /** * Callback for the result from requesting permissions. This method * is invoked for every call on {@link #requestPermissions(String[], int)}. + * <p> + * <strong>Note:</strong> It is possible that the permissions request interaction + * with the user is interrupted. In this case you will receive empty permissions + * and results arrays which should be treated as a cancellation. + * </p> * * @param requestCode The request code passed in {@link #requestPermissions(String[], int)}. * @param permissions The requested permissions. Never null. @@ -1249,7 +1254,8 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene */ public boolean shouldShowRequestPermissionRationale(@NonNull String permission) { if (mHost != null) { - mHost.getContext().getPackageManager().shouldShowRequestPermissionRationale(permission); + return mHost.getContext().getPackageManager() + .shouldShowRequestPermissionRationale(permission); } return false; } diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index acce81c..5eb3961 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -72,7 +72,8 @@ public interface IActivityManager extends IInterface { ProfilerInfo profilerInfo, Bundle options, int userId) throws RemoteException; public int startActivityAsCaller(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, - int flags, ProfilerInfo profilerInfo, Bundle options, int userId) throws RemoteException; + int flags, ProfilerInfo profilerInfo, Bundle options, boolean ignoreTargetSecurity, + int userId) throws RemoteException; public WaitResult startActivityAndWait(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int flags, ProfilerInfo profilerInfo, Bundle options, @@ -106,7 +107,7 @@ public interface IActivityManager extends IInterface { public void unregisterReceiver(IIntentReceiver receiver) throws RemoteException; public int broadcastIntent(IApplicationThread caller, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, - String resultData, Bundle map, String requiredPermission, + String resultData, Bundle map, String[] requiredPermissions, int appOp, Bundle options, boolean serialized, boolean sticky, int userId) throws RemoteException; public void unbroadcastIntent(IApplicationThread caller, Intent intent, int userId) throws RemoteException; public void finishReceiver(IBinder who, int resultCode, String resultData, Bundle map, diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index 653f1b6..c2d901d 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -1701,7 +1701,8 @@ public class Instrumentation { */ public ActivityResult execStartActivityAsCaller( Context who, IBinder contextThread, IBinder token, Activity target, - Intent intent, int requestCode, Bundle options, int userId) { + Intent intent, int requestCode, Bundle options, boolean ignoreTargetSecurity, + int userId) { IApplicationThread whoThread = (IApplicationThread) contextThread; if (mActivityMonitors != null) { synchronized (mSync) { @@ -1725,7 +1726,7 @@ public class Instrumentation { .startActivityAsCaller(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, - requestCode, 0, null, options, userId); + requestCode, 0, null, options, ignoreTargetSecurity, userId); checkStartActivityResult(result, intent); } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index c3dece8..b0d8541 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -166,8 +166,10 @@ public class Notification implements Parcelable /** * The resource id of a drawable to use as the icon in the status bar. - * This is required; notifications with an invalid icon resource will not be shown. + * + * @deprecated Use {@link Builder#setSmallIcon(Icon)} instead. */ + @Deprecated @DrawableRes public int icon; @@ -269,8 +271,11 @@ public class Notification implements Parcelable public RemoteViews headsUpContentView; /** - * The bitmap that may escape the bounds of the panel and bar. + * A large bitmap to be shown in the notification content area. + * + * @deprecated Use {@link Builder#setLargeIcon(Icon)} instead. */ + @Deprecated public Bitmap largeIcon; /** @@ -900,11 +905,15 @@ public class Notification implements Parcelable */ public static class Action implements Parcelable { private final Bundle mExtras; + private Icon mIcon; private final RemoteInput[] mRemoteInputs; /** * Small icon representing the action. + * + * @deprecated Use {@link Action#getIcon()} instead. */ + @Deprecated public int icon; /** @@ -919,7 +928,12 @@ public class Notification implements Parcelable public PendingIntent actionIntent; private Action(Parcel in) { - icon = in.readInt(); + if (in.readInt() != 0) { + mIcon = Icon.CREATOR.createFromParcel(in); + } + if (mIcon.getType() == Icon.TYPE_RESOURCE) { + icon = mIcon.getResId(); + } title = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); if (in.readInt() == 1) { actionIntent = PendingIntent.CREATOR.createFromParcel(in); @@ -929,15 +943,16 @@ public class Notification implements Parcelable } /** - * Use {@link Notification.Builder#addAction(int, CharSequence, PendingIntent)}. + * @deprecated Use {@link android.app.Notification.Action.Builder}. */ + @Deprecated public Action(int icon, CharSequence title, PendingIntent intent) { - this(icon, title, intent, new Bundle(), null); + this(Icon.createWithResource("", icon), title, intent, new Bundle(), null); } - private Action(int icon, CharSequence title, PendingIntent intent, Bundle extras, + private Action(Icon icon, CharSequence title, PendingIntent intent, Bundle extras, RemoteInput[] remoteInputs) { - this.icon = icon; + this.mIcon = icon; this.title = title; this.actionIntent = intent; this.mExtras = extras != null ? extras : new Bundle(); @@ -945,6 +960,17 @@ public class Notification implements Parcelable } /** + * Return an icon representing the action. + */ + public Icon getIcon() { + if (mIcon == null && icon != 0) { + // you snuck an icon in here without using the builder; let's try to keep it + mIcon = Icon.createWithResource("", icon); + } + return mIcon; + } + + /** * Get additional metadata carried around with this Action. */ public Bundle getExtras() { @@ -963,7 +989,7 @@ public class Notification implements Parcelable * Builder class for {@link Action} objects. */ public static final class Builder { - private final int mIcon; + private final Icon mIcon; private final CharSequence mTitle; private final PendingIntent mIntent; private final Bundle mExtras; @@ -975,7 +1001,18 @@ public class Notification implements Parcelable * @param title the title of the action * @param intent the {@link PendingIntent} to fire when users trigger this action */ + @Deprecated public Builder(int icon, CharSequence title, PendingIntent intent) { + this(Icon.createWithResource("", icon), title, intent, new Bundle(), null); + } + + /** + * Construct a new builder for {@link Action} object. + * @param icon icon to show for this action + * @param title the title of the action + * @param intent the {@link PendingIntent} to fire when users trigger this action + */ + public Builder(Icon icon, CharSequence title, PendingIntent intent) { this(icon, title, intent, new Bundle(), null); } @@ -985,11 +1022,11 @@ public class Notification implements Parcelable * @param action the action to read fields from. */ public Builder(Action action) { - this(action.icon, action.title, action.actionIntent, new Bundle(action.mExtras), + this(action.getIcon(), action.title, action.actionIntent, new Bundle(action.mExtras), action.getRemoteInputs()); } - private Builder(int icon, CharSequence title, PendingIntent intent, Bundle extras, + private Builder(Icon icon, CharSequence title, PendingIntent intent, Bundle extras, RemoteInput[] remoteInputs) { mIcon = icon; mTitle = title; @@ -1063,7 +1100,7 @@ public class Notification implements Parcelable @Override public Action clone() { return new Action( - icon, + getIcon(), title, actionIntent, // safe to alias new Bundle(mExtras), @@ -1075,7 +1112,13 @@ public class Notification implements Parcelable } @Override public void writeToParcel(Parcel out, int flags) { - out.writeInt(icon); + final Icon ic = getIcon(); + if (ic != null) { + out.writeInt(1); + ic.writeToParcel(out, 0); + } else { + out.writeInt(0); + } TextUtils.writeToParcel(title, out, flags); if (actionIntent != null) { out.writeInt(1); @@ -2725,7 +2768,10 @@ public class Notification implements Parcelable * @param icon Resource ID of a drawable that represents the action. * @param title Text describing the action. * @param intent PendingIntent to be fired when the action is invoked. + * + * @deprecated Use {@link #addAction(Action)} instead. */ + @Deprecated public Builder addAction(int icon, CharSequence title, PendingIntent intent) { mActions.add(new Action(icon, safeCharSequence(title), intent)); return this; @@ -3122,7 +3168,7 @@ public class Notification implements Parcelable private RemoteViews generateActionButton(Action action) { final boolean tombstone = (action.actionIntent == null); - RemoteViews button = new RemoteViews(mContext.getPackageName(), + RemoteViews button = new BuilderRemoteViews(mContext.getApplicationInfo(), tombstone ? getActionTombstoneLayoutResource() : getActionLayoutResource()); button.setTextViewCompoundDrawablesRelative(R.id.action0, action.icon, 0, 0, 0); @@ -4265,7 +4311,7 @@ public class Notification implements Parcelable * * In the expanded form, {@link Notification#bigContentView}, up to 5 * {@link Notification.Action}s specified with - * {@link Notification.Builder#addAction(int, CharSequence, PendingIntent) addAction} will be + * {@link Notification.Builder#addAction(Action) addAction} will be * shown as icon-only pushbuttons, suitable for transport controls. The Bitmap given to * {@link Notification.Builder#setLargeIcon(android.graphics.Bitmap) setLargeIcon()} will be * treated as album artwork. @@ -4391,7 +4437,7 @@ public class Notification implements Parcelable private RemoteViews generateMediaActionButton(Action action) { final boolean tombstone = (action.actionIntent == null); - RemoteViews button = new RemoteViews(mBuilder.mContext.getPackageName(), + RemoteViews button = new BuilderRemoteViews(mBuilder.mContext.getApplicationInfo(), R.layout.notification_material_media_action); button.setImageViewResource(R.id.action0, action.icon); button.setDrawableParameters(R.id.action0, false, -1, diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java index 9673c98..40126d6 100644 --- a/core/java/android/app/assist/AssistStructure.java +++ b/core/java/android/app/assist/AssistStructure.java @@ -812,7 +812,7 @@ public class AssistStructure implements Parcelable { * Returns true if assist data has been blocked starting at this node in the hierarchy. */ public boolean isAssistBlocked() { - return (mFlags&ViewNode.FLAGS_ASSIST_BLOCKED) == 0; + return (mFlags&ViewNode.FLAGS_ASSIST_BLOCKED) != 0; } /** diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index c96fe71..d27dfa0 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -92,7 +92,8 @@ public final class BluetoothDevice implements Parcelable { * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link * #EXTRA_CLASS}. Can contain the extra fields {@link #EXTRA_NAME} and/or * {@link #EXTRA_RSSI} if they are available. - * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} and + * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} to receive. */ // TODO: Change API to not broadcast RSSI if not available (incoming connection) @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 675515b..4c7dd10 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -1516,6 +1516,33 @@ public abstract class Context { public abstract void sendBroadcast(Intent intent, @Nullable String receiverPermission); + + /** + * Broadcast the given intent to all interested BroadcastReceivers, allowing + * an array of required permissions to be enforced. This call is asynchronous; it returns + * immediately, and you will continue executing while the receivers are run. No results are + * propagated from receivers and receivers can not abort the broadcast. If you want to allow + * receivers to propagate results or abort the broadcast, you must send an ordered broadcast + * using {@link #sendOrderedBroadcast(Intent, String)}. + * + * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts. + * + * @param intent The Intent to broadcast; all receivers matching this + * Intent will receive the broadcast. + * @param receiverPermissions Array of names of permissions that a receiver must hold + * in order to receive your broadcast. + * If null or empty, no permissions are required. + * + * @see android.content.BroadcastReceiver + * @see #registerReceiver + * @see #sendBroadcast(Intent) + * @see #sendOrderedBroadcast(Intent, String) + * @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle) + * @hide + */ + public abstract void sendBroadcastMultiplePermissions(Intent intent, + String[] receiverPermissions); + /** * Broadcast the given intent to all interested BroadcastReceivers, allowing * an optional required permission to be enforced. This @@ -1782,6 +1809,17 @@ public abstract class Context { @Nullable Bundle initialExtras); /** + * Similar to above but takes an appOp as well, to enforce restrictions, and an options Bundle. + * @see #sendOrderedBroadcastAsUser(Intent, UserHandle, String, + * BroadcastReceiver, Handler, int, String, Bundle) + * @hide + */ + public abstract void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, + @Nullable String receiverPermission, int appOp, @Nullable Bundle options, + BroadcastReceiver resultReceiver, @Nullable Handler scheduler, int initialCode, + @Nullable String initialData, @Nullable Bundle initialExtras); + + /** * <p>Perform a {@link #sendBroadcast(Intent)} that is "sticky," meaning the * Intent you are sending stays around after the broadcast is complete, * so that others can quickly retrieve that data through the return diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index 4e7c832..8359edf 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -402,6 +402,12 @@ public class ContextWrapper extends Context { } /** @hide */ + @Override + public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions) { + mBase.sendBroadcastMultiplePermissions(intent, receiverPermissions); + } + + /** @hide */ @SystemApi @Override public void sendBroadcast(Intent intent, String receiverPermission, Bundle options) { @@ -483,12 +489,20 @@ public class ContextWrapper extends Context { @Override public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, int appOp, BroadcastReceiver resultReceiver, - Handler scheduler, - int initialCode, String initialData, Bundle initialExtras) { + Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { mBase.sendOrderedBroadcastAsUser(intent, user, receiverPermission, appOp, resultReceiver, scheduler, initialCode, initialData, initialExtras); } + /** @hide */ + @Override + public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, + String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver, + Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { + mBase.sendOrderedBroadcastAsUser(intent, user, receiverPermission, appOp, options, + resultReceiver, scheduler, initialCode, initialData, initialExtras); + } + @Override @Deprecated public void sendStickyBroadcast(Intent intent) { diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index c9f9b56..f786d2f 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -1023,7 +1023,7 @@ public class Intent implements Parcelable, Cloneable { * * <p>Note: if you app targets {@link android.os.Build.VERSION_CODES#MNC MNC} * and above and declares as using the {@link android.Manifest.permission#CALL_PHONE} - * permission which is not granted, then atempting to use this action will + * permission which is not granted, then attempting to use this action will * result in a {@link java.lang.SecurityException}. */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) @@ -3094,6 +3094,13 @@ public class Intent implements Parcelable, Cloneable { @SdkConstant(SdkConstantType.INTENT_CATEGORY) public static final String CATEGORY_HOME = "android.intent.category.HOME"; /** + * This is the setup wizard activity, that is the first activity that is displayed + * when the user sets up the device for the first time. + * @hide + */ + @SdkConstant(SdkConstantType.INTENT_CATEGORY) + public static final String CATEGORY_SETUP_WIZARD = "android.intent.category.SETUP_WIZARD"; + /** * This activity is a preference panel. */ @SdkConstant(SdkConstantType.INTENT_CATEGORY) diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index b7ee82d..9341be1 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -18,8 +18,10 @@ package android.content.pm; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.annotation.SystemApi; import android.app.ActivityManager; import android.content.Context; import android.content.Intent; @@ -889,6 +891,8 @@ public class PackageInstaller { public String abiOverride; /** {@hide} */ public String volumeUuid; + /** {@hide} */ + public String[] grantedRuntimePermissions; /** * Construct parameters for a new package install session. @@ -914,6 +918,7 @@ public class PackageInstaller { referrerUri = source.readParcelable(null); abiOverride = source.readString(); volumeUuid = source.readString(); + grantedRuntimePermissions = source.readStringArray(); } /** @@ -987,6 +992,23 @@ public class PackageInstaller { this.referrerUri = referrerUri; } + /** + * Sets which runtime permissions to be granted to the package at installation. + * Using this API requires holding {@link android.Manifest.permission + * #INSTALL_GRANT_RUNTIME_PERMISSIONS} + * + * @param permissions The permissions to grant or null to grant all runtime + * permissions. + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS) + public void setGrantedRuntimePermissions(String[] permissions) { + installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS; + this.grantedRuntimePermissions = permissions; + } + /** {@hide} */ public void setInstallFlagsInternal() { installFlags |= PackageManager.INSTALL_INTERNAL; @@ -1012,6 +1034,7 @@ public class PackageInstaller { pw.printPair("referrerUri", referrerUri); pw.printPair("abiOverride", abiOverride); pw.printPair("volumeUuid", volumeUuid); + pw.printPair("grantedRuntimePermissions", grantedRuntimePermissions); pw.println(); } @@ -1033,6 +1056,7 @@ public class PackageInstaller { dest.writeParcelable(referrerUri, flags); dest.writeString(abiOverride); dest.writeString(volumeUuid); + dest.writeStringArray(grantedRuntimePermissions); } public static final Parcelable.Creator<SessionParams> diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java index 30aa2d5..5583920 100644 --- a/core/java/android/hardware/camera2/CameraCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraCharacteristics.java @@ -1901,7 +1901,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * <tbody> * <tr> * <td align="center">{@link android.graphics.ImageFormat#JPEG }</td> - * <td align="center">{@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</td> + * <td align="center">{@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} (*1)</td> * <td align="center">Any</td> * <td align="center"></td> * </tr> @@ -1913,7 +1913,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * </tr> * <tr> * <td align="center">{@link android.graphics.ImageFormat#JPEG }</td> - * <td align="center">1280x720 (720)</td> + * <td align="center">1280x720 (720p)</td> * <td align="center">Any</td> * <td align="center">if 720p <= activeArraySize</td> * </tr> @@ -1951,6 +1951,22 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * </table> * <p>Refer to {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} and {@link android.hardware.camera2.CameraDevice#createCaptureSession } for additional mandatory * stream configurations on a per-capability basis.</p> + * <p>*1: For JPEG format, the sizes may be restricted by below conditions:</p> + * <ul> + * <li>The HAL may choose the aspect ratio of each Jpeg size to be one of well known ones + * (e.g. 4:3, 16:9, 3:2 etc.). If the sensor maximum resolution + * (defined by {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}) has an aspect ratio other than these, + * it does not have to be included in the supported JPEG sizes.</li> + * <li>Some hardware JPEG encoders may have pixel boundary alignment requirements, such as + * the dimensions being a multiple of 16. + * Therefore, the maximum JPEG size may be smaller than sensor maximum resolution. + * However, the largest JPEG size will be as close as possible to the sensor maximum + * resolution given above constraints. It is required that after aspect ratio adjustments, + * additional size reduction due to other issues must be less than 3% in area. For example, + * if the sensor maximum resolution is 3280x2464, if the maximum JPEG size has aspect + * ratio 4:3, and the JPEG encoder alignment requirement is 16, the maximum JPEG size will be + * 3264x2448.</li> + * </ul> * <p>This key is available on all devices.</p> * * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl index 0fe112c..80c7b1a 100644 --- a/core/java/android/hardware/usb/IUsbManager.aidl +++ b/core/java/android/hardware/usb/IUsbManager.aidl @@ -19,6 +19,8 @@ package android.hardware.usb; import android.app.PendingIntent; import android.hardware.usb.UsbAccessory; import android.hardware.usb.UsbDevice; +import android.hardware.usb.UsbPort; +import android.hardware.usb.UsbPortStatus; import android.os.Bundle; import android.os.ParcelFileDescriptor; @@ -108,4 +110,13 @@ interface IUsbManager /* Clear public keys installed for secure USB debugging */ void clearUsbDebuggingKeys(); + + /* Gets the list of USB ports. */ + UsbPort[] getPorts(); + + /* Gets the status of the specified USB port. */ + UsbPortStatus getPortStatus(in String portId); + + /* Sets the port's current role. */ + void setPortRoles(in String portId, int powerRole, int dataRole); } diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java index f58b9d6..c88f213 100644 --- a/core/java/android/hardware/usb/UsbManager.java +++ b/core/java/android/hardware/usb/UsbManager.java @@ -17,6 +17,8 @@ package android.hardware.usb; +import com.android.internal.util.Preconditions; + import android.app.PendingIntent; import android.content.Context; import android.os.Bundle; @@ -74,6 +76,22 @@ public class UsbManager { public static final String ACTION_USB_STATE = "android.hardware.usb.action.USB_STATE"; + /** + * Broadcast Action: A broadcast for USB port changes. + * + * This intent is sent when a USB port is added, removed, or changes state. + * <ul> + * <li> {@link #EXTRA_PORT} containing the {@link android.hardware.usb.UsbPort} + * for the port. + * <li> {@link #EXTRA_PORT_STATUS} containing the {@link android.hardware.usb.UsbPortStatus} + * for the port, or null if the port has been removed + * </ul> + * + * @hide + */ + public static final String ACTION_USB_PORT_CHANGED = + "android.hardware.usb.action.USB_PORT_CHANGED"; + /** * Broadcast Action: A broadcast for USB device attached event. * @@ -214,6 +232,23 @@ public class UsbManager { public static final String USB_FUNCTION_ACCESSORY = "accessory"; /** + * Name of extra for {@link #ACTION_USB_PORT_CHANGED} + * containing the {@link UsbPort} object for the port. + * + * @hide + */ + public static final String EXTRA_PORT = "port"; + + /** + * Name of extra for {@link #ACTION_USB_PORT_CHANGED} + * containing the {@link UsbPortStatus} object for the port, or null if the port + * was removed. + * + * @hide + */ + public static final String EXTRA_PORT_STATUS = "portStatus"; + + /** * Name of extra for {@link #ACTION_USB_DEVICE_ATTACHED} and * {@link #ACTION_USB_DEVICE_DETACHED} broadcasts * containing the {@link UsbDevice} object for the device. @@ -499,6 +534,77 @@ public class UsbManager { return false; } + /** + * Returns a list of physical USB ports on the device. + * <p> + * This list is guaranteed to contain all dual-role USB Type C ports but it might + * be missing other ports depending on whether the kernel USB drivers have been + * updated to publish all of the device's ports through the new "dual_role_usb" + * device class (which supports all types of ports despite its name). + * </p> + * + * @return The list of USB ports, or null if none. + * + * @hide + */ + public UsbPort[] getPorts() { + try { + return mService.getPorts(); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in getPorts", e); + } + return null; + } + + /** + * Gets the status of the specified USB port. + * + * @param port The port to query. + * @return The status of the specified USB port, or null if unknown. + * + * @hide + */ + public UsbPortStatus getPortStatus(UsbPort port) { + Preconditions.checkNotNull(port, "port must not be null"); + + try { + return mService.getPortStatus(port.getId()); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in getPortStatus", e); + } + return null; + } + + /** + * Sets the desired role combination of the port. + * <p> + * The supported role combinations depend on what is connected to the port and may be + * determined by consulting + * {@link UsbPortStatus#isRoleCombinationSupported UsbPortStatus.isRoleCombinationSupported}. + * </p><p> + * Note: This function is asynchronous and may fail silently without applying + * the requested changes. If this function does cause a status change to occur then + * a {@link #ACTION_USB_PORT_CHANGED} broadcast will be sent. + * </p> + * + * @param powerRole The desired power role: {@link UsbPort#POWER_ROLE_SOURCE} + * or {@link UsbPort#POWER_ROLE_SINK}, or 0 if no power role. + * @param dataRole The desired data role: {@link UsbPort#DATA_ROLE_HOST} + * or {@link UsbPort#DATA_ROLE_DEVICE}, or 0 if no data role. + * + * @hide + */ + public void setPortRoles(UsbPort port, int powerRole, int dataRole) { + Preconditions.checkNotNull(port, "port must not be null"); + UsbPort.checkRoles(powerRole, dataRole); + + try { + mService.setPortRoles(port.getId(), powerRole, dataRole); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in setPortRole", e); + } + } + /** @hide */ public static String addFunction(String functions, String function) { if ("none".equals(functions)) { diff --git a/core/java/android/hardware/usb/UsbPort.aidl b/core/java/android/hardware/usb/UsbPort.aidl new file mode 100644 index 0000000..b7a7920 --- /dev/null +++ b/core/java/android/hardware/usb/UsbPort.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2015, 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.hardware.usb; + +parcelable UsbPort; diff --git a/core/java/android/hardware/usb/UsbPort.java b/core/java/android/hardware/usb/UsbPort.java new file mode 100644 index 0000000..c9a4e9b --- /dev/null +++ b/core/java/android/hardware/usb/UsbPort.java @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2015 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.hardware.usb; + +import com.android.internal.util.Preconditions; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Represents a physical USB port and describes its characteristics. + * <p> + * This object is immutable. + * </p> + * + * @hide + */ +public final class UsbPort implements Parcelable { + private final String mId; + private final int mSupportedModes; + + /** + * Mode bit: This USB port can act as a downstream facing port (host). + * <p> + * Implies that the port supports the {@link #POWER_ROLE_SOURCE} and {@link #DATA_ROLE_HOST} + * combination of roles (and possibly others as well). + * </p> + */ + public static final int MODE_DFP = 1 << 0; + + /** + * Mode bit: This USB port can act as an upstream facing port (device). + * <p> + * Implies that the port supports the {@link #POWER_ROLE_SINK} and {@link #DATA_ROLE_DEVICE} + * combination of roles (and possibly others as well). + * </p> + */ + public static final int MODE_UFP = 1 << 1; + + /** + * Mode bit: This USB port can act either as an downstream facing port (host) or as + * an upstream facing port (device). + * <p> + * Implies that the port supports the {@link #POWER_ROLE_SOURCE} and {@link #DATA_ROLE_HOST} + * combination of roles and the {@link #POWER_ROLE_SINK} and {@link #DATA_ROLE_DEVICE} + * combination of roles (and possibly others as well). + * </p> + */ + public static final int MODE_DUAL = MODE_DFP | MODE_UFP; + + /** + * Power role: This USB port can act as a source (provide power). + */ + public static final int POWER_ROLE_SOURCE = 1; + + /** + * Power role: This USB port can act as a sink (receive power). + */ + public static final int POWER_ROLE_SINK = 2; + + /** + * Data role: This USB port can act as a host (access data services). + */ + public static final int DATA_ROLE_HOST = 1; + + /** + * Data role: This USB port can act as a device (offer data services). + */ + public static final int DATA_ROLE_DEVICE = 2; + + private static final int NUM_DATA_ROLES = 3; + + /** @hide */ + public UsbPort(String id, int supportedModes) { + mId = id; + mSupportedModes = supportedModes; + } + + /** + * Gets the unique id of the port. + * + * @return The unique id of the port; not intended for display. + */ + public String getId() { + return mId; + } + + /** + * Gets the supported modes of the port. + * <p> + * The actual mode of the port may vary depending on what is plugged into it. + * </p> + * + * @return The supported modes: one of {@link #MODE_DFP}, {@link #MODE_UFP}, or + * {@link #MODE_DUAL}. + */ + public int getSupportedModes() { + return mSupportedModes; + } + + /** + * Combines one power and one data role together into a unique value with + * exactly one bit set. This can be used to efficiently determine whether + * a combination of roles is supported by testing whether that bit is present + * in a bit-field. + * + * @param powerRole The desired power role: {@link UsbPort#POWER_ROLE_SOURCE} + * or {@link UsbPort#POWER_ROLE_SINK}, or 0 if no power role. + * @param dataRole The desired data role: {@link UsbPort#DATA_ROLE_HOST} + * or {@link UsbPort#DATA_ROLE_DEVICE}, or 0 if no data role. + * @hide + */ + public static int combineRolesAsBit(int powerRole, int dataRole) { + checkRoles(powerRole, dataRole); + final int index = powerRole * NUM_DATA_ROLES + dataRole; + return 1 << index; + } + + /** @hide */ + public static String modeToString(int mode) { + switch (mode) { + case 0: + return "none"; + case MODE_DFP: + return "dfp"; + case MODE_UFP: + return "ufp"; + case MODE_DUAL: + return "dual"; + default: + return Integer.toString(mode); + } + } + + /** @hide */ + public static String powerRoleToString(int role) { + switch (role) { + case 0: + return "no-power"; + case POWER_ROLE_SOURCE: + return "source"; + case POWER_ROLE_SINK: + return "sink"; + default: + return Integer.toString(role); + } + } + + /** @hide */ + public static String dataRoleToString(int role) { + switch (role) { + case 0: + return "no-data"; + case DATA_ROLE_HOST: + return "host"; + case DATA_ROLE_DEVICE: + return "device"; + default: + return Integer.toString(role); + } + } + + /** @hide */ + public static String roleCombinationsToString(int combo) { + StringBuilder result = new StringBuilder(); + result.append("["); + + boolean first = true; + while (combo != 0) { + final int index = Integer.numberOfTrailingZeros(combo); + combo &= ~(1 << index); + final int powerRole = index / NUM_DATA_ROLES; + final int dataRole = index % NUM_DATA_ROLES; + if (first) { + first = false; + } else { + result.append(", "); + } + result.append(powerRoleToString(powerRole)); + result.append(':'); + result.append(dataRoleToString(dataRole)); + } + + result.append("]"); + return result.toString(); + } + + /** @hide */ + public static void checkRoles(int powerRole, int dataRole) { + Preconditions.checkArgumentInRange(powerRole, 0, POWER_ROLE_SINK, "powerRole"); + Preconditions.checkArgumentInRange(dataRole, 0, DATA_ROLE_DEVICE, "dataRole"); + } + + @Override + public String toString() { + return "UsbPort{id=" + mId + ", supportedModes=" + modeToString(mSupportedModes) + "}"; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(mId); + dest.writeInt(mSupportedModes); + } + + public static final Parcelable.Creator<UsbPort> CREATOR = + new Parcelable.Creator<UsbPort>() { + @Override + public UsbPort createFromParcel(Parcel in) { + String id = in.readString(); + int supportedModes = in.readInt(); + return new UsbPort(id, supportedModes); + } + + @Override + public UsbPort[] newArray(int size) { + return new UsbPort[size]; + } + }; +} diff --git a/core/java/android/hardware/usb/UsbPortStatus.aidl b/core/java/android/hardware/usb/UsbPortStatus.aidl new file mode 100644 index 0000000..9a7e468 --- /dev/null +++ b/core/java/android/hardware/usb/UsbPortStatus.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2015, 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.hardware.usb; + +parcelable UsbPortStatus; diff --git a/core/java/android/hardware/usb/UsbPortStatus.java b/core/java/android/hardware/usb/UsbPortStatus.java new file mode 100644 index 0000000..5c0e81a --- /dev/null +++ b/core/java/android/hardware/usb/UsbPortStatus.java @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2015 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.hardware.usb; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Describes the status of a USB port. + * <p> + * This object is immutable. + * </p> + * + * @hide + */ +public final class UsbPortStatus implements Parcelable { + private final int mCurrentMode; + private final int mCurrentPowerRole; + private final int mCurrentDataRole; + private final int mSupportedRoleCombinations; + + /** @hide */ + public UsbPortStatus(int currentMode, int currentPowerRole, int currentDataRole, + int supportedRoleCombinations) { + mCurrentMode = currentMode; + mCurrentPowerRole = currentPowerRole; + mCurrentDataRole = currentDataRole; + mSupportedRoleCombinations = supportedRoleCombinations; + } + + /** + * Returns true if there is anything connected to the port. + * + * @return True if there is anything connected to the port. + */ + public boolean isConnected() { + return mCurrentMode != 0; + } + + /** + * Gets the current mode of the port. + * + * @return The current mode: {@link UsbPort#MODE_DFP}, {@link UsbPort#MODE_UFP}, + * or 0 if nothing is connected. + */ + public int getCurrentMode() { + return mCurrentMode; + } + + /** + * Gets the current power role of the port. + * + * @return The current power role: {@link UsbPort#POWER_ROLE_SOURCE}, + * {@link UsbPort#POWER_ROLE_SINK}, or 0 if nothing is connected. + */ + public int getCurrentPowerRole() { + return mCurrentPowerRole; + } + + /** + * Gets the current data role of the port. + * + * @return The current data role: {@link UsbPort#DATA_ROLE_HOST}, + * {@link UsbPort#DATA_ROLE_DEVICE}, or 0 if nothing is connected. + */ + public int getCurrentDataRole() { + return mCurrentDataRole; + } + + /** + * Returns true if the specified power and data role combination is supported + * given what is currently connected to the port. + * + * @param powerRole The power role to check: {@link UsbPort#POWER_ROLE_SOURCE} + * or {@link UsbPort#POWER_ROLE_SINK}, or 0 if no power role. + * @param dataRole The data role to check: either {@link UsbPort#DATA_ROLE_HOST} + * or {@link UsbPort#DATA_ROLE_DEVICE}, or 0 if no data role. + */ + public boolean isRoleCombinationSupported(int powerRole, int dataRole) { + return (mSupportedRoleCombinations & + UsbPort.combineRolesAsBit(powerRole, dataRole)) != 0; + } + + /** @hide */ + public int getSupportedRoleCombinations() { + return mSupportedRoleCombinations; + } + + @Override + public String toString() { + return "UsbPortStatus{connected=" + isConnected() + + ", currentMode=" + UsbPort.modeToString(mCurrentMode) + + ", currentPowerRole=" + UsbPort.powerRoleToString(mCurrentPowerRole) + + ", currentDataRole=" + UsbPort.dataRoleToString(mCurrentDataRole) + + ", supportedRoleCombinations=" + + UsbPort.roleCombinationsToString(mSupportedRoleCombinations) + + "}"; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mCurrentMode); + dest.writeInt(mCurrentPowerRole); + dest.writeInt(mCurrentDataRole); + dest.writeInt(mSupportedRoleCombinations); + } + + public static final Parcelable.Creator<UsbPortStatus> CREATOR = + new Parcelable.Creator<UsbPortStatus>() { + @Override + public UsbPortStatus createFromParcel(Parcel in) { + int currentMode = in.readInt(); + int currentPowerRole = in.readInt(); + int currentDataRole = in.readInt(); + int supportedRoleCombinations = in.readInt(); + return new UsbPortStatus(currentMode, currentPowerRole, currentDataRole, + supportedRoleCombinations); + } + + @Override + public UsbPortStatus[] newArray(int size) { + return new UsbPortStatus[size]; + } + }; +} diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index adc84bc..ecb7f5a 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -1193,9 +1193,13 @@ public abstract class BatteryStats implements Parcelable { public static final int EVENT_PACKAGE_INACTIVE = 0x000f; // Event for a package becoming active due to an interaction. public static final int EVENT_PACKAGE_ACTIVE = 0x0010; + // Event for a package being on the temporary whitelist. + public static final int EVENT_TEMP_WHITELIST = 0x0011; + // Event for the screen waking up. + public static final int EVENT_SCREEN_WAKE_UP = 0x0012; // Number of event types. - public static final int EVENT_COUNT = 0x0011; + public static final int EVENT_COUNT = 0x0013; // Mask to extract out only the type part of the event. public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH); @@ -1219,6 +1223,10 @@ public abstract class BatteryStats implements Parcelable { EVENT_USER_FOREGROUND | EVENT_FLAG_FINISH; public static final int EVENT_ALARM_START = EVENT_ALARM | EVENT_FLAG_START; public static final int EVENT_ALARM_FINISH = EVENT_ALARM | EVENT_FLAG_FINISH; + public static final int EVENT_TEMP_WHITELIST_START = + EVENT_TEMP_WHITELIST | EVENT_FLAG_START; + public static final int EVENT_TEMP_WHITELIST_FINISH = + EVENT_TEMP_WHITELIST | EVENT_FLAG_FINISH; // For CMD_EVENT. public int eventCode; @@ -1852,12 +1860,14 @@ public abstract class BatteryStats implements Parcelable { public static final String[] HISTORY_EVENT_NAMES = new String[] { "null", "proc", "fg", "top", "sync", "wake_lock_in", "job", "user", "userfg", "conn", - "active", "pkginst", "pkgunin", "alarm", "stats", "inactive", "active" + "active", "pkginst", "pkgunin", "alarm", "stats", "inactive", "active", "tmpwhitelist", + "screenwake", }; public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] { "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf", "Ecn", - "Eac", "Epi", "Epu", "Eal", "Est", "Eai", "Eaa" + "Eac", "Epi", "Epu", "Eal", "Est", "Eai", "Eaa", "Etw", + "Esw", }; /** diff --git a/core/java/android/os/IDeviceIdleController.aidl b/core/java/android/os/IDeviceIdleController.aidl index fe4aa13..b768852 100644 --- a/core/java/android/os/IDeviceIdleController.aidl +++ b/core/java/android/os/IDeviceIdleController.aidl @@ -27,6 +27,7 @@ interface IDeviceIdleController { int[] getAppIdWhitelist(); int[] getAppIdTempWhitelist(); boolean isPowerSaveWhitelistApp(String name); - void addPowerSaveTempWhitelistApp(String name, long duration, int userId); + void addPowerSaveTempWhitelistApp(String name, long duration, int userId, String reason); + long addPowerSaveTempWhitelistAppForMms(String name, int userId, String reason); void exitIdle(String reason); } diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl index 804d3d0..0f37ac7 100644 --- a/core/java/android/os/IPowerManager.aidl +++ b/core/java/android/os/IPowerManager.aidl @@ -37,7 +37,7 @@ interface IPowerManager boolean isWakeLockLevelSupported(int level); void userActivity(long time, int event, int flags); - void wakeUp(long time); + void wakeUp(long time, String reason, String opPackageName); void goToSleep(long time, int reason, int flags); void nap(long time); boolean isInteractive(); diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index 6ef1cd0..9a1a03e 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -658,7 +658,17 @@ public final class PowerManager { */ public void wakeUp(long time) { try { - mService.wakeUp(time); + mService.wakeUp(time, "wakeUp", mContext.getOpPackageName()); + } catch (RemoteException e) { + } + } + + /** + * @hide + */ + public void wakeUp(long time, String reason) { + try { + mService.wakeUp(time, reason, mContext.getOpPackageName()); } catch (RemoteException e) { } } diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index 2b75f31..b2cec60 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -860,8 +860,23 @@ public class StorageManager { final IMountService mountService = IMountService.Stub.asInterface( ServiceManager.getService("mount")); try { - final String packageName = ActivityThread.currentOpPackageName(); + String packageName = ActivityThread.currentOpPackageName(); + if (packageName == null) { + // Package name can be null if the activity thread is running but the app + // hasn't bound yet. In this case we fall back to the first package in the + // current UID. This works for runtime permissions as permission state is + // per UID and permission realted app ops are updated for all UID packages. + String[] packageNames = ActivityThread.getPackageManager().getPackagesForUid( + android.os.Process.myUid()); + if (packageNames == null || packageNames.length <= 0) { + return new StorageVolume[0]; + } + packageName = packageNames[0]; + } final int uid = ActivityThread.getPackageManager().getPackageUid(packageName, userId); + if (uid <= 0) { + return new StorageVolume[0]; + } return mountService.getVolumeList(uid, packageName); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java index d743484..aa22041 100644 --- a/core/java/android/provider/CalendarContract.java +++ b/core/java/android/provider/CalendarContract.java @@ -2393,7 +2393,7 @@ public final class CalendarContract { intent.setData(ContentUris.withAppendedId(CalendarContract.CONTENT_URI, alarmTime)); intent.putExtra(ALARM_TIME, alarmTime); PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0); - manager.setExact(AlarmManager.RTC_WAKEUP, alarmTime, pi); + manager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, alarmTime, pi); } /** diff --git a/core/java/android/service/chooser/ChooserTarget.java b/core/java/android/service/chooser/ChooserTarget.java index 50c435a..c2f70cc 100644 --- a/core/java/android/service/chooser/ChooserTarget.java +++ b/core/java/android/service/chooser/ChooserTarget.java @@ -17,20 +17,14 @@ package android.service.chooser; -import android.app.Activity; -import android.app.PendingIntent; +import android.annotation.Nullable; import android.content.ComponentName; -import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.IntentSender; -import android.graphics.Bitmap; import android.graphics.drawable.Icon; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; -import android.os.UserHandle; -import android.util.Log; /** * A ChooserTarget represents a deep-link into an application as returned by a @@ -62,52 +56,21 @@ public final class ChooserTarget implements Parcelable { private Icon mIcon; /** - * The IntentSender that will be used to deliver the intent to the target. - * It will be {@link android.content.Intent#fillIn(android.content.Intent, int)} filled in} - * by the real intent sent by the application. + * The ComponentName of the Activity to be invoked. Must be part of the target creator's + * own package or an Activity exported by its package. */ - private IntentSender mIntentSender; + private ComponentName mComponentName; /** - * The score given to this item. It can be normalized. + * A Bundle to merge with the extras of the intent sent to this target. + * Any extras here will override the extras from the original intent. */ - private float mScore; + private Bundle mIntentExtras; /** - * Construct a deep link target for presentation by a chooser UI. - * - * <p>A target is composed of a title and an icon for presentation to the user. - * The UI presenting this target may truncate the title if it is too long to be presented - * in the available space, as well as crop, resize or overlay the supplied icon.</p> - * - * <p>The creator of a target may supply a ranking score. This score is assumed to be relative - * to the other targets supplied by the same - * {@link ChooserTargetService#onGetChooserTargets(ComponentName, IntentFilter) query}. - * Scores should be in the range from 0.0f (unlikely match) to 1.0f (very relevant match). - * Scores for a set of targets do not need to sum to 1.</p> - * - * <p>Before being sent, the PendingIntent supplied will be - * {@link Intent#fillIn(Intent, int) filled in} by the Intent originally supplied - * to the chooser. When constructing a PendingIntent for use in a ChooserTarget, make sure - * that you permit the relevant fields to be filled in using the appropriate flags such as - * {@link Intent#FILL_IN_ACTION}, {@link Intent#FILL_IN_CATEGORIES}, - * {@link Intent#FILL_IN_DATA} and {@link Intent#FILL_IN_CLIP_DATA}. Note that - * {@link Intent#FILL_IN_CLIP_DATA} is required to appropriately receive URI permission grants - * for {@link Intent#ACTION_SEND} intents.</p> - * - * <p>Take care not to place custom {@link android.os.Parcelable} types into - * the PendingIntent as extras, as the system will not be able to unparcel it to merge - * additional extras.</p> - * - * @param title title of this target that will be shown to a user - * @param icon icon to represent this target - * @param score ranking score for this target between 0.0f and 1.0f, inclusive - * @param pendingIntent PendingIntent to fill in and send if the user chooses this target + * The score given to this item. It can be normalized. */ - public ChooserTarget(CharSequence title, Icon icon, float score, - PendingIntent pendingIntent) { - this(title, icon, score, pendingIntent.getIntentSender()); - } + private float mScore; /** * Construct a deep link target for presentation by a chooser UI. @@ -122,25 +85,23 @@ public final class ChooserTarget implements Parcelable { * Scores should be in the range from 0.0f (unlikely match) to 1.0f (very relevant match). * Scores for a set of targets do not need to sum to 1.</p> * - * <p>Before being sent, the IntentSender supplied will be - * {@link Intent#fillIn(Intent, int) filled in} by the Intent originally supplied - * to the chooser. When constructing an IntentSender for use in a ChooserTarget, make sure - * that you permit the relevant fields to be filled in using the appropriate flags such as - * {@link Intent#FILL_IN_ACTION}, {@link Intent#FILL_IN_CATEGORIES}, - * {@link Intent#FILL_IN_DATA} and {@link Intent#FILL_IN_CLIP_DATA}. Note that - * {@link Intent#FILL_IN_CLIP_DATA} is required to appropriately receive URI permission grants - * for {@link Intent#ACTION_SEND} intents.</p> + * <p>The ComponentName must be the name of an Activity component in the creator's own + * package, or an exported component from any other package. You may provide an optional + * Bundle of extras that will be merged into the final intent before it is sent to the + * target Activity; use this to add any additional data about the deep link that the target + * activity will read. e.g. conversation IDs, email addresses, etc.</p> * * <p>Take care not to place custom {@link android.os.Parcelable} types into - * the IntentSender as extras, as the system will not be able to unparcel it to merge - * additional extras.</p> + * the extras bundle, as the system will not be able to unparcel them to merge them.</p> * * @param title title of this target that will be shown to a user * @param icon icon to represent this target * @param score ranking score for this target between 0.0f and 1.0f, inclusive - * @param intentSender IntentSender to fill in and send if the user chooses this target + * @param componentName Name of the component to be launched if this target is chosen + * @param intentExtras Bundle of extras to merge with the extras of the launched intent */ - public ChooserTarget(CharSequence title, Icon icon, float score, IntentSender intentSender) { + public ChooserTarget(CharSequence title, Icon icon, float score, + ComponentName componentName, @Nullable Bundle intentExtras) { mTitle = title; mIcon = icon; if (score > 1.f || score < 0.f) { @@ -148,7 +109,8 @@ public final class ChooserTarget implements Parcelable { + "must be between 0.0f and 1.0f"); } mScore = score; - mIntentSender = intentSender; + mComponentName = componentName; + mIntentExtras = intentExtras; } ChooserTarget(Parcel in) { @@ -159,7 +121,8 @@ public final class ChooserTarget implements Parcelable { mIcon = null; } mScore = in.readFloat(); - mIntentSender = IntentSender.readIntentSenderOrNullFromParcel(in); + mComponentName = ComponentName.readFromParcel(in); + mIntentExtras = in.readBundle(); } /** @@ -194,49 +157,29 @@ public final class ChooserTarget implements Parcelable { } /** - * Returns the raw IntentSender supplied by the ChooserTarget's creator. - * This may be null if the creator specified a regular Intent instead. - * - * <p>To fill in and send the intent, see {@link #sendIntent(Context, Intent)}.</p> + * Returns the ComponentName of the Activity that should be launched for this ChooserTarget. * - * @return the IntentSender supplied by the ChooserTarget's creator + * @return the name of the target Activity to launch */ - public IntentSender getIntentSender() { - return mIntentSender; + public ComponentName getComponentName() { + return mComponentName; } /** - * Fill in the IntentSender supplied by the ChooserTarget's creator and send it. + * Returns the Bundle of extras to be added to an intent launched to this target. * - * @param context the sending Context; generally the Activity presenting the chooser UI - * @param fillInIntent the Intent provided to the Chooser to be sent to a selected target - * @return true if sending the Intent was successful + * @return the extras to merge with the extras of the intent being launched */ - public boolean sendIntent(Context context, Intent fillInIntent) { - if (fillInIntent != null) { - fillInIntent.migrateExtraStreamToClipData(); - fillInIntent.prepareToLeaveProcess(); - } - if (mIntentSender != null) { - try { - mIntentSender.sendIntent(context, 0, fillInIntent, null, null); - return true; - } catch (IntentSender.SendIntentException e) { - Log.e(TAG, "sendIntent " + this + " failed", e); - return false; - } - } else { - Log.e(TAG, "sendIntent " + this + " failed - no IntentSender to send"); - return false; - } + public Bundle getIntentExtras() { + return mIntentExtras; } @Override public String toString() { return "ChooserTarget{" - + (mIntentSender != null ? mIntentSender.getCreatorPackage() : null) - + ", " - + "'" + mTitle + + mComponentName + + ", " + mIntentExtras + + ", '" + mTitle + "', " + mScore + "}"; } @@ -255,7 +198,8 @@ public final class ChooserTarget implements Parcelable { dest.writeInt(0); } dest.writeFloat(mScore); - IntentSender.writeIntentSenderOrNullToParcel(mIntentSender, dest); + ComponentName.writeToParcel(mComponentName, dest); + dest.writeBundle(mIntentExtras); } public static final Creator<ChooserTarget> CREATOR diff --git a/core/java/android/service/chooser/ChooserTargetService.java b/core/java/android/service/chooser/ChooserTargetService.java index a3bfece..e054185 100644 --- a/core/java/android/service/chooser/ChooserTargetService.java +++ b/core/java/android/service/chooser/ChooserTargetService.java @@ -105,9 +105,8 @@ public abstract class ChooserTargetService extends Service { * can handle an intent. * * <p>The returned list should be sorted such that the most relevant targets appear first. - * Any PendingIntents used to construct the resulting ChooserTargets should always be prepared - * to have the relevant data fields filled in by the sender. See - * {@link ChooserTarget#ChooserTarget(CharSequence, android.graphics.drawable.Icon, float, android.app.PendingIntent) ChooserTarget}.</p> + * The score for each ChooserTarget will be combined with the system's score for the original + * target Activity to sort and filter targets presented to the user.</p> * * <p><em>Important:</em> Calls to this method from other applications will occur on * a binder thread, not on your app's main thread. Make sure that access to relevant data diff --git a/core/java/android/service/chooser/IChooserTargetResult.aidl b/core/java/android/service/chooser/IChooserTargetResult.aidl index dbd7cbd..6c648a2 100644 --- a/core/java/android/service/chooser/IChooserTargetResult.aidl +++ b/core/java/android/service/chooser/IChooserTargetResult.aidl @@ -21,7 +21,7 @@ import android.service.chooser.ChooserTarget; /** * @hide */ -interface IChooserTargetResult +oneway interface IChooserTargetResult { void sendResult(in List<ChooserTarget> targets); } diff --git a/core/java/android/service/dreams/Sandman.java b/core/java/android/service/dreams/Sandman.java index 5f5b079..eeb340b 100644 --- a/core/java/android/service/dreams/Sandman.java +++ b/core/java/android/service/dreams/Sandman.java @@ -92,7 +92,8 @@ public final class Sandman { // be awake by the time this happens. Otherwise the dream may not start. PowerManager powerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); - powerManager.wakeUp(SystemClock.uptimeMillis()); + powerManager.wakeUp(SystemClock.uptimeMillis(), + "android.service.dreams:DREAM"); } else { Slog.i(TAG, "Activating dream by user request."); } diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java index 549c93e..479c9e2 100644 --- a/core/java/android/service/voice/VoiceInteractionService.java +++ b/core/java/android/service/voice/VoiceInteractionService.java @@ -37,7 +37,6 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.Locale; - /** * Top-level service of the current global voice interactor, which is providing * support for hotwording, the back-end of a {@link android.app.VoiceInteractor}, etc. @@ -154,11 +153,39 @@ public class VoiceInteractionService extends Service { } /** + * Set contextual options you would always like to have disabled when a session + * is shown. The flags may be any combination of + * {@link VoiceInteractionSession#SHOW_WITH_ASSIST VoiceInteractionSession.SHOW_WITH_ASSIST} and + * {@link VoiceInteractionSession#SHOW_WITH_SCREENSHOT + * VoiceInteractionSession.SHOW_WITH_SCREENSHOT}. + */ + public void setDisabledShowContext(int flags) { + try { + mSystemService.setDisabledShowContext(flags); + } catch (RemoteException e) { + } + } + + /** + * Return the value set by {@link #setDisabledShowContext}. + */ + public int getDisabledShowContext() { + try { + return mSystemService.getDisabledShowContext(); + } catch (RemoteException e) { + return 0; + } + } + + /** * Request that the associated {@link android.service.voice.VoiceInteractionSession} be * shown to the user, starting it if necessary. * @param args Arbitrary arguments that will be propagated to the session. * @param flags Indicates additional optional behavior that should be performed. May - * be {@link VoiceInteractionSession#SHOW_WITH_ASSIST VoiceInteractionSession.SHOW_WITH_ASSIST} + * be any combination of + * {@link VoiceInteractionSession#SHOW_WITH_ASSIST VoiceInteractionSession.SHOW_WITH_ASSIST} and + * {@link VoiceInteractionSession#SHOW_WITH_SCREENSHOT + * VoiceInteractionSession.SHOW_WITH_SCREENSHOT} * to request that the system generate and deliver assist data on the current foreground * app as part of showing the session UI. */ diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java index e408b36..95f96e8 100644 --- a/core/java/android/service/voice/VoiceInteractionSession.java +++ b/core/java/android/service/voice/VoiceInteractionSession.java @@ -650,7 +650,7 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall class MyCallbacks implements HandlerCaller.Callback, SoftInputWindow.Callback { @Override public void executeMessage(Message msg) { - SomeArgs args; + SomeArgs args = null; switch (msg.what) { case MSG_START_CONFIRMATION: if (DEBUG) Log.d(TAG, "onConfirm: req=" + msg.obj); @@ -676,6 +676,8 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall args = (SomeArgs)msg.obj; if (DEBUG) Log.d(TAG, "onGetSupportedCommands: cmds=" + args.arg1); args.arg1 = onGetSupportedCommands((String[]) args.arg1); + args.complete(); + args = null; break; case MSG_CANCEL: if (DEBUG) Log.d(TAG, "onCancel: req=" + ((Request)msg.obj)); @@ -723,6 +725,9 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall doHide(); break; } + if (args != null) { + args.recycle(); + } } @Override @@ -908,12 +913,38 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall } /** + * Equivalent to {@link VoiceInteractionService#setDisabledShowContext + * VoiceInteractionService.setDisabledShowContext(int)}. + */ + public void setDisabledShowContext(int flags) { + try { + mSystemService.setDisabledShowContext(flags); + } catch (RemoteException e) { + } + } + + /** + * Equivalent to {@link VoiceInteractionService#getDisabledShowContext + * VoiceInteractionService.getDisabledShowContext}. + */ + public int getDisabledShowContext() { + try { + return mSystemService.getDisabledShowContext(); + } catch (RemoteException e) { + return 0; + } + } + + /** * Show the UI for this session. This asks the system to go through the process of showing * your UI, which will eventually culminate in {@link #onShow}. This is similar to calling * {@link VoiceInteractionService#showSession VoiceInteractionService.showSession}. * @param args Arbitrary arguments that will be propagated {@link #onShow}. * @param flags Indicates additional optional behavior that should be performed. May - * be {@link VoiceInteractionSession#SHOW_WITH_ASSIST VoiceInteractionSession.SHOW_WITH_ASSIST} + * be any combination of + * {@link VoiceInteractionSession#SHOW_WITH_ASSIST VoiceInteractionSession.SHOW_WITH_ASSIST} and + * {@link VoiceInteractionSession#SHOW_WITH_SCREENSHOT + * VoiceInteractionSession.SHOW_WITH_SCREENSHOT} * to request that the system generate and deliver assist data on the current foreground * app as part of showing the session UI. */ diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index c4f57c7..6af2e8b 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -471,6 +471,36 @@ public class ChooserActivity extends ResolverActivity { return false; } + void filterServiceTargets(String packageName, List<ChooserTarget> targets) { + if (targets == null) { + return; + } + + final PackageManager pm = getPackageManager(); + for (int i = targets.size() - 1; i >= 0; i--) { + final ChooserTarget target = targets.get(i); + final ComponentName targetName = target.getComponentName(); + if (packageName != null && packageName.equals(targetName.getPackageName())) { + // Anything from the original target's package is fine. + continue; + } + + boolean remove; + try { + final ActivityInfo ai = pm.getActivityInfo(targetName, 0); + remove = !ai.exported || ai.permission != null; + } catch (NameNotFoundException e) { + Log.e(TAG, "Target " + target + " returned by " + packageName + + " component not found"); + remove = true; + } + + if (remove) { + targets.remove(i); + } + } + } + @Override ResolveListAdapter createAdapter(Context context, List<Intent> payloadIntents, Intent[] initialIntents, List<ResolveInfo> rList, int launchedFromUid, @@ -554,11 +584,11 @@ public class ChooserActivity extends ResolverActivity { return null; } - private Intent getFillInIntent() { + private Intent getBaseIntentToSend() { Intent result = mSourceInfo != null ? mSourceInfo.getResolvedIntent() : getTargetIntent(); if (result == null) { - Log.e(TAG, "ChooserTargetInfo#getFillInIntent: no fillIn intent available"); + Log.e(TAG, "ChooserTargetInfo: no base intent available to send"); } else { result = new Intent(result); if (mFillInIntent != null) { @@ -571,31 +601,24 @@ public class ChooserActivity extends ResolverActivity { @Override public boolean start(Activity activity, Bundle options) { - final Intent intent = getFillInIntent(); - if (intent == null) { - return false; - } - return mChooserTarget.sendIntent(activity, intent); + throw new RuntimeException("ChooserTargets should be started as caller."); } @Override public boolean startAsCaller(Activity activity, Bundle options, int userId) { - final Intent intent = getFillInIntent(); + final Intent intent = getBaseIntentToSend(); if (intent == null) { return false; } - // ChooserTargets will launch with their IntentSender's identity - return mChooserTarget.sendIntent(activity, intent); + intent.setComponent(mChooserTarget.getComponentName()); + intent.putExtras(mChooserTarget.getIntentExtras()); + activity.startActivityAsCaller(intent, options, true, userId); + return true; } @Override public boolean startAsUser(Activity activity, Bundle options, UserHandle user) { - final Intent intent = getFillInIntent(); - if (intent == null) { - return false; - } - // ChooserTargets will launch with their IntentSender's identity - return mChooserTarget.sendIntent(activity, intent); + throw new RuntimeException("ChooserTargets should be started as caller."); } @Override @@ -998,6 +1021,8 @@ public class ChooserActivity extends ResolverActivity { private final IChooserTargetResult mChooserTargetResult = new IChooserTargetResult.Stub() { @Override public void sendResult(List<ChooserTarget> targets) throws RemoteException { + filterServiceTargets(mOriginalTarget.getResolveInfo().activityInfo.packageName, + targets); final Message msg = Message.obtain(); msg.what = CHOOSER_TARGET_SERVICE_RESULT; msg.obj = new ServiceResultInfo(mOriginalTarget, targets, diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl index 6f0cec6..3cddbf6 100644 --- a/core/java/com/android/internal/app/IBatteryStats.aidl +++ b/core/java/com/android/internal/app/IBatteryStats.aidl @@ -83,6 +83,7 @@ interface IBatteryStats { void noteScreenState(int state); void noteScreenBrightness(int brightness); void noteUserActivity(int uid, int event); + void noteWakeUp(String reason, int reasonUid); void noteInteractive(boolean interactive); void noteConnectivityChanged(int type, String extra); void noteMobileRadioPowerState(int powerState, long timestampNs); diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl index 7f54f50..73ad981 100644 --- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl +++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl @@ -37,6 +37,8 @@ interface IVoiceInteractionManagerService { void setKeepAwake(IBinder token, boolean keepAwake); void closeSystemDialogs(IBinder token); void finish(IBinder token); + void setDisabledShowContext(int flags); + int getDisabledShowContext(); /** * Gets the registered Sound model for keyphrase detection for the current user. diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java index 233bee3..39b66aa 100644 --- a/core/java/com/android/internal/app/IntentForwarderActivity.java +++ b/core/java/com/android/internal/app/IntentForwarderActivity.java @@ -103,7 +103,7 @@ public class IntentForwarderActivity extends Activity { || ChooserActivity.class.getName().equals(ri.activityInfo.name)); try { - startActivityAsCaller(newIntent, null, targetUserId); + startActivityAsCaller(newIntent, null, false, targetUserId); } catch (RuntimeException e) { int launchedFromUid = -1; String launchedFromPackage = "?"; diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index 7bc18f3..ba19131 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -973,7 +973,7 @@ public class ResolverActivity extends Activity { @Override public boolean startAsCaller(Activity activity, Bundle options, int userId) { - activity.startActivityAsCaller(mResolvedIntent, options, userId); + activity.startActivityAsCaller(mResolvedIntent, options, false, userId); return true; } diff --git a/core/java/com/android/internal/app/ToolbarActionBar.java b/core/java/com/android/internal/app/ToolbarActionBar.java index 2b162af..c1b184e 100644 --- a/core/java/com/android/internal/app/ToolbarActionBar.java +++ b/core/java/com/android/internal/app/ToolbarActionBar.java @@ -463,6 +463,18 @@ public class ToolbarActionBar extends ActionBar { return true; } + @Override + public boolean onKeyShortcut(int keyCode, KeyEvent event) { + Menu menu = mDecorToolbar.getMenu(); + if (menu != null) { + menu.performShortcut(keyCode, event, 0); + } + // This action bar always returns true for handling keyboard shortcuts. + // This will block the window from preparing a temporary panel to handle + // keyboard shortcuts. + return true; + } + public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener) { mMenuVisibilityListeners.add(listener); } diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 84c2417..60f47d6 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -3122,6 +3122,13 @@ public final class BatteryStatsImpl extends BatteryStats { } } + public void noteWakeUpLocked(String reason, int reasonUid) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SCREEN_WAKE_UP, + reason, reasonUid); + } + public void noteInteractiveLocked(boolean interactive) { if (mInteractive != interactive) { final long elapsedRealtime = SystemClock.elapsedRealtime(); @@ -8073,7 +8080,7 @@ public final class BatteryStatsImpl extends BatteryStats { timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs); final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*"); - proc.addCpuTimeLocked(userTimeUs, systemTimeUs); + proc.addCpuTimeLocked(userTimeUs / 1000, systemTimeUs / 1000); mTempTotalCpuUserTimeUs -= userTimeUs; mTempTotalCpuSystemTimeUs -= systemTimeUs; @@ -8097,8 +8104,8 @@ public final class BatteryStatsImpl extends BatteryStats { u.mSystemCpuTime.addCountLocked(mTempTotalCpuSystemTimeUs); final Uid.Proc proc = u.getProcessStatsLocked("*lost*"); - proc.addCpuTimeLocked((int) mTempTotalCpuUserTimeUs, - (int) mTempTotalCpuSystemTimeUs); + proc.addCpuTimeLocked((int) mTempTotalCpuUserTimeUs / 1000, + (int) mTempTotalCpuSystemTimeUs / 1000); } } diff --git a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java index 1a1e0b2..0df78ed 100644 --- a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java +++ b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java @@ -151,6 +151,7 @@ public class KernelUidCpuTimeReader { if (index >= 0) { mLastUserTimeUs.removeAt(index); mLastSystemTimeUs.removeAt(index); + mLastPowerMaUs.removeAt(index); } try (FileWriter writer = new FileWriter(sRemoveUidProcFile)) { diff --git a/core/java/com/android/internal/os/SomeArgs.java b/core/java/com/android/internal/os/SomeArgs.java index b0d24fd..c05e0d8 100644 --- a/core/java/com/android/internal/os/SomeArgs.java +++ b/core/java/com/android/internal/os/SomeArgs.java @@ -73,6 +73,16 @@ public final class SomeArgs { } } + public void complete() { + synchronized (this) { + if (mWaitState != WAIT_WAITING) { + throw new IllegalStateException("Not waiting"); + } + mWaitState = WAIT_FINISHED; + notifyAll(); + } + } + public void recycle() { if (mInPool) { throw new IllegalStateException("Already recycled."); diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index 016d010..9bd2eec 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -27,6 +27,7 @@ import android.animation.Animator; import android.animation.ObjectAnimator; import android.app.ActivityManagerNative; import android.app.SearchManager; +import android.os.Build; import android.os.UserHandle; import android.view.ActionMode; @@ -3531,7 +3532,28 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { public void onDestroyActionMode(ActionMode mode) { mWrapped.onDestroyActionMode(mode); - if (mode == mPrimaryActionMode) { + final boolean isMncApp = mContext.getApplicationInfo().targetSdkVersion + >= Build.VERSION_CODES.MNC; + final boolean isPrimary; + final boolean isFloating; + if (isMncApp) { + isPrimary = mode == mPrimaryActionMode; + isFloating = mode == mFloatingActionMode; + if (!isPrimary && mode.getType() == ActionMode.TYPE_PRIMARY) { + Log.e(TAG, "Destroying unexpected ActionMode instance of TYPE_PRIMARY; " + + mode + " was not the current primary action mode! Expected " + + mPrimaryActionMode); + } + if (!isFloating && mode.getType() == ActionMode.TYPE_FLOATING) { + Log.e(TAG, "Destroying unexpected ActionMode instance of TYPE_FLOATING; " + + mode + " was not the current floating action mode! Expected " + + mFloatingActionMode); + } + } else { + isPrimary = mode.getType() == ActionMode.TYPE_PRIMARY; + isFloating = mode.getType() == ActionMode.TYPE_FLOATING; + } + if (isPrimary) { if (mPrimaryActionModePopup != null) { removeCallbacks(mShowPrimaryActionModePopup); } @@ -3569,7 +3591,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } mPrimaryActionMode = null; - } else if (mode == mFloatingActionMode) { + } else if (isFloating) { cleanupFloatingActionModeViews(); mFloatingActionMode = null; } diff --git a/core/java/com/android/internal/util/XmlUtils.java b/core/java/com/android/internal/util/XmlUtils.java index 32746c2..6393fba 100644 --- a/core/java/com/android/internal/util/XmlUtils.java +++ b/core/java/com/android/internal/util/XmlUtils.java @@ -20,6 +20,7 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Bitmap.CompressFormat; import android.net.Uri; +import android.text.TextUtils; import android.util.ArrayMap; import android.util.Base64; import android.util.Xml; @@ -45,6 +46,8 @@ import java.util.Set; /** {@hide} */ public class XmlUtils { + private static final String STRING_ARRAY_SEPARATOR = ":"; + public static void skipCurrentTag(XmlPullParser parser) throws XmlPullParserException, IOException { int outerDepth = parser.getDepth(); diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java index b3f688b..ca6fe61 100644 --- a/core/java/com/android/internal/widget/FloatingToolbar.java +++ b/core/java/com/android/internal/widget/FloatingToolbar.java @@ -285,7 +285,6 @@ public final class FloatingToolbar { private final Context mContext; private final View mParent; - private final int[] mParentPositionOnScreen = new int[2]; private final PopupWindow mPopupWindow; private final ViewGroup mContentContainer; private final int mMarginHorizontal; @@ -339,7 +338,8 @@ public final class FloatingToolbar { }; private final Rect mViewPortOnScreen = new Rect(); - private final Point mCoordsOnScreen = new Point(); + private final Point mCoordsOnWindow = new Point(); + private final int[] mTmpCoords = new int[2]; private final Rect mTmpRect = new Rect(); private final Region mTouchableRegion = new Region(); @@ -450,13 +450,11 @@ public final class FloatingToolbar { } refreshCoordinatesAndOverflowDirection(contentRectOnScreen); preparePopupContent(); - // We need to specify the offset relative to mParent. + // We need to specify the position in window coordinates. // TODO: Consider to use PopupWindow.setLayoutInScreenEnabled(true) so that we can // specify the popup poision in screen coordinates. - mParent.getLocationOnScreen(mParentPositionOnScreen); - final int relativeX = mCoordsOnScreen.x - mParentPositionOnScreen[0]; - final int relativeY = mCoordsOnScreen.y - mParentPositionOnScreen[1]; - mPopupWindow.showAtLocation(mParent, Gravity.NO_GRAVITY, relativeX, relativeY); + mPopupWindow.showAtLocation(mParent, Gravity.NO_GRAVITY, mCoordsOnWindow.x, + mCoordsOnWindow.y); setTouchableSurfaceInsetsComputer(); runShowAnimation(); } @@ -519,13 +517,10 @@ public final class FloatingToolbar { cancelOverflowAnimations(); refreshCoordinatesAndOverflowDirection(contentRectOnScreen); preparePopupContent(); - // We need to specify the offset relative to mParent. + // We need to specify the position in window coordinates. // TODO: Consider to use PopupWindow.setLayoutInScreenEnabled(true) so that we can // specify the popup poision in screen coordinates. - mParent.getLocationOnScreen(mParentPositionOnScreen); - final int relativeX = mCoordsOnScreen.x - mParentPositionOnScreen[0]; - final int relativeY = mCoordsOnScreen.y - mParentPositionOnScreen[1]; - mPopupWindow.update(relativeX, relativeY, getWidth(), getHeight()); + mPopupWindow.update(mCoordsOnWindow.x, mCoordsOnWindow.y, getWidth(), getHeight()); } /** @@ -624,7 +619,22 @@ public final class FloatingToolbar { mOverflowPanel.setOverflowDirection(mOverflowDirection); } - mCoordsOnScreen.set(x, y); + // We later specify the location of PopupWindow relative to the attached window. + // The idea here is that 1) we can get the location of a View in both window coordinates + // and screen coordiantes, where the offset between them should be equal to the window + // origin, and 2) we can use an arbitrary for this calculation while calculating the + // location of the rootview is supposed to be least expensive. + // TODO: Consider to use PopupWindow.setLayoutInScreenEnabled(true) so that we can avoid + // the following calculation. + mParent.getRootView().getLocationOnScreen(mTmpCoords); + int rootViewLeftOnScreen = mTmpCoords[0]; + int rootViewTopOnScreen = mTmpCoords[1]; + mParent.getRootView().getLocationInWindow(mTmpCoords); + int rootViewLeftOnWindow = mTmpCoords[0]; + int rootViewTopOnWindow = mTmpCoords[1]; + int windowLeftOnScreen = rootViewLeftOnScreen - rootViewLeftOnWindow; + int windowTopOnScreen = rootViewTopOnScreen - rootViewTopOnWindow; + mCoordsOnWindow.set(x - windowLeftOnScreen, y - windowTopOnScreen); } private int getToolbarHeightWithVerticalMargin() { diff --git a/core/java/com/android/internal/widget/IRemoteViewsAdapterConnection.aidl b/core/java/com/android/internal/widget/IRemoteViewsAdapterConnection.aidl index 7eb2aef..7294124 100644 --- a/core/java/com/android/internal/widget/IRemoteViewsAdapterConnection.aidl +++ b/core/java/com/android/internal/widget/IRemoteViewsAdapterConnection.aidl @@ -19,7 +19,7 @@ package com.android.internal.widget; import android.os.IBinder; /** {@hide} */ -interface IRemoteViewsAdapterConnection { +oneway interface IRemoteViewsAdapterConnection { void onServiceConnected(IBinder service); void onServiceDisconnected(); } |
