diff options
Diffstat (limited to 'core/java')
50 files changed, 1105 insertions, 859 deletions
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java index 6503d89..951fe49 100644 --- a/core/java/android/animation/AnimatorSet.java +++ b/core/java/android/animation/AnimatorSet.java @@ -16,9 +16,10 @@ package android.animation; +import android.util.ArrayMap; + import java.util.ArrayList; import java.util.Collection; -import java.util.HashMap; import java.util.List; /** @@ -68,7 +69,7 @@ public final class AnimatorSet extends Animator { * to a single node representing that Animator, not create a new Node * if one already exists. */ - private HashMap<Animator, Node> mNodeMap = new HashMap<Animator, Node>(); + private ArrayMap<Animator, Node> mNodeMap = new ArrayMap<Animator, Node>(); /** * Set of all nodes created for this AnimatorSet. This list is used upon @@ -646,7 +647,7 @@ public final class AnimatorSet extends Animator { anim.mTerminated = false; anim.mStarted = false; anim.mPlayingSet = new ArrayList<Animator>(); - anim.mNodeMap = new HashMap<Animator, Node>(); + anim.mNodeMap = new ArrayMap<Animator, Node>(); anim.mNodes = new ArrayList<Node>(nodeCount); anim.mSortedNodes = new ArrayList<Node>(nodeCount); anim.mReversible = mReversible; diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 9968dbb..49f5099 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -3841,10 +3841,7 @@ public class Activity extends ContextThemeWrapper mStartedActivity = true; } - final View decor = mWindow != null ? mWindow.peekDecorView() : null; - if (decor != null) { - decor.cancelPendingInputEvents(); - } + cancelInputsAndStartExitTransition(options); // TODO Consider clearing/flushing other event sources and events for child windows. } else { if (options != null) { @@ -3855,6 +3852,18 @@ public class Activity extends ContextThemeWrapper mParent.startActivityFromChild(this, intent, requestCode); } } + } + + /** + * Cancels pending inputs and if an Activity Transition is to be run, starts the transition. + * + * @param options The ActivityOptions bundle used to start an Activity. + */ + private void cancelInputsAndStartExitTransition(Bundle options) { + final View decor = mWindow != null ? mWindow.peekDecorView() : null; + if (decor != null) { + decor.cancelPendingInputEvents(); + } if (options != null && !isTopOfTask()) { mActivityTransitionState.startExitOutTransition(this, options); } @@ -3872,9 +3881,6 @@ public class Activity extends ContextThemeWrapper */ public void startActivityForResultAsUser(Intent intent, int requestCode, @Nullable Bundle options, UserHandle user) { - if (options != null) { - mActivityTransitionState.startExitOutTransition(this, options); - } if (mParent != null) { throw new RuntimeException("Can't be called from a child"); } @@ -3896,10 +3902,7 @@ public class Activity extends ContextThemeWrapper mStartedActivity = true; } - final View decor = mWindow != null ? mWindow.peekDecorView() : null; - if (decor != null) { - decor.cancelPendingInputEvents(); - } + cancelInputsAndStartExitTransition(options); } /** @@ -3925,6 +3928,7 @@ public class Activity extends ContextThemeWrapper mToken, mEmbeddedID, -1, ar.getResultCode(), ar.getResultData()); } + cancelInputsAndStartExitTransition(options); } /** @@ -3948,6 +3952,7 @@ public class Activity extends ContextThemeWrapper mToken, mEmbeddedID, -1, ar.getResultCode(), ar.getResultData()); } + cancelInputsAndStartExitTransition(options); } /** @@ -4380,6 +4385,7 @@ public class Activity extends ContextThemeWrapper mToken, child.mEmbeddedID, requestCode, ar.getResultCode(), ar.getResultData()); } + cancelInputsAndStartExitTransition(options); } /** @@ -4431,9 +4437,6 @@ public class Activity extends ContextThemeWrapper @Override public void startActivityForResult( String who, Intent intent, int requestCode, @Nullable Bundle options) { - if (options != null) { - mActivityTransitionState.startExitOutTransition(this, options); - } Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, who, @@ -4443,6 +4446,7 @@ public class Activity extends ContextThemeWrapper mToken, who, requestCode, ar.getResultCode(), ar.getResultData()); } + cancelInputsAndStartExitTransition(options); } /** diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index bde8f39..40eb799 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -17,6 +17,7 @@ package android.app; import android.annotation.NonNull; +import android.content.ComponentName; /** * Activity manager local system service interface. @@ -48,4 +49,10 @@ public abstract class ActivityManagerInternal { */ public abstract void release(); } + + /** + * Returns home activity for the specified user. + * @param userId ID of the user or {@link android.os.UserHandle#USER_ALL} + */ + public abstract ComponentName getHomeActivityForUser(int userId); } diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java index 968c956..fa81412 100644 --- a/core/java/android/app/ActivityTransitionCoordinator.java +++ b/core/java/android/app/ActivityTransitionCoordinator.java @@ -31,6 +31,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewGroupOverlay; import android.view.ViewParent; +import android.view.ViewRootImpl; import android.view.ViewTreeObserver; import android.view.Window; import android.widget.ImageView; @@ -187,11 +188,6 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { */ public static final int MSG_SHARED_ELEMENT_DESTINATION = 107; - /** - * Send the shared element positions. - */ - public static final int MSG_SEND_SHARED_ELEMENT_DESTINATION = 108; - private Window mWindow; final protected ArrayList<String> mAllSharedElementNames; final protected ArrayList<View> mSharedElements = new ArrayList<View>(); @@ -207,6 +203,8 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { new ArrayList<GhostViewListeners>(); private ArrayMap<View, Float> mOriginalAlphas = new ArrayMap<View, Float>(); private ArrayList<Matrix> mSharedElementParentMatrices; + private boolean mSharedElementTransitionComplete; + private boolean mViewsTransitionComplete; public ActivityTransitionCoordinator(Window window, ArrayList<String> allSharedElementNames, @@ -219,6 +217,11 @@ 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); @@ -878,6 +881,32 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { } } + protected boolean isViewsTransitionComplete() { + return mViewsTransitionComplete; + } + + protected void viewsTransitionComplete() { + mViewsTransitionComplete = true; + startInputWhenTransitionsComplete(); + } + + protected void sharedElementTransitionComplete() { + mSharedElementTransitionComplete = true; + startInputWhenTransitionsComplete(); + } + private void startInputWhenTransitionsComplete() { + if (mViewsTransitionComplete && mSharedElementTransitionComplete) { + final View decor = getDecor(); + if (decor != null) { + final ViewRootImpl viewRoot = decor.getViewRootImpl(); + viewRoot.setPausedForTransition(false); + } + onTransitionsComplete(); + } + } + + protected void onTransitionsComplete() {} + protected class ContinueTransitionListener extends Transition.TransitionListenerAdapter { @Override public void onTransitionStart(Transition transition) { diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java index b0fda9c..5e7bd0d 100644 --- a/core/java/android/app/AlarmManager.java +++ b/core/java/android/app/AlarmManager.java @@ -71,10 +71,7 @@ import java.io.IOException; * {@link android.content.Context#getSystemService * Context.getSystemService(Context.ALARM_SERVICE)}. */ -public class AlarmManager -{ - private static final String TAG = "AlarmManager"; - +public class AlarmManager { /** * Alarm time in {@link System#currentTimeMillis System.currentTimeMillis()} * (wall clock time in UTC), which will wake up the device when @@ -558,7 +555,93 @@ public class AlarmManager long intervalMillis, PendingIntent operation) { setImpl(type, triggerAtMillis, WINDOW_HEURISTIC, intervalMillis, 0, operation, null, null); } - + + /** + * Like {@link #set(int, long, PendingIntent)}, but this alarm will be allowed to execute + * even when the system is in low-power idle modes. This type of alarm must <b>only</b> + * be used for situations where it is actually required that the alarm go off while in + * idle -- a reasonable example would be for a calendar notification that should make a + * sound so the user is aware of it. These alarms can significantly impact the power use + * of the device when idle (and thus cause significant battery blame to the app scheduling + * them), so they should be used with care. + * + * <p>Unlike other alarms, the system is free to reschedule this type of alarm to happen + * out of order with any other alarms, even those from the same app. This will clearly happen + * when the device is idle (since this alarm can go off while idle, when any other alarms + * from the app will be held until later), but may also happen even when not idle.</p> + * + * <p>Regardless of the app's target SDK version, this call always allows batching of the + * alarm.</p> + * + * @param type One of {@link #ELAPSED_REALTIME}, {@link #ELAPSED_REALTIME_WAKEUP}, + * {@link #RTC}, or {@link #RTC_WAKEUP}. + * @param triggerAtMillis time in milliseconds that the alarm should go + * off, using the appropriate clock (depending on the alarm type). + * @param operation Action to perform when the alarm goes off; + * typically comes from {@link PendingIntent#getBroadcast + * IntentSender.getBroadcast()}. + * + * @see #set(int, long, PendingIntent) + * @see #setExactAndAllowWhileIdle + * @see #cancel + * @see android.content.Context#sendBroadcast + * @see android.content.Context#registerReceiver + * @see android.content.Intent#filterEquals + * @see #ELAPSED_REALTIME + * @see #ELAPSED_REALTIME_WAKEUP + * @see #RTC + * @see #RTC_WAKEUP + */ + public void setAndAllowWhileIdle(int type, long triggerAtMillis, PendingIntent operation) { + setImpl(type, triggerAtMillis, WINDOW_HEURISTIC, 0, FLAG_ALLOW_WHILE_IDLE, operation, + null, null); + } + + /** + * Like {@link #setExact(int, long, PendingIntent)}, but this alarm will be allowed to execute + * even when the system is in low-power idle modes. If you don't need exact scheduling of + * the alarm but still need to execute while idle, consider using + * {@link #setAndAllowWhileIdle}. This type of alarm must <b>only</b> + * be used for situations where it is actually required that the alarm go off while in + * idle -- a reasonable example would be for a calendar notification that should make a + * sound so the user is aware of it. These alarms can significantly impact the power use + * of the device when idle (and thus cause significant battery blame to the app scheduling + * them), so they should be used with care. + * + * <p>Unlike other alarms, the system is free to reschedule this type of alarm to happen + * out of order with any other alarms, even those from the same app. This will clearly happen + * when the device is idle (since this alarm can go off while idle, when any other alarms + * from the app will be held until later), but may also happen even when not idle. + * Note that the OS will allow itself more flexibility for scheduling these alarms than + * regular exact alarms, since the application has opted into this behavior. When the + * device is idle it may take even more liberties with scheduling in order to optimize + * for battery life.</p> + * + * @param type One of {@link #ELAPSED_REALTIME}, {@link #ELAPSED_REALTIME_WAKEUP}, + * {@link #RTC}, or {@link #RTC_WAKEUP}. + * @param triggerAtMillis time in milliseconds that the alarm should go + * off, using the appropriate clock (depending on the alarm type). + * @param operation Action to perform when the alarm goes off; + * typically comes from {@link PendingIntent#getBroadcast + * IntentSender.getBroadcast()}. + * + * @see #set + * @see #setRepeating + * @see #setWindow + * @see #cancel + * @see android.content.Context#sendBroadcast + * @see android.content.Context#registerReceiver + * @see android.content.Intent#filterEquals + * @see #ELAPSED_REALTIME + * @see #ELAPSED_REALTIME_WAKEUP + * @see #RTC + * @see #RTC_WAKEUP + */ + public void setExactAndAllowWhileIdle(int type, long triggerAtMillis, PendingIntent operation) { + setImpl(type, triggerAtMillis, WINDOW_EXACT, 0, FLAG_ALLOW_WHILE_IDLE, operation, + null, null); + } + /** * Remove any alarms with a matching {@link Intent}. * Any alarm, of any type, whose Intent matches this one (as defined by diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 5aa399b..7104185 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -606,7 +606,7 @@ public class AppOpsManager { UserManager.DISALLOW_CREATE_WINDOWS, //SYSTEM_ALERT_WINDOW null, //ACCESS_NOTIFICATIONS null, //CAMERA - null, //RECORD_AUDIO + UserManager.DISALLOW_RECORD_AUDIO, //RECORD_AUDIO null, //PLAY_AUDIO null, //READ_CLIPBOARD null, //WRITE_CLIPBOARD diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 90293a4..04f6430 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -446,18 +446,40 @@ final class ApplicationPackageManager extends PackageManager { } @Override - public void grantPermission(String packageName, String permissionName, UserHandle user) { + public void grantRuntimePermission(String packageName, String permissionName, + UserHandle user) { + try { + mPM.grantRuntimePermission(packageName, permissionName, user.getIdentifier()); + } catch (RemoteException e) { + throw new RuntimeException("Package manager has died", e); + } + } + + @Override + public void revokeRuntimePermission(String packageName, String permissionName, + UserHandle user) { + try { + mPM.revokeRuntimePermission(packageName, permissionName, user.getIdentifier()); + } catch (RemoteException e) { + throw new RuntimeException("Package manager has died", e); + } + } + + @Override + public int getPermissionFlags(String permissionName, String packageName, UserHandle user) { try { - mPM.grantPermission(packageName, permissionName, user.getIdentifier()); + return mPM.getPermissionFlags(permissionName, packageName, user.getIdentifier()); } catch (RemoteException e) { throw new RuntimeException("Package manager has died", e); } } @Override - public void revokePermission(String packageName, String permissionName, UserHandle user) { + public void updatePermissionFlags(String permissionName, String packageName, + int flagMask, int flagValues, UserHandle user) { try { - mPM.revokePermission(packageName, permissionName, user.getIdentifier()); + mPM.updatePermissionFlags(permissionName, packageName, flagMask, + flagValues, user.getIdentifier()); } catch (RemoteException e) { throw new RuntimeException("Package manager has died", e); } @@ -1571,9 +1593,15 @@ final class ApplicationPackageManager extends PackageManager { final VolumeInfo currentVol = getPrimaryStorageCurrentVolume(); final List<VolumeInfo> vols = storage.getVolumes(); final List<VolumeInfo> candidates = new ArrayList<>(); - for (VolumeInfo vol : vols) { - if (Objects.equals(vol, currentVol) || isPrimaryStorageCandidateVolume(vol)) { - candidates.add(vol); + if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, + storage.getPrimaryStorageUuid()) && currentVol != null) { + // TODO: support moving primary physical to emulated volume + candidates.add(currentVol); + } else { + for (VolumeInfo vol : vols) { + if (Objects.equals(vol, currentVol) || isPrimaryStorageCandidateVolume(vol)) { + candidates.add(vol); + } } } return candidates; @@ -1590,12 +1618,7 @@ final class ApplicationPackageManager extends PackageManager { return false; } - // We can move to public volumes on legacy devices - if ((vol.getType() == VolumeInfo.TYPE_PUBLIC) && vol.getDisk().isDefaultPrimary()) { - return true; - } - - // Otherwise we can move to any private volume + // We can move to any private volume return (vol.getType() == VolumeInfo.TYPE_PRIVATE); } diff --git a/core/java/android/app/AssistAction.java b/core/java/android/app/AssistAction.java deleted file mode 100644 index eb33542..0000000 --- a/core/java/android/app/AssistAction.java +++ /dev/null @@ -1,277 +0,0 @@ -/* - * 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.app; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.net.Uri; -import android.os.Bundle; -import android.text.TextUtils; - -import com.android.internal.util.Preconditions; - -/** - * Helper class for building a {@link Bundle} representing an action being performed by the user, - * to be included in the Bundle generated by {@link Activity#onProvideAssistData}. - * - * @see Activity#onProvideAssistData - */ -public final class AssistAction { - - /** - * Key name for the Bundle containing the schema.org representation of - * an action performed, and should be stored in the Bundle generated by - * {@link Activity#onProvideAssistData}. - */ - public static final String ASSIST_ACTION_KEY = "android:assist_action"; - - /** Bundle key to specify the schema.org ID of the content. */ - public static final String KEY_ID = "@id"; - - /** Bundle key to specify the schema.org type of the content. */ - public static final String KEY_TYPE = "@type"; - - /** Bundle key to specify the name of the content. */ - public static final String KEY_NAME = "name"; - - /** Bundle key to specify the description of the content. */ - public static final String KEY_DESCRIPTION = "description"; - - /** Bundle key to specify the URL of the content. */ - public static final String KEY_URL = "url"; - - /** Bundle key to specify the object of an action. */ - public static final String KEY_ACTION_OBJECT = "object"; - - /** Bundle key to specify the action's status. */ - public static final String KEY_ACTION_STATUS = "actionStatus"; - - /** The act of editing by adding an object to a collection. */ - public static final String TYPE_ADD_ACTION = "AddAction"; - - /** The act of bookmarking an object. */ - public static final String TYPE_BOOKMARK_ACTION = "BookmarkAction"; - - /** The act of liking an object. */ - public static final String TYPE_LIKE_ACTION = "LikeAction"; - - /** The act of consuming audio content. */ - public static final String TYPE_LISTEN_ACTION = "ListenAction"; - - /** The act of consuming static visual content. */ - public static final String TYPE_VIEW_ACTION = "ViewAction"; - - /** The act of expressing a desire about the object. */ - public static final String TYPE_WANT_ACTION = "WantAction"; - - /** The act of watching an object. */ - public static final String TYPE_WATCH_ACTION = "WatchAction"; - - /** The status of an active action. */ - public static final String STATUS_TYPE_ACTIVE = "ActiveActionStatus"; - - /** The status of a completed action. */ - public static final String STATUS_TYPE_COMPLETED = "CompletedActionStatus"; - - private AssistAction() { - } - - /** - * Update the Bundle passed into {@link Activity#onProvideAssistData} with the action Bundle, - * built with {@link ActionBuilder}. - * - * @param assistDataBundle The Bundle provided to {@link Activity#onProvideAssistData}. - * @param actionBundle The Bundle representing an schema.org action. - */ - public static void updateAssistData(Bundle assistDataBundle, Bundle actionBundle) { - Preconditions.checkNotNull(assistDataBundle); - Preconditions.checkNotNull(actionBundle); - - Preconditions.checkNotNull(actionBundle.getString(KEY_TYPE), - "The '@type' property is required in the provided actionBundle"); - assistDataBundle.putParcelable(ASSIST_ACTION_KEY, actionBundle); - } - - /** - * Builds a {@link Bundle} representing a schema.org entity. - */ - public static final class ThingBuilder { - private final Bundle mBundle; - - public ThingBuilder() { - mBundle = new Bundle(); - } - - /** - * Sets the name of the content. - * - * @param name The name of the content. - */ - public ThingBuilder setName(@Nullable String name) { - set(KEY_NAME, name); - return this; - } - - /** - * Sets the app URI of the content. - * - * @param uri The app URI of the content. - */ - public ThingBuilder setUrl(@Nullable Uri uri) { - if (uri != null) { - set(KEY_URL, uri.toString()); - } - return this; - } - - /** - * Sets the ID of the content. - * - * @param id Set the ID of the content. - */ - public ThingBuilder setId(@Nullable String id) { - set(KEY_ID, id); - return this; - } - - /** - * Sets the schema.org type of the content. - * - * @param type The schema.org type. - */ - public ThingBuilder setType(@Nullable String type) { - set(KEY_TYPE, type); - return this; - } - - /** - * Sets the optional description of the content. - * - * @param description The description of the content. - */ - public ThingBuilder setDescription(@Nullable String description) { - set(KEY_DESCRIPTION, description); - return this; - } - - /** - * Sets a property of the content. - * - * @param key The schema.org property. Must not be null. - * @param value The value of the schema.org property. - * If null, the value will be ignored. - */ - public ThingBuilder set(@NonNull String key, @Nullable String value) { - if (value != null) { - mBundle.putString(key, value); - } - return this; - } - - /** - * Sets a property of the content. - * - * @param key The schema.org property. Must not be null. - * @param value The value of the schema.org property represented as a bundle. - * If null, the value will be ignored. - */ - public ThingBuilder set(@NonNull String key, @Nullable Bundle value) { - if (value != null) { - mBundle.putParcelable(key, value); - } - return this; - } - - /** - * Build the {@link Bundle} object representing the schema.org entity. - */ - public Bundle build() { - return mBundle; - } - } - - /** - * Builds a {@link Bundle} representing a schema.org action. - */ - public static final class ActionBuilder { - private final Bundle mBundle; - - public ActionBuilder() { - mBundle = new Bundle(); - } - - /** - * Sets the schema.org type of the action. - * - * @param type The schema.org type. - */ - public ActionBuilder setType(@Nullable String type) { - set(KEY_TYPE, type); - return this; - } - - /** - * Sets the schema.org object of the action. - * - * @param object The schema.org object of the action. - */ - public ActionBuilder setObject(@Nullable Bundle object) { - set(KEY_ACTION_OBJECT, object); - return this; - } - - /** - * Sets a property of the action. - * - * @param key The schema.org property. Must not be null. - * @param value The value of the schema.org property. - * If null, the value will be ignored. - */ - public ActionBuilder set(@NonNull String key, @Nullable String value) { - if (value != null) { - mBundle.putString(key, value); - } - return this; - } - - /** - * Sets a property of the action. - * - * @param key The schema.org property. Must not be null. - * @param value The value of the schema.org property represented as a bundle. - * If null, the value will be ignored. - */ - public ActionBuilder set(@NonNull String key, @Nullable Bundle value) { - if (value != null) { - mBundle.putParcelable(key, value); - } - return this; - } - - /** - * Build the {@link Bundle} object representing the schema.org action. - */ - public Bundle build() { - if (TextUtils.isEmpty(mBundle.getString(KEY_TYPE, null))) { - // Defaults to the base action type http://schema.org/Action. - setType("Action"); - } - - return mBundle; - } - } -} diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java index e84a8da..4db4be0 100644 --- a/core/java/android/app/EnterTransitionCoordinator.java +++ b/core/java/android/app/EnterTransitionCoordinator.java @@ -55,8 +55,6 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { private boolean mWasOpaque; private boolean mAreViewsReady; private boolean mIsViewsTransitionStarted; - private boolean mIsViewsTransitionComplete; - private boolean mIsSharedElementTransitionComplete; private Transition mEnterViewsTransition; public EnterTransitionCoordinator(Activity activity, ResultReceiver resultReceiver, @@ -456,7 +454,7 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { } } if (viewsTransition == null) { - viewTransitionComplete(); + viewsTransitionComplete(); } else { viewsTransition.forceVisibility(View.INVISIBLE, true); final ArrayList<View> transitioningViews = mTransitioningViews; @@ -474,7 +472,7 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { public void onTransitionEnd(Transition transition) { mEnterViewsTransition = null; transition.removeListener(this); - viewTransitionComplete(); + viewsTransitionComplete(); super.onTransitionEnd(transition); } }); @@ -497,18 +495,9 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { return transition; } - private void viewTransitionComplete() { - mIsViewsTransitionComplete = true; - if (mIsSharedElementTransitionComplete) { - moveSharedElementsFromOverlay(); - } - } - - private void sharedElementTransitionComplete() { - mIsSharedElementTransitionComplete = true; - if (mIsViewsTransitionComplete) { - moveSharedElementsFromOverlay(); - } + @Override + protected void onTransitionsComplete() { + moveSharedElementsFromOverlay(); } private void sharedElementTransitionStarted() { diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java index 0f286fb..9ddebb0 100644 --- a/core/java/android/app/ExitTransitionCoordinator.java +++ b/core/java/android/app/ExitTransitionCoordinator.java @@ -46,8 +46,6 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator { private static final String TAG = "ExitTransitionCoordinator"; private static final long MAX_WAIT_MS = 1000; - private boolean mExitComplete; - private Bundle mSharedElementBundle; private boolean mExitNotified; @@ -165,7 +163,7 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator { @Override public void onTransitionEnd(Transition transition) { transition.removeListener(this); - if (mExitComplete) { + if (isViewsTransitionComplete()) { delayCancel(); } } @@ -310,14 +308,14 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator { viewsTransition = configureTransition(getViewsTransition(), true); } if (viewsTransition == null) { - exitTransitionComplete(); + viewsTransitionComplete(); } else { final ArrayList<View> transitioningViews = mTransitioningViews; viewsTransition.addListener(new ContinueTransitionListener() { @Override public void onTransitionEnd(Transition transition) { transition.removeListener(this); - exitTransitionComplete(); + viewsTransitionComplete(); if (mIsHidden && transitioningViews != null) { showViews(transitioningViews, true); } @@ -373,19 +371,15 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator { } } - private void exitTransitionComplete() { - mExitComplete = true; - notifyComplete(); - } - protected boolean isReadyToNotify() { return mSharedElementBundle != null && mResultReceiver != null && mIsBackgroundReady; } - private void sharedElementTransitionComplete() { + @Override + protected void sharedElementTransitionComplete() { mSharedElementBundle = mExitSharedElementBundle == null ? captureSharedElementState() : captureExitSharedElementsState(); - notifyComplete(); + super.sharedElementTransitionComplete(); } private Bundle captureExitSharedElementsState() { @@ -405,6 +399,11 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator { return bundle; } + @Override + protected void onTransitionsComplete() { + notifyComplete(); + } + protected void notifyComplete() { if (isReadyToNotify()) { if (!mSharedElementNotified) { @@ -433,7 +432,7 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator { } private void notifyExitComplete() { - if (!mExitNotified && mExitComplete) { + if (!mExitNotified && isViewsTransitionComplete()) { mExitNotified = true; mResultReceiver.send(MSG_EXIT_TRANSITION_COMPLETE, null); mResultReceiver = null; // done talking diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 391131a..0d00908 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -55,7 +55,6 @@ import android.location.CountryDetector; import android.location.ICountryDetector; import android.location.ILocationManager; import android.location.LocationManager; -import android.media.AudioDevicesManager; import android.media.AudioManager; import android.media.MediaRouter; import android.media.midi.IMidiManager; @@ -701,13 +700,6 @@ final class SystemServiceRegistry { public RadioManager createService(ContextImpl ctx) { return new RadioManager(ctx); }}); - - registerService(Context.AUDIO_DEVICES_SERVICE, AudioDevicesManager.class, - new CachedServiceFetcher<AudioDevicesManager>() { - @Override - public AudioDevicesManager createService(ContextImpl ctx) { - return new AudioDevicesManager(ctx); - }}); } /** @@ -726,7 +718,7 @@ final class SystemServiceRegistry { } /** - * Gets the name of the system-level service that is represented by the specified class. + * Gets the name of the system-level service that is represented by the specified class. */ public static String getSystemServiceName(Class<?> serviceClass) { return SYSTEM_SERVICE_NAMES.get(serviceClass); diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index ae07206..3fb7059 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -4253,11 +4253,7 @@ public class DevicePolicyManager { public void setSystemUpdatePolicy(ComponentName who, SystemUpdatePolicy policy) { if (mService != null) { try { - if (policy != null) { - mService.setSystemUpdatePolicy(who, policy.getPolicyBundle()); - } else { - mService.setSystemUpdatePolicy(who, null); - } + mService.setSystemUpdatePolicy(who, policy); } catch (RemoteException re) { Log.w(TAG, "Error calling setSystemUpdatePolicy", re); } @@ -4272,12 +4268,7 @@ public class DevicePolicyManager { public SystemUpdatePolicy getSystemUpdatePolicy() { if (mService != null) { try { - PersistableBundle bundle = mService.getSystemUpdatePolicy(); - if (bundle != null) { - return new SystemUpdatePolicy(bundle); - } else { - return null; - } + return mService.getSystemUpdatePolicy(); } catch (RemoteException re) { Log.w(TAG, "Error calling getSystemUpdatePolicy", re); } diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index e81e7c1..481ff62 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -17,6 +17,7 @@ package android.app.admin; +import android.app.admin.SystemUpdatePolicy; import android.content.ComponentName; import android.content.Intent; import android.content.IntentFilter; @@ -221,8 +222,8 @@ interface IDevicePolicyManager { void setUserIcon(in ComponentName admin, in Bitmap icon); void sendDeviceInitializerStatus(int statusCode, String description); - void setSystemUpdatePolicy(in ComponentName who, in PersistableBundle policy); - PersistableBundle getSystemUpdatePolicy(); + void setSystemUpdatePolicy(in ComponentName who, in SystemUpdatePolicy policy); + SystemUpdatePolicy getSystemUpdatePolicy(); boolean setKeyguardDisabled(in ComponentName admin, boolean disabled); boolean setStatusBarDisabled(in ComponentName who, boolean disabled); diff --git a/core/java/android/app/admin/SystemUpdatePolicy.aidl b/core/java/android/app/admin/SystemUpdatePolicy.aidl new file mode 100644 index 0000000..58e8d15 --- /dev/null +++ b/core/java/android/app/admin/SystemUpdatePolicy.aidl @@ -0,0 +1,20 @@ +/* +** +** Copyright 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.app.admin; + +parcelable SystemUpdatePolicy; diff --git a/core/java/android/app/admin/SystemUpdatePolicy.java b/core/java/android/app/admin/SystemUpdatePolicy.java index de56cd0..20ddb77 100644 --- a/core/java/android/app/admin/SystemUpdatePolicy.java +++ b/core/java/android/app/admin/SystemUpdatePolicy.java @@ -17,8 +17,15 @@ package android.app.admin; import android.annotation.IntDef; +import android.os.Parcel; +import android.os.Parcelable; import android.os.PersistableBundle; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -28,7 +35,7 @@ import java.lang.annotation.RetentionPolicy; * @see DevicePolicyManager#setSystemUpdatePolicy * @see DevicePolicyManager#getSystemUpdatePolicy */ -public class SystemUpdatePolicy { +public class SystemUpdatePolicy implements Parcelable { /** @hide */ @IntDef({ @@ -39,6 +46,10 @@ public class SystemUpdatePolicy { @interface SystemUpdatePolicyType {} /** + * Unknown policy type, used only internally. + */ + private static final int TYPE_UNKNOWN = -1; + /** * Install system update automatically as soon as one is available. */ public static final int TYPE_INSTALL_AUTOMATIC = 1; @@ -63,45 +74,40 @@ public class SystemUpdatePolicy { private static final String KEY_POLICY_TYPE = "policy_type"; private static final String KEY_INSTALL_WINDOW_START = "install_window_start"; private static final String KEY_INSTALL_WINDOW_END = "install_window_end"; + /** + * The upper boundary of the daily maintenance window: 24 * 60 minutes. + */ + private static final int WINDOW_BOUNDARY = 24 * 60; - private PersistableBundle mPolicy; + @SystemUpdatePolicyType + private int mPolicyType; - public SystemUpdatePolicy() { - mPolicy = new PersistableBundle(); - } + private int mMaintenanceWindowStart; + private int mMaintenanceWindowEnd; - /** - * Construct an SystemUpdatePolicy object from a bundle. - * @hide - */ - public SystemUpdatePolicy(PersistableBundle in) { - mPolicy = new PersistableBundle(in); - } - /** - * Retrieve the underlying bundle where the policy is stored. - * @hide - */ - public PersistableBundle getPolicyBundle() { - return new PersistableBundle(mPolicy); + private SystemUpdatePolicy() { + mPolicyType = TYPE_UNKNOWN; } /** - * Set the policy to: install update automatically as soon as one is available. + * Create a policy object and set it to install update automatically as soon as one is + * available. * * @see #TYPE_INSTALL_AUTOMATIC */ - public void setAutomaticInstallPolicy() { - mPolicy.clear(); - mPolicy.putInt(KEY_POLICY_TYPE, TYPE_INSTALL_AUTOMATIC); + public static SystemUpdatePolicy createAutomaticInstallPolicy() { + SystemUpdatePolicy policy = new SystemUpdatePolicy(); + policy.mPolicyType = TYPE_INSTALL_AUTOMATIC; + return policy; } /** - * Set the policy to: new system update will only be installed automatically when the system - * clock is inside a daily maintenance window. If the start and end times are the same, the - * window is considered to include the WHOLE 24 hours, that is, updates can install at any time. - * If the given window in invalid, a {@link SystemUpdatePolicy.InvalidWindowException} will be - * thrown. If start time is later than end time, the window is considered spanning midnight, + * Create a policy object and set it to: new system update will only be installed automatically + * when the system clock is inside a daily maintenance window. If the start and end times are + * the same, the window is considered to include the WHOLE 24 hours, that is, updates can + * install at any time. If the given window in invalid, a {@link IllegalArgumentException} will + * be thrown. If start time is later than end time, the window is considered spanning midnight, * i.e. end time donates a time on the next day. The maintenance window will last for 30 days, * after which the system should revert back to its normal behavior as if no policy were set. * @@ -111,25 +117,29 @@ public class SystemUpdatePolicy { * midnight in the device's local time. Must be in the range of [0, 1440). * @see #TYPE_INSTALL_WINDOWED */ - public void setWindowedInstallPolicy(int startTime, int endTime) throws InvalidWindowException{ - if (startTime < 0 || startTime >= 1440 || endTime < 0 || endTime >= 1440) { - throw new InvalidWindowException("startTime and endTime must be inside [0, 1440)"); + public static SystemUpdatePolicy createWindowedInstallPolicy(int startTime, int endTime) { + if (startTime < 0 || startTime >= WINDOW_BOUNDARY + || endTime < 0 || endTime >= WINDOW_BOUNDARY) { + throw new IllegalArgumentException("startTime and endTime must be inside [0, 1440)"); } - mPolicy.clear(); - mPolicy.putInt(KEY_POLICY_TYPE, TYPE_INSTALL_WINDOWED); - mPolicy.putInt(KEY_INSTALL_WINDOW_START, startTime); - mPolicy.putInt(KEY_INSTALL_WINDOW_END, endTime); + SystemUpdatePolicy policy = new SystemUpdatePolicy(); + policy.mPolicyType = TYPE_INSTALL_WINDOWED; + policy.mMaintenanceWindowStart = startTime; + policy.mMaintenanceWindowEnd = endTime; + return policy; } /** - * Set the policy to: block installation for a maximum period of 30 days. After expiration the - * system should revert back to its normal behavior as if no policy were set. + * Create a policy object and set it to block installation for a maximum period of 30 days. + * After expiration the system should revert back to its normal behavior as if no policy were + * set. * * @see #TYPE_POSTPONE */ - public void setPostponeInstallPolicy() { - mPolicy.clear(); - mPolicy.putInt(KEY_POLICY_TYPE, TYPE_POSTPONE); + public static SystemUpdatePolicy createPostponeInstallPolicy() { + SystemUpdatePolicy policy = new SystemUpdatePolicy(); + policy.mPolicyType = TYPE_POSTPONE; + return policy; } /** @@ -140,7 +150,7 @@ public class SystemUpdatePolicy { */ @SystemUpdatePolicyType public int getPolicyType() { - return mPolicy.getInt(KEY_POLICY_TYPE, -1); + return mPolicyType; } /** @@ -150,8 +160,8 @@ public class SystemUpdatePolicy { * or -1 if the policy does not have a maintenance window. */ public int getInstallWindowStart() { - if (getPolicyType() == TYPE_INSTALL_WINDOWED) { - return mPolicy.getInt(KEY_INSTALL_WINDOW_START, -1); + if (mPolicyType == TYPE_INSTALL_WINDOWED) { + return mMaintenanceWindowStart; } else { return -1; } @@ -164,26 +174,98 @@ public class SystemUpdatePolicy { * or -1 if the policy does not have a maintenance window. */ public int getInstallWindowEnd() { - if (getPolicyType() == TYPE_INSTALL_WINDOWED) { - return mPolicy.getInt(KEY_INSTALL_WINDOW_END, -1); + if (mPolicyType == TYPE_INSTALL_WINDOWED) { + return mMaintenanceWindowEnd; } else { return -1; } } + /** + * Return if this object represents a valid policy. + * @hide + */ + public boolean isValid() { + if (mPolicyType == TYPE_INSTALL_AUTOMATIC || mPolicyType == TYPE_POSTPONE) { + return true; + } else if (mPolicyType == TYPE_INSTALL_WINDOWED) { + return mMaintenanceWindowStart >= 0 && mMaintenanceWindowStart < WINDOW_BOUNDARY + && mMaintenanceWindowEnd >= 0 && mMaintenanceWindowEnd < WINDOW_BOUNDARY; + } else { + return false; + } + } + @Override public String toString() { - return mPolicy.toString(); + return String.format("SystemUpdatePolicy (type: %d, windowStart: %d, windowEnd: %d)", + mPolicyType, mMaintenanceWindowStart, mMaintenanceWindowEnd); + } + + @Override + public int describeContents() { + return 0; } + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mPolicyType); + dest.writeInt(mMaintenanceWindowStart); + dest.writeInt(mMaintenanceWindowEnd); + } + + public static final Parcelable.Creator<SystemUpdatePolicy> CREATOR = + new Parcelable.Creator<SystemUpdatePolicy>() { + + @Override + public SystemUpdatePolicy createFromParcel(Parcel source) { + SystemUpdatePolicy policy = new SystemUpdatePolicy(); + policy.mPolicyType = source.readInt(); + policy.mMaintenanceWindowStart = source.readInt(); + policy.mMaintenanceWindowEnd = source.readInt(); + return policy; + } + + @Override + public SystemUpdatePolicy[] newArray(int size) { + return new SystemUpdatePolicy[size]; + } + }; + + /** - * Exception thrown by {@link SystemUpdatePolicy#setWindowedInstallPolicy(int, int)} in case the - * specified window is invalid. + * @hide */ - public static class InvalidWindowException extends Exception { - public InvalidWindowException(String reason) { - super(reason); + public static SystemUpdatePolicy restoreFromXml(XmlPullParser parser) { + try { + SystemUpdatePolicy policy = new SystemUpdatePolicy(); + String value = parser.getAttributeValue(null, KEY_POLICY_TYPE); + if (value != null) { + policy.mPolicyType = Integer.parseInt(value); + + value = parser.getAttributeValue(null, KEY_INSTALL_WINDOW_START); + if (value != null) { + policy.mMaintenanceWindowStart = Integer.parseInt(value); + } + value = parser.getAttributeValue(null, KEY_INSTALL_WINDOW_END); + if (value != null) { + policy.mMaintenanceWindowEnd = Integer.parseInt(value); + } + return policy; + } + } catch (NumberFormatException e) { + // Fail through } + return null; + } + + /** + * @hide + */ + public void saveToXml(XmlSerializer out) throws IOException { + out.attribute(null, KEY_POLICY_TYPE, Integer.toString(mPolicyType)); + out.attribute(null, KEY_INSTALL_WINDOW_START, Integer.toString(mMaintenanceWindowStart)); + out.attribute(null, KEY_INSTALL_WINDOW_END, Integer.toString(mMaintenanceWindowEnd)); } } diff --git a/core/java/android/app/usage/IUsageStatsManager.aidl b/core/java/android/app/usage/IUsageStatsManager.aidl index 23659e3..254408a 100644 --- a/core/java/android/app/usage/IUsageStatsManager.aidl +++ b/core/java/android/app/usage/IUsageStatsManager.aidl @@ -30,6 +30,6 @@ interface IUsageStatsManager { ParceledListSlice queryConfigurationStats(int bucketType, long beginTime, long endTime, String callingPackage); UsageEvents queryEvents(long beginTime, long endTime, String callingPackage); - void setAppIdle(String packageName, boolean idle, int userId); - boolean isAppIdle(String packageName, int userId); + void setAppInactive(String packageName, boolean inactive, int userId); + boolean isAppInactive(String packageName, int userId); } diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java index abfc435..81c7422 100644 --- a/core/java/android/app/usage/UsageStats.java +++ b/core/java/android/app/usage/UsageStats.java @@ -46,6 +46,13 @@ public final class UsageStats implements Parcelable { public long mLastTimeUsed; /** + * Last time the package was used and the beginning of the idle countdown. + * This uses a different timebase that is about how much the device has been in use in general. + * {@hide} + */ + public long mBeginIdleTime; + + /** * {@hide} */ public long mTotalTimeInForeground; @@ -74,6 +81,7 @@ public final class UsageStats implements Parcelable { mTotalTimeInForeground = stats.mTotalTimeInForeground; mLaunchCount = stats.mLaunchCount; mLastEvent = stats.mLastEvent; + mBeginIdleTime = stats.mBeginIdleTime; } public String getPackageName() { @@ -110,6 +118,15 @@ public final class UsageStats implements Parcelable { } /** + * @hide + * Get the last time this package was active, measured in milliseconds. This timestamp + * uses a timebase that represents how much the device was used and not wallclock time. + */ + public long getBeginIdleTime() { + return mBeginIdleTime; + } + + /** * Get the total time this package spent in the foreground, measured in milliseconds. */ public long getTotalTimeInForeground() { @@ -133,6 +150,7 @@ public final class UsageStats implements Parcelable { mLastEvent = right.mLastEvent; mEndTimeStamp = right.mEndTimeStamp; mLastTimeUsed = right.mLastTimeUsed; + mBeginIdleTime = right.mBeginIdleTime; } mBeginTimeStamp = Math.min(mBeginTimeStamp, right.mBeginTimeStamp); mTotalTimeInForeground += right.mTotalTimeInForeground; @@ -153,6 +171,7 @@ public final class UsageStats implements Parcelable { dest.writeLong(mTotalTimeInForeground); dest.writeInt(mLaunchCount); dest.writeInt(mLastEvent); + dest.writeLong(mBeginIdleTime); } public static final Creator<UsageStats> CREATOR = new Creator<UsageStats>() { @@ -166,6 +185,7 @@ public final class UsageStats implements Parcelable { stats.mTotalTimeInForeground = in.readLong(); stats.mLaunchCount = in.readInt(); stats.mLastEvent = in.readInt(); + stats.mBeginIdleTime = in.readLong(); return stats; } diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java index 8a01d66..c74bbdd 100644 --- a/core/java/android/app/usage/UsageStatsManager.java +++ b/core/java/android/app/usage/UsageStatsManager.java @@ -220,15 +220,15 @@ public final class UsageStatsManager { } /** - * Returns whether the specified app is currently considered idle. This will be true if the + * Returns whether the specified app is currently considered inactive. This will be true if the * app hasn't been used directly or indirectly for a period of time defined by the system. This * could be of the order of several hours or days. * @param packageName The package name of the app to query - * @return whether the app is currently considered idle + * @return whether the app is currently considered inactive */ - public boolean isAppIdle(String packageName) { + public boolean isAppInactive(String packageName) { try { - return mService.isAppIdle(packageName, UserHandle.myUserId()); + return mService.isAppInactive(packageName, UserHandle.myUserId()); } catch (RemoteException e) { // fall through and return default } diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java index 8b3fc2e..7bcc038 100644 --- a/core/java/android/app/usage/UsageStatsManagerInternal.java +++ b/core/java/android/app/usage/UsageStatsManagerInternal.java @@ -69,14 +69,6 @@ public abstract class UsageStatsManagerInternal { public abstract boolean isAppIdle(String packageName, int userId); /** - * Returns the most recent time that the specified package was active for the given user. - * @param packageName The package to search. - * @param userId The user id of the user of interest. - * @return The timestamp of when the package was last used, or -1 if it hasn't been used. - */ - public abstract long getLastPackageAccessTime(String packageName, int userId); - - /** * Sets up a listener for changes to packages being accessed. * @param listener A listener within the system process. */ diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl index a3eceb5..7a894ae 100644 --- a/core/java/android/bluetooth/IBluetooth.aidl +++ b/core/java/android/bluetooth/IBluetooth.aidl @@ -101,8 +101,8 @@ interface IBluetooth void getActivityEnergyInfoFromController(); BluetoothActivityEnergyInfo reportActivityInfo(); - // for dumpsys support - String dump(); + // For dumpsys support + void dump(in ParcelFileDescriptor fd); void onLeServiceUp(); void onBrEdrDown(); } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 17f946b..a434c7b 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -3136,16 +3136,6 @@ public abstract class Context { public static final String RADIO_SERVICE = "radio"; /** - * Use with {@link #getSystemService} to retrieve a - * {@link android.media.AudioDevicesManager} for handling device enumeration & notification. - * - * @see #getSystemService - * @see android.media.AudioDevicesManager - */ - public static final String AUDIO_DEVICES_SERVICE = "audio_devices_manager"; - - - /** * Determine whether the given permission is allowed for a particular * process and user ID running in the system. * diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 6f543a8..7d76760 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -3365,14 +3365,6 @@ public class Intent implements Parcelable, Cloneable { public static final String EXTRA_INITIAL_INTENTS = "android.intent.extra.INITIAL_INTENTS"; /** - * A Parcelable[] of {@link android.service.chooser.ChooserTarget ChooserTarget} objects - * as set with {@link #putExtra(String, Parcelable[])} representing additional app-specific - * targets to place at the front of the list of choices. Shown to the user with - * {@link #ACTION_CHOOSER}. - */ - public static final String EXTRA_CHOOSER_TARGETS = "android.intent.extra.CHOOSER_TARGETS"; - - /** * A Bundle forming a mapping of potential target package names to different extras Bundles * to add to the default intent extras in {@link #EXTRA_INTENT} when used with * {@link #ACTION_CHOOSER}. Each key should be a package name. The package need not diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 94b0223..ddff782 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -96,9 +96,14 @@ interface IPackageManager { void removePermission(String name); - void grantPermission(String packageName, String permissionName, int userId); + void grantRuntimePermission(String packageName, String permissionName, int userId); - void revokePermission(String packageName, String permissionName, int userId); + void revokeRuntimePermission(String packageName, String permissionName, int userId); + + int getPermissionFlags(String permissionName, String packageName, int userId); + + void updatePermissionFlags(String permissionName, String packageName, int flagMask, + int flagValues, int userId); boolean isProtectedBroadcast(String actionName); diff --git a/core/java/android/content/pm/LauncherActivityInfo.java b/core/java/android/content/pm/LauncherActivityInfo.java index 87b97aa..6827d7a 100644 --- a/core/java/android/content/pm/LauncherActivityInfo.java +++ b/core/java/android/content/pm/LauncherActivityInfo.java @@ -103,20 +103,30 @@ public class LauncherActivityInfo { * density DPI values from {@link DisplayMetrics}. * @see #getBadgedIcon(int) * @see DisplayMetrics - * @return The drawable associated with the activity + * @return The drawable associated with the activity. */ public Drawable getIcon(int density) { - int iconRes = mResolveInfo.getIconResource(); - Resources resources = null; - Drawable icon = null; - // Get the preferred density icon from the app's resources - if (density != 0 && iconRes != 0) { - try { - resources = mPm.getResourcesForApplication(mActivityInfo.applicationInfo); - icon = resources.getDrawableForDensity(iconRes, density); - } catch (NameNotFoundException | Resources.NotFoundException exc) { - } + final int iconRes = mResolveInfo.getIconResource(); + Drawable icon = getDrawableForDensity(iconRes, density); + // Get the default density icon + if (icon == null) { + icon = mResolveInfo.loadIcon(mPm); } + return icon; + } + + /** + * Returns the icon for this activity, without any badging for the profile. + * This function can get the icon no matter the icon needs to be badged or not. + * @param density The preferred density of the icon, zero for default density. Use + * density DPI values from {@link DisplayMetrics}. + * @see #getBadgedIcon(int) + * @see DisplayMetrics + * @return The drawable associated with the activity. + */ + private Drawable getOriginalIcon(int density) { + final int iconRes = mResolveInfo.getIconResourceInternal(); + Drawable icon = getDrawableForDensity(iconRes, density); // Get the default density icon if (icon == null) { icon = mResolveInfo.loadIcon(mPm); @@ -125,6 +135,27 @@ public class LauncherActivityInfo { } /** + * Returns the drawable for this activity, without any badging for the profile. + * @param resource id of the drawable. + * @param density The preferred density of the icon, zero for default density. Use + * density DPI values from {@link DisplayMetrics}. + * @see DisplayMetrics + * @return The drawable associated with the resource id. + */ + private Drawable getDrawableForDensity(int iconRes, int density) { + // Get the preferred density icon from the app's resources + if (density != 0 && iconRes != 0) { + try { + final Resources resources + = mPm.getResourcesForApplication(mActivityInfo.applicationInfo); + return resources.getDrawableForDensity(iconRes, density); + } catch (NameNotFoundException | Resources.NotFoundException exc) { + } + } + return null; + } + + /** * Returns the application flags from the ApplicationInfo of the activity. * * @return Application flags @@ -167,7 +198,7 @@ public class LauncherActivityInfo { * @return A badged icon for the activity. */ public Drawable getBadgedIcon(int density) { - Drawable originalIcon = getIcon(density); + Drawable originalIcon = getOriginalIcon(density); if (originalIcon instanceof BitmapDrawable) { return mPm.getUserBadgedIcon(originalIcon, mUser); diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 51fa075..6401fe6 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -1888,6 +1888,57 @@ public abstract class PackageManager { public static final String EXTRA_FAILURE_EXISTING_PERMISSION = "android.content.pm.extra.FAILURE_EXISTING_PERMISSION"; + /** + * Permission flag: The permission is set in its current state + * by the user and apps can still request it at runtime. + * + * @hide + */ + @SystemApi + public static final int FLAG_PERMISSION_USER_SET = 1 << 0; + + /** + * Permission flag: The permission is set in its current state + * by the user and it is fixed, i.e. apps can no longer request + * this permission. + * + * @hide + */ + @SystemApi + public static final int FLAG_PERMISSION_USER_FIXED = 1 << 1; + + /** + * Permission flag: The permission is set in its current state + * by device policy and neither apps nor the user can change + * its state. + * + * @hide + */ + @SystemApi + public static final int FLAG_PERMISSION_POLICY_FIXED = 1 << 2; + + /** + * Permission flag: The permission is set in a granted state but + * access to resources it guards is restricted by other means to + * enable revoking a permission on legacy apps that do not support + * runtime permissions. If this permission is upgraded to runtime + * because the app was updated to support runtime permissions, the + * the permission will be revoked in the upgrade process. + * + * @hide + */ + @SystemApi + public static final int FLAG_PERMISSION_REVOKE_ON_UPGRADE = 1 << 3; + + + /** + * Mask for all permission flags. + * + * @hide + */ + @SystemApi + public static final int MASK_PERMISSION_FLAGS = 0xF; + /** * Retrieve overall information about an application package that is * installed on the system. @@ -2374,6 +2425,20 @@ public abstract class PackageManager { */ public abstract void removePermission(String name); + + /** + * Permission flags set when granting or revoking a permission. + * + * @hide + */ + @SystemApi + @IntDef({FLAG_PERMISSION_USER_SET, + FLAG_PERMISSION_USER_FIXED, + FLAG_PERMISSION_POLICY_FIXED, + FLAG_PERMISSION_REVOKE_ON_UPGRADE}) + @Retention(RetentionPolicy.SOURCE) + public @interface PermissionFlags {} + /** * Grant a runtime permission to an application which the application does not * already have. The permission must have been requested by the application. @@ -2389,19 +2454,20 @@ public abstract class PackageManager { * @param permissionName The permission name to grant. * @param user The user for which to grant the permission. * - * @see #revokePermission(String, String, android.os.UserHandle) + * @see #revokeRuntimePermission(String, String, android.os.UserHandle) + * @see android.content.pm.PackageManager.PermissionFlags * * @hide */ @SystemApi - public abstract void grantPermission(@NonNull String packageName, + public abstract void grantRuntimePermission(@NonNull String packageName, @NonNull String permissionName, @NonNull UserHandle user); /** * Revoke a runtime permission that was previously granted by {@link - * #grantPermission(String, String, android.os.UserHandle)}. The permission - * must have been requested by and granted to the application. If the - * application is not allowed to hold the permission, a {@link + * #grantRuntimePermission(String, String, android.os.UserHandle)}. The + * permission must have been requested by and granted to the application. + * If the application is not allowed to hold the permission, a {@link * java.lang.SecurityException} is thrown. * <p> * <strong>Note: </strong>Using this API requires holding @@ -2413,15 +2479,47 @@ public abstract class PackageManager { * @param permissionName The permission name to revoke. * @param user The user for which to revoke the permission. * - * @see #grantPermission(String, String, android.os.UserHandle) + * @see #grantRuntimePermission(String, String, android.os.UserHandle) + * @see android.content.pm.PackageManager.PermissionFlags * * @hide */ @SystemApi - public abstract void revokePermission(@NonNull String packageName, + public abstract void revokeRuntimePermission(@NonNull String packageName, @NonNull String permissionName, @NonNull UserHandle user); /** + * Gets the state flags associated with a permission. + * + * @param permissionName The permission for which to get the flags. + * @param packageName The package name for which to get the flags. + * @param user The user for which to get permission flags. + * @return The permission flags. + * + * @hide + */ + @SystemApi + public abstract @PermissionFlags int getPermissionFlags(String permissionName, + String packageName, @NonNull UserHandle user); + + /** + * Updates the flags associated with a permission by replacing the flags in + * the specified mask with the provided flag values. + * + * @param permissionName The permission for which to update the flags. + * @param packageName The package name for which to update the flags. + * @param flagMask The flags which to replace. + * @param flagValues The flags with which to replace. + * @param user The user for which to update the permission flags. + * + * @hide + */ + @SystemApi + public abstract void updatePermissionFlags(String permissionName, + String packageName, @PermissionFlags int flagMask, int flagValues, + @NonNull UserHandle user); + + /** * Returns an {@link android.content.Intent} suitable for passing to * {@link android.app.Activity#startActivityForResult(android.content.Intent, int)} * which prompts the user to grant permissions to this application. diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java index 05f5e90..649fdb4 100644 --- a/core/java/android/content/pm/ResolveInfo.java +++ b/core/java/android/content/pm/ResolveInfo.java @@ -221,16 +221,16 @@ public class ResolveInfo implements Parcelable { } return ci.loadIcon(pm); } - + /** * Return the icon resource identifier to use for this match. If the * match defines an icon, that is used; else if the activity defines * an icon, that is used; else, the application icon is used. - * + * This function does not check noResourceId flag. + * * @return The icon associated with this match. */ - public final int getIconResource() { - if (noResourceId) return 0; + final int getIconResourceInternal() { if (icon != 0) return icon; final ComponentInfo ci = getComponentInfo(); if (ci != null) { @@ -239,6 +239,18 @@ public class ResolveInfo implements Parcelable { return 0; } + /** + * Return the icon resource identifier to use for this match. If the + * match defines an icon, that is used; else if the activity defines + * an icon, that is used; else, the application icon is used. + * + * @return The icon associated with this match. + */ + public final int getIconResource() { + if (noResourceId) return 0; + return getIconResourceInternal(); + } + public void dump(Printer pw, String prefix) { if (filter != null) { pw.println(prefix + "Filter:"); diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl index 9bc967f..e4ab3f2 100644 --- a/core/java/android/hardware/usb/IUsbManager.aidl +++ b/core/java/android/hardware/usb/IUsbManager.aidl @@ -85,9 +85,6 @@ interface IUsbManager /* Sets the current USB function. */ void setCurrentFunction(String function, boolean makeDefault); - /* Sets the file path for USB mass storage backing file. */ - void setMassStorageBackingFile(String path); - /* Allow USB debugging from the attached host. If alwaysAllow is true, add the * the public key to list of host keys that the user has approved. */ diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java index f283051..a45d4ca 100644 --- a/core/java/android/hardware/usb/UsbManager.java +++ b/core/java/android/hardware/usb/UsbManager.java @@ -410,28 +410,6 @@ public class UsbManager { } } - private static boolean propertyContainsFunction(String property, String function) { - String functions = SystemProperties.get(property, ""); - int index = functions.indexOf(function); - if (index < 0) return false; - if (index > 0 && functions.charAt(index - 1) != ',') return false; - int charAfter = index + function.length(); - if (charAfter < functions.length() && functions.charAt(charAfter) != ',') return false; - return true; - } - - /** - * Returns true if the specified USB function is currently enabled. - * - * @param function name of the USB function - * @return true if the USB function is enabled. - * - * {@hide} - */ - public boolean isFunctionEnabled(String function) { - return propertyContainsFunction("sys.usb.config", function); - } - /** * Returns the current default USB function. * @@ -465,19 +443,4 @@ public class UsbManager { Log.e(TAG, "RemoteException in setCurrentFunction", e); } } - - /** - * Sets the file path for USB mass storage backing file. - * - * @param path backing file path - * - * {@hide} - */ - public void setMassStorageBackingFile(String path) { - try { - mService.setMassStorageBackingFile(path); - } catch (RemoteException e) { - Log.e(TAG, "RemoteException in setDefaultFunction", e); - } - } } diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index d8c3361..26878c0 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -496,6 +496,8 @@ public class ConnectivityManager { * Tests if a given integer represents a valid network type. * @param networkType the type to be tested * @return a boolean. {@code true} if the type is valid, else {@code false} + * @deprecated All APIs accepting a network type are deprecated. There should be no need to + * validate a network type. */ public static boolean isNetworkTypeValid(int networkType) { return networkType >= 0 && networkType <= MAX_NETWORK_TYPE; diff --git a/core/java/android/os/IDeviceIdleController.aidl b/core/java/android/os/IDeviceIdleController.aidl index 3cb29ff..602bfea 100644 --- a/core/java/android/os/IDeviceIdleController.aidl +++ b/core/java/android/os/IDeviceIdleController.aidl @@ -23,4 +23,5 @@ interface IDeviceIdleController { String[] getSystemPowerWhitelist(); String[] getFullPowerWhitelist(); int[] getAppIdWhitelist(); + boolean isPowerSaveWhitelistApp(String name); } diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl index 811418b..f212daf 100644 --- a/core/java/android/os/IUserManager.aidl +++ b/core/java/android/os/IUserManager.aidl @@ -45,6 +45,8 @@ interface IUserManager { Bundle getUserRestrictions(int userHandle); boolean hasUserRestriction(in String restrictionKey, int userHandle); void setUserRestrictions(in Bundle restrictions, int userHandle); + void setUserRestriction(String key, boolean value, int userId); + void setSystemControlledUserRestriction(String key, boolean value, int userId); void setApplicationRestrictions(in String packageName, in Bundle restrictions, int userHandle); Bundle getApplicationRestrictions(in String packageName); diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java index 00ab262..9a0d0d0 100644 --- a/core/java/android/os/PowerManagerInternal.java +++ b/core/java/android/os/PowerManagerInternal.java @@ -134,4 +134,6 @@ public abstract class PowerManagerInternal { } public abstract void setDeviceIdleMode(boolean enabled); + + public abstract void setDeviceIdleWhitelist(int[] appids); } diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index c7ac7ce..cc37d5e 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -412,6 +412,16 @@ public class UserManager { public static final String DISALLOW_SAFE_BOOT = "no_safe_boot"; /** + * Specifies if a user is not allowed to record audio. This restriction is always enabled for + * background users. The default value is <code>false</code>. + * + * @see #setUserRestrictions(Bundle) + * @see #getUserRestrictions() + * @hide + */ + public static final String DISALLOW_RECORD_AUDIO = "no_record_audio"; + + /** * Application restriction key that is used to indicate the pending arrival * of real restrictions for the app. * @@ -688,9 +698,11 @@ public class UserManager { */ @Deprecated public void setUserRestriction(String key, boolean value, UserHandle userHandle) { - Bundle bundle = getUserRestrictions(userHandle); - bundle.putBoolean(key, value); - setUserRestrictions(bundle, userHandle); + try { + mService.setUserRestriction(key, value, userHandle.getIdentifier()); + } catch (RemoteException re) { + Log.w(TAG, "Could not set user restriction", re); + } } /** diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index dc70d7b..d3a5561 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -5517,6 +5517,12 @@ public final class Settings { public static final String APP_IDLE_DURATION = "app_idle_duration"; /** + * Controls whether double tap to wake is enabled. + * @hide + */ + public static final String DOUBLE_TAP_TO_WAKE = "double_tap_to_wake"; + + /** * This are the settings to be backed up. * * NOTE: Settings are backed up and restored in the order they appear @@ -5571,7 +5577,8 @@ public final class Settings { MOUNT_UMS_PROMPT, MOUNT_UMS_NOTIFY_ENABLED, UI_NIGHT_MODE, - SLEEP_TIMEOUT + SLEEP_TIMEOUT, + DOUBLE_TAP_TO_WAKE, }; /** diff --git a/core/java/android/service/chooser/ChooserTarget.java b/core/java/android/service/chooser/ChooserTarget.java index f0ca276..4c94ee7 100644 --- a/core/java/android/service/chooser/ChooserTarget.java +++ b/core/java/android/service/chooser/ChooserTarget.java @@ -58,12 +58,6 @@ public final class ChooserTarget implements Parcelable { private IntentSender mIntentSender; /** - * A raw intent provided in lieu of an IntentSender. Will be filled in and sent - * by {@link #sendIntent(Context, Intent)}. - */ - private Intent mIntent; - - /** * The score given to this item. It can be normalized. */ private float mScore; @@ -146,43 +140,6 @@ public final class ChooserTarget implements Parcelable { mIntentSender = intentSender; } - /** - * 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 Intent supplied will be - * {@link Intent#fillIn(Intent, int) filled in} by the Intent originally supplied - * to the chooser.</p> - * - * <p>Take care not to place custom {@link android.os.Parcelable} types into - * the Intent 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 intent Intent to fill in and send if the user chooses this target - */ - public ChooserTarget(CharSequence title, Bitmap icon, float score, Intent intent) { - mTitle = title; - mIcon = icon; - if (score > 1.f || score < 0.f) { - throw new IllegalArgumentException("Score " + score + " out of range; " - + "must be between 0.0f and 1.0f"); - } - mScore = score; - mIntent = intent; - } - ChooserTarget(Parcel in) { mTitle = in.readCharSequence(); if (in.readInt() != 0) { @@ -192,9 +149,6 @@ public final class ChooserTarget implements Parcelable { } mScore = in.readFloat(); mIntentSender = IntentSender.readIntentSenderOrNullFromParcel(in); - if (in.readInt() != 0) { - mIntent = Intent.CREATOR.createFromParcel(in); - } } /** @@ -241,18 +195,6 @@ public final class ChooserTarget implements Parcelable { } /** - * Returns the Intent supplied by the ChooserTarget's creator. - * This may be null if the creator specified an IntentSender or PendingIntent instead. - * - * <p>To fill in and send the intent, see {@link #sendIntent(Context, Intent)}.</p> - * - * @return the Intent supplied by the ChooserTarget's creator - */ - public Intent getIntent() { - return mIntent; - } - - /** * Fill in the IntentSender supplied by the ChooserTarget's creator and send it. * * @param context the sending Context; generally the Activity presenting the chooser UI @@ -272,91 +214,8 @@ public final class ChooserTarget implements Parcelable { Log.e(TAG, "sendIntent " + this + " failed", e); return false; } - } else if (mIntent != null) { - try { - final Intent toSend = new Intent(mIntent); - toSend.fillIn(fillInIntent, 0); - context.startActivity(toSend); - return true; - } catch (Exception e) { - Log.e(TAG, "sendIntent " + this + " failed", e); - return false; - } } else { - Log.e(TAG, "sendIntent " + this + " failed - no IntentSender or Intent to send"); - return false; - } - } - - /** - * Same as {@link #sendIntent(Context, Intent)}, but offers a userId field to use - * for launching the {@link #getIntent() intent} using - * {@link Activity#startActivityAsCaller(Intent, Bundle, int)} if the - * {@link #getIntentSender() IntentSender} is not present. If the IntentSender is present, - * it will be invoked as usual with its own calling identity. - * - * @hide internal use only. - */ - public boolean sendIntentAsCaller(Activity context, Intent fillInIntent, int userId) { - 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 if (mIntent != null) { - try { - final Intent toSend = new Intent(mIntent); - toSend.fillIn(fillInIntent, 0); - context.startActivityAsCaller(toSend, null, userId); - return true; - } catch (Exception e) { - Log.e(TAG, "sendIntent " + this + " failed", e); - return false; - } - } else { - Log.e(TAG, "sendIntent " + this + " failed - no IntentSender or Intent to send"); - return false; - } - } - - /** - * The UserHandle is only used if we're launching a raw intent. The IntentSender will be - * launched with its associated identity. - * - * @hide Internal use only - */ - public boolean sendIntentAsUser(Activity context, Intent fillInIntent, UserHandle user) { - 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 if (mIntent != null) { - try { - final Intent toSend = new Intent(mIntent); - toSend.fillIn(fillInIntent, 0); - context.startActivityAsUser(toSend, user); - return true; - } catch (Exception e) { - Log.e(TAG, "sendIntent " + this + " failed", e); - return false; - } - } else { - Log.e(TAG, "sendIntent " + this + " failed - no IntentSender or Intent to send"); + Log.e(TAG, "sendIntent " + this + " failed - no IntentSender to send"); return false; } } @@ -364,7 +223,7 @@ public final class ChooserTarget implements Parcelable { @Override public String toString() { return "ChooserTarget{" - + (mIntentSender != null ? mIntentSender.getCreatorPackage() : mIntent) + + (mIntentSender != null ? mIntentSender.getCreatorPackage() : null) + ", " + "'" + mTitle + "', " + mScore + "}"; @@ -386,10 +245,6 @@ public final class ChooserTarget implements Parcelable { } dest.writeFloat(mScore); IntentSender.writeIntentSenderOrNullToParcel(mIntentSender, dest); - dest.writeInt(mIntent != null ? 1 : 0); - if (mIntent != null) { - mIntent.writeToParcel(dest, 0); - } } public static final Creator<ChooserTarget> CREATOR diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java index 68ad782..3781d40 100644 --- a/core/java/android/view/AccessibilityInteractionController.java +++ b/core/java/android/view/AccessibilityInteractionController.java @@ -586,7 +586,7 @@ final class AccessibilityInteractionController { } } - private void perfromAccessibilityActionUiThread(Message message) { + private void performAccessibilityActionUiThread(Message message) { final int flags = message.arg1; final int accessibilityViewId = message.arg2; @@ -602,7 +602,8 @@ final class AccessibilityInteractionController { boolean succeeded = false; try { - if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) { + if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null || + mViewRootImpl.mStopped || mViewRootImpl.mPausedForTransition) { return; } mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags; @@ -1146,7 +1147,7 @@ final class AccessibilityInteractionController { findAccessibilityNodeInfoByAccessibilityIdUiThread(message); } break; case MSG_PERFORM_ACCESSIBILITY_ACTION: { - perfromAccessibilityActionUiThread(message); + performAccessibilityActionUiThread(message); } break; case MSG_FIND_ACCESSIBILITY_NODE_INFOS_BY_VIEW_ID: { findAccessibilityNodeInfosByViewIdUiThread(message); diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java index 1ac3f45..f6ce353 100644 --- a/core/java/android/view/KeyEvent.java +++ b/core/java/android/view/KeyEvent.java @@ -1817,9 +1817,7 @@ public class KeyEvent extends InputEvent implements Parcelable { public static final boolean isWakeKey(int keyCode) { switch (keyCode) { case KeyEvent.KEYCODE_BACK: - case KeyEvent.KEYCODE_POWER: case KeyEvent.KEYCODE_MENU: - case KeyEvent.KEYCODE_SLEEP: case KeyEvent.KEYCODE_WAKEUP: case KeyEvent.KEYCODE_PAIRING: return true; diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 51c4760..b476e9b 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -586,6 +586,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager mGroupFlags |= FLAG_CLIP_CHILDREN; mGroupFlags |= FLAG_CLIP_TO_PADDING; mGroupFlags |= FLAG_ANIMATION_DONE; + mGroupFlags |= FLAG_ANIMATION_CACHE; + mGroupFlags |= FLAG_ALWAYS_DRAWN_WITH_CACHE; if (mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB) { mGroupFlags |= FLAG_SPLIT_MOTION_EVENTS; diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index ea1dadb..57c6cbf 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -174,6 +174,9 @@ public final class ViewRootImpl implements ViewParent, // so the window should no longer be active. boolean mStopped = false; + // Set to true to stop input during an Activity Transition. + boolean mPausedForTransition = false; + boolean mLastInCompatMode = false; SurfaceHolder.Callback2 mSurfaceHolderCallback; @@ -982,15 +985,25 @@ public final class ViewRootImpl implements ViewParent, return null; } - void setStopped(boolean stopped) { + void setWindowStopped(boolean stopped) { if (mStopped != stopped) { mStopped = stopped; - if (!stopped) { + if (!mStopped) { scheduleTraversals(); } } } + /** + * Block the input events during an Activity Transition. The KEYCODE_BACK event is allowed + * through to allow quick reversal of the Activity Transition. + * + * @param paused true to pause, false to resume. + */ + public void setPausedForTransition(boolean paused) { + mPausedForTransition = paused; + } + @Override public ViewParent getParent() { return null; @@ -3637,8 +3650,9 @@ public final class ViewRootImpl implements ViewParent, if (mView == null || !mAdded) { Slog.w(TAG, "Dropping event due to root view being removed: " + q.mEvent); return true; - } else if ((!mAttachInfo.mHasWindowFocus || mStopped) - && !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) { + } else if ((!mAttachInfo.mHasWindowFocus + && !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) || mStopped + || (mPausedForTransition && !isBack(q.mEvent))) { // This is a focus event and the window doesn't currently have input focus or // has stopped. This could be an event that came back from the previous stage // but the window has lost focus or stopped in the meantime. @@ -3661,6 +3675,14 @@ public final class ViewRootImpl implements ViewParent, mNext.dump(prefix, writer); } } + + private boolean isBack(InputEvent event) { + if (event instanceof KeyEvent) { + return ((KeyEvent) event).getKeyCode() == KeyEvent.KEYCODE_BACK; + } else { + return false; + } + } } /** @@ -6228,7 +6250,7 @@ public final class ViewRootImpl implements ViewParent, @Override public boolean requestSendAccessibilityEvent(View child, AccessibilityEvent event) { - if (mView == null) { + if (mView == null || mStopped || mPausedForTransition) { return false; } // Intercept accessibility focus events fired by virtual nodes to keep diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java index 57558ff..e7a7ba8 100644 --- a/core/java/android/view/WindowManagerGlobal.java +++ b/core/java/android/view/WindowManagerGlobal.java @@ -21,7 +21,6 @@ import android.app.ActivityManager; import android.content.ComponentCallbacks2; import android.content.Context; import android.content.res.Configuration; -import android.os.Build; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; @@ -552,7 +551,7 @@ public final class WindowManagerGlobal { for (int i = 0; i < count; i++) { if (token == null || mParams.get(i).token == token) { ViewRootImpl root = mRoots.get(i); - root.setStopped(stopped); + root.setWindowStopped(stopped); } } } diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java index 6feb94b..bb4a948 100644 --- a/core/java/android/widget/AppSecurityPermissions.java +++ b/core/java/android/widget/AppSecurityPermissions.java @@ -244,7 +244,7 @@ public class AppSecurityPermissions { @Override public void onClick(DialogInterface dialog, int which) { PackageManager pm = getContext().getPackageManager(); - pm.revokePermission(mPackageName, mPerm.name, + pm.revokeRuntimePermission(mPackageName, mPerm.name, new UserHandle(mContext.getUserId())); PermissionItemView.this.setVisibility(View.GONE); } diff --git a/core/java/android/widget/CalendarViewLegacyDelegate.java b/core/java/android/widget/CalendarViewLegacyDelegate.java index 6ab3828..442fb33 100644 --- a/core/java/android/widget/CalendarViewLegacyDelegate.java +++ b/core/java/android/widget/CalendarViewLegacyDelegate.java @@ -713,7 +713,7 @@ class CalendarViewLegacyDelegate extends CalendarView.AbstractCalendarViewDelega for (int i = 1, count = mDayNamesHeader.getChildCount(); i < count; i++) { label = (TextView) mDayNamesHeader.getChildAt(i); if (mWeekDayTextAppearanceResId > -1) { - label.setTextAppearance(mContext, mWeekDayTextAppearanceResId); + label.setTextAppearance(mWeekDayTextAppearanceResId); } if (i < mDaysPerWeek + 1) { label.setText(mDayNamesShort[i - 1]); diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 78c418b..2e36cee 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -2055,7 +2055,7 @@ public class Editor { shadowView.setText(text); shadowView.setTextColor(mTextView.getTextColors()); - shadowView.setTextAppearance(mTextView.getContext(), R.styleable.Theme_textAppearanceLarge); + shadowView.setTextAppearance(R.styleable.Theme_textAppearanceLarge); shadowView.setGravity(Gravity.CENTER); shadowView.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, @@ -3902,6 +3902,9 @@ public class Editor { @Override public void updatePosition(float x, float y) { positionAtCursorOffset(mTextView.getOffsetForPosition(x, y), false); + if (mSelectionActionMode != null) { + mSelectionActionMode.invalidate(); + } } @Override diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java index 087406a..62d948d 100644 --- a/core/java/android/widget/Toolbar.java +++ b/core/java/android/widget/Toolbar.java @@ -590,7 +590,7 @@ public class Toolbar extends ViewGroup { mTitleTextView.setSingleLine(); mTitleTextView.setEllipsize(TextUtils.TruncateAt.END); if (mTitleTextAppearance != 0) { - mTitleTextView.setTextAppearance(context, mTitleTextAppearance); + mTitleTextView.setTextAppearance(mTitleTextAppearance); } if (mTitleTextColor != 0) { mTitleTextView.setTextColor(mTitleTextColor); @@ -644,7 +644,7 @@ public class Toolbar extends ViewGroup { mSubtitleTextView.setSingleLine(); mSubtitleTextView.setEllipsize(TextUtils.TruncateAt.END); if (mSubtitleTextAppearance != 0) { - mSubtitleTextView.setTextAppearance(context, mSubtitleTextAppearance); + mSubtitleTextView.setTextAppearance(mSubtitleTextAppearance); } if (mSubtitleTextColor != 0) { mSubtitleTextView.setTextColor(mSubtitleTextColor); @@ -670,7 +670,7 @@ public class Toolbar extends ViewGroup { public void setTitleTextAppearance(Context context, @StyleRes int resId) { mTitleTextAppearance = resId; if (mTitleTextView != null) { - mTitleTextView.setTextAppearance(context, resId); + mTitleTextView.setTextAppearance(resId); } } @@ -681,7 +681,7 @@ public class Toolbar extends ViewGroup { public void setSubtitleTextAppearance(Context context, @StyleRes int resId) { mSubtitleTextAppearance = resId; if (mSubtitleTextView != null) { - mSubtitleTextView.setTextAppearance(context, resId); + mSubtitleTextView.setTextAppearance(resId); } } diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index 62ca1f0..83fa967 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -24,9 +24,11 @@ import android.content.IntentSender; import android.content.IntentSender.SendIntentException; import android.content.ServiceConnection; import android.content.pm.ActivityInfo; +import android.content.pm.LabeledIntent; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; +import android.database.DataSetObserver; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Bundle; @@ -37,6 +39,7 @@ import android.os.Parcelable; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.UserHandle; +import android.os.UserManager; import android.service.chooser.ChooserTarget; import android.service.chooser.ChooserTargetService; import android.service.chooser.IChooserTargetResult; @@ -44,8 +47,16 @@ import android.service.chooser.IChooserTargetService; import android.text.TextUtils; import android.util.Log; import android.util.Slog; +import android.view.LayoutInflater; import android.view.View; +import android.view.View.OnClickListener; import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; +import android.widget.AbsListView; +import android.widget.BaseAdapter; +import android.widget.LinearLayout; +import android.widget.ListView; +import com.android.internal.R; import java.util.ArrayList; import java.util.List; @@ -63,7 +74,7 @@ public class ChooserActivity extends ResolverActivity { private IntentSender mRefinementIntentSender; private RefinementResultReceiver mRefinementResultReceiver; - private ChooserTarget[] mCallerChooserTargets; + private ChooserListAdapter mChooserListAdapter; private final List<ChooserTargetServiceConnection> mServiceConnections = new ArrayList<>(); @@ -84,8 +95,7 @@ public class ChooserActivity extends ResolverActivity { + " Have you considered returning results faster?"); break; } - final ChooserListAdapter cla = (ChooserListAdapter) getAdapter(); - cla.addServiceResults(sri.originalTarget, sri.resultTargets); + mChooserListAdapter.addServiceResults(sri.originalTarget, sri.resultTargets); unbindService(sri.connection); mServiceConnections.remove(sri.connection); break; @@ -166,20 +176,6 @@ public class ChooserActivity extends ResolverActivity { } } - pa = intent.getParcelableArrayExtra(Intent.EXTRA_CHOOSER_TARGETS); - if (pa != null) { - final ChooserTarget[] targets = new ChooserTarget[pa.length]; - for (int i = 0; i < pa.length; i++) { - if (!(pa[i] instanceof ChooserTarget)) { - Log.w(TAG, "Chooser target #" + i + " is not a ChooserTarget: " + pa[i]); - finish(); - super.onCreate(null); - return; - } - targets[i] = (ChooserTarget) pa[i]; - } - mCallerChooserTargets = targets; - } mChosenComponentSender = intent.getParcelableExtra( Intent.EXTRA_CHOSEN_COMPONENT_INTENT_SENDER); mRefinementIntentSender = intent.getParcelableExtra( @@ -233,8 +229,19 @@ public class ChooserActivity extends ResolverActivity { } @Override + void onPrepareAdapterView(AbsListView adapterView, ResolveListAdapter adapter, + boolean alwaysUseOption) { + final ListView listView = adapterView instanceof ListView ? (ListView) adapterView : null; + mChooserListAdapter = (ChooserListAdapter) adapter; + adapterView.setAdapter(new ChooserRowAdapter(mChooserListAdapter)); + if (listView != null) { + listView.setItemsCanFocus(true); + } + } + + @Override int getLayoutResource() { - return com.android.internal.R.layout.chooser_grid; + return R.layout.chooser_grid; } @Override @@ -413,10 +420,11 @@ public class ChooserActivity extends ResolverActivity { } @Override - ResolveListAdapter createAdapter(Context context, Intent[] initialIntents, - List<ResolveInfo> rList, int launchedFromUid, boolean filterLastUsed) { - final ChooserListAdapter adapter = new ChooserListAdapter(context, initialIntents, rList, - launchedFromUid, filterLastUsed, mCallerChooserTargets); + ResolveListAdapter createAdapter(Context context, List<Intent> payloadIntents, + Intent[] initialIntents, List<ResolveInfo> rList, int launchedFromUid, + boolean filterLastUsed) { + final ChooserListAdapter adapter = new ChooserListAdapter(context, payloadIntents, + initialIntents, rList, launchedFromUid, filterLastUsed); if (DEBUG) Log.d(TAG, "Adapter created; querying services"); queryTargetServices(adapter); return adapter; @@ -426,17 +434,23 @@ public class ChooserActivity extends ResolverActivity { private final DisplayResolveInfo mSourceInfo; private final ResolveInfo mBackupResolveInfo; private final ChooserTarget mChooserTarget; + private Drawable mBadgeIcon = null; private final Drawable mDisplayIcon; private final Intent mFillInIntent; private final int mFillInFlags; - public ChooserTargetInfo(ChooserTarget target) { - this(null, target); - } - public ChooserTargetInfo(DisplayResolveInfo sourceInfo, ChooserTarget chooserTarget) { mSourceInfo = sourceInfo; mChooserTarget = chooserTarget; + if (sourceInfo != null) { + final ResolveInfo ri = sourceInfo.getResolveInfo(); + if (ri != null) { + final ActivityInfo ai = ri.activityInfo; + if (ai != null && ai.applicationInfo != null) { + mBadgeIcon = getPackageManager().getApplicationIcon(ai.applicationInfo); + } + } + } mDisplayIcon = new BitmapDrawable(getResources(), chooserTarget.getIcon()); if (sourceInfo != null) { @@ -453,6 +467,7 @@ public class ChooserActivity extends ResolverActivity { mSourceInfo = other.mSourceInfo; mBackupResolveInfo = other.mBackupResolveInfo; mChooserTarget = other.mChooserTarget; + mBadgeIcon = other.mBadgeIcon; mDisplayIcon = other.mDisplayIcon; mFillInIntent = fillInIntent; mFillInFlags = flags; @@ -460,10 +475,7 @@ public class ChooserActivity extends ResolverActivity { @Override public Intent getResolvedIntent() { - final Intent targetIntent = mChooserTarget.getIntent(); - if (targetIntent != null) { - return targetIntent; - } else if (mSourceInfo != null) { + if (mSourceInfo != null) { return mSourceInfo.getResolvedIntent(); } return getTargetIntent(); @@ -507,7 +519,8 @@ public class ChooserActivity extends ResolverActivity { if (intent == null) { return false; } - return mChooserTarget.sendIntentAsCaller(activity, intent, userId); + // ChooserTargets will launch with their IntentSender's identity + return mChooserTarget.sendIntent(activity, intent); } @Override @@ -516,7 +529,8 @@ public class ChooserActivity extends ResolverActivity { if (intent == null) { return false; } - return mChooserTarget.sendIntentAsUser(activity, intent, user); + // ChooserTargets will launch with their IntentSender's identity + return mChooserTarget.sendIntent(activity, intent); } @Override @@ -540,6 +554,11 @@ public class ChooserActivity extends ResolverActivity { } @Override + public Drawable getBadgeIcon() { + return mBadgeIcon; + } + + @Override public TargetInfo cloneFilledIn(Intent fillInIntent, int flags) { return new ChooserTargetInfo(this, fillInIntent, flags); } @@ -556,16 +575,49 @@ public class ChooserActivity extends ResolverActivity { } public class ChooserListAdapter extends ResolveListAdapter { - private final List<ChooserTargetInfo> mServiceTargets = new ArrayList<>(); - private final List<ChooserTargetInfo> mCallerTargets = new ArrayList<>(); - - public ChooserListAdapter(Context context, Intent[] initialIntents, List<ResolveInfo> rList, - int launchedFromUid, boolean filterLastUsed, ChooserTarget[] callerChooserTargets) { - super(context, initialIntents, rList, launchedFromUid, filterLastUsed); + public static final int TARGET_BAD = -1; + public static final int TARGET_CALLER = 0; + public static final int TARGET_SERVICE = 1; + public static final int TARGET_STANDARD = 2; - if (callerChooserTargets != null) { - for (ChooserTarget target : callerChooserTargets) { - mCallerTargets.add(new ChooserTargetInfo(target)); + private final List<ChooserTargetInfo> mServiceTargets = new ArrayList<>(); + private final List<TargetInfo> mCallerTargets = new ArrayList<>(); + + public ChooserListAdapter(Context context, List<Intent> payloadIntents, + Intent[] initialIntents, List<ResolveInfo> rList, int launchedFromUid, + boolean filterLastUsed) { + // Don't send the initial intents through the shared ResolverActivity path, + // we want to separate them into a different section. + super(context, payloadIntents, null, rList, launchedFromUid, filterLastUsed); + + if (initialIntents != null) { + final PackageManager pm = getPackageManager(); + for (int i = 0; i < initialIntents.length; i++) { + final Intent ii = initialIntents[i]; + if (ii == null) { + continue; + } + final ActivityInfo ai = ii.resolveActivityInfo(pm, 0); + if (ai == null) { + Log.w(TAG, "No activity found for " + ii); + continue; + } + ResolveInfo ri = new ResolveInfo(); + ri.activityInfo = ai; + UserManager userManager = + (UserManager) getSystemService(Context.USER_SERVICE); + if (userManager.isManagedProfile()) { + ri.noResourceId = true; + } + if (ii instanceof LabeledIntent) { + LabeledIntent li = (LabeledIntent)ii; + ri.resolvePackageName = li.getSourcePackage(); + ri.labelRes = li.getLabelResource(); + ri.nonLocalizedLabel = li.getNonLocalizedLabel(); + ri.icon = li.getIconResource(); + } + mCallerTargets.add(new DisplayResolveInfo(ii, ri, + ri.loadLabel(pm), null, ii)); } } } @@ -578,7 +630,7 @@ public class ChooserActivity extends ResolverActivity { } @Override - public View createView(ViewGroup parent) { + public View onCreateView(ViewGroup parent) { return mInflater.inflate( com.android.internal.R.layout.resolve_grid_item, parent, false); } @@ -600,6 +652,41 @@ public class ChooserActivity extends ResolverActivity { return super.getCount() + mServiceTargets.size() + mCallerTargets.size(); } + public int getCallerTargetsCount() { + return mCallerTargets.size(); + } + + public int getServiceTargetsCount() { + return mServiceTargets.size(); + } + + public int getStandardTargetCount() { + return super.getCount(); + } + + public int getPositionTargetType(int position) { + int offset = 0; + + final int callerTargetCount = mCallerTargets.size(); + if (position < callerTargetCount) { + return TARGET_CALLER; + } + offset += callerTargetCount; + + final int serviceTargetCount = mServiceTargets.size(); + if (position - offset < serviceTargetCount) { + return TARGET_SERVICE; + } + offset += serviceTargetCount; + + final int standardTargetCount = super.getCount(); + if (position - offset < standardTargetCount) { + return TARGET_STANDARD; + } + + return TARGET_BAD; + } + @Override public TargetInfo getItem(int position) { int offset = 0; @@ -643,6 +730,133 @@ public class ChooserActivity extends ResolverActivity { } } + class ChooserRowAdapter extends BaseAdapter { + private ChooserListAdapter mChooserListAdapter; + private final LayoutInflater mLayoutInflater; + private final int mColumnCount = 4; + + public ChooserRowAdapter(ChooserListAdapter wrappedAdapter) { + mChooserListAdapter = wrappedAdapter; + mLayoutInflater = LayoutInflater.from(ChooserActivity.this); + + wrappedAdapter.registerDataSetObserver(new DataSetObserver() { + @Override + public void onChanged() { + super.onChanged(); + notifyDataSetChanged(); + } + + @Override + public void onInvalidated() { + super.onInvalidated(); + notifyDataSetInvalidated(); + } + }); + } + + @Override + public int getCount() { + return (int) ( + Math.ceil((float) mChooserListAdapter.getCallerTargetsCount() / mColumnCount) + + Math.ceil((float) mChooserListAdapter.getServiceTargetsCount() / mColumnCount) + + Math.ceil((float) mChooserListAdapter.getStandardTargetCount() / mColumnCount) + ); + } + + @Override + public Object getItem(int position) { + // We have nothing useful to return here. + return position; + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + final View[] holder; + if (convertView == null) { + holder = createViewHolder(parent); + } else { + holder = (View[]) convertView.getTag(); + } + bindViewHolder(position, holder); + + // We keep the actual list item view as the last item in the holder array + return holder[mColumnCount]; + } + + View[] createViewHolder(ViewGroup parent) { + final View[] holder = new View[mColumnCount + 1]; + + final ViewGroup row = (ViewGroup) mLayoutInflater.inflate(R.layout.chooser_row, + parent, false); + for (int i = 0; i < mColumnCount; i++) { + holder[i] = mChooserListAdapter.createView(row); + row.addView(holder[i]); + } + row.setTag(holder); + holder[mColumnCount] = row; + return holder; + } + + void bindViewHolder(int rowPosition, View[] holder) { + final int start = getFirstRowPosition(rowPosition); + final int startType = mChooserListAdapter.getPositionTargetType(start); + + int end = start + mColumnCount - 1; + while (mChooserListAdapter.getPositionTargetType(end) != startType && end >= start) { + end--; + } + + final ViewGroup row = (ViewGroup) holder[mColumnCount]; + + if (startType == ChooserListAdapter.TARGET_SERVICE) { + row.setBackgroundColor(getColor(R.color.chooser_service_row_background_color)); + } else { + row.setBackground(null); + } + + for (int i = 0; i < mColumnCount; i++) { + final View v = holder[i]; + if (start + i <= end) { + v.setVisibility(View.VISIBLE); + final int itemIndex = start + i; + mChooserListAdapter.bindView(itemIndex, v); + v.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + startSelected(itemIndex, false, true); + } + }); + } else { + v.setVisibility(View.GONE); + } + } + } + + int getFirstRowPosition(int row) { + final int callerCount = mChooserListAdapter.getCallerTargetsCount(); + final int callerRows = (int) Math.ceil((float) callerCount / mColumnCount); + + if (row < callerRows) { + return row * mColumnCount; + } + + final int serviceCount = mChooserListAdapter.getServiceTargetsCount(); + final int serviceRows = (int) Math.ceil((float) serviceCount / mColumnCount); + + if (row < callerRows + serviceRows) { + return callerCount + (row - callerRows) * mColumnCount; + } + + return callerCount + serviceCount + + (row - callerRows - serviceRows) * mColumnCount; + } + } + class ChooserTargetServiceConnection implements ServiceConnection { private final DisplayResolveInfo mOriginalTarget; diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index 2048664..4696757 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -25,7 +25,6 @@ import android.provider.Settings; import android.text.TextUtils; import android.util.Slog; import android.widget.AbsListView; -import android.widget.GridView; import com.android.internal.R; import com.android.internal.content.PackageMonitor; @@ -83,7 +82,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; * which there is more than one matching activity, allowing the user to decide * which to go to. It is not normally used directly by application developers. */ -public class ResolverActivity extends Activity implements AdapterView.OnItemClickListener { +public class ResolverActivity extends Activity { private static final String TAG = "ResolverActivity"; private static final boolean DEBUG = false; @@ -93,8 +92,6 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic private boolean mSafeForwardingMode; private boolean mAlwaysUseOption; private AbsListView mAdapterView; - private ListView mListView; - private GridView mGridView; private Button mAlwaysButton; private Button mOnceButton; private View mProfileView; @@ -217,6 +214,13 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic } catch (RemoteException e) { mLaunchedFromUid = -1; } + + if (mLaunchedFromUid < 0 || UserHandle.isIsolated(mLaunchedFromUid)) { + // Gulp! + finish(); + return; + } + mPm = getPackageManager(); mUsm = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE); @@ -229,67 +233,11 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic final ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE); mIconDpi = am.getLauncherLargeIconDensity(); + // Add our initial intent as the first item, regardless of what else has already been added. mIntents.add(0, new Intent(intent)); - mAdapter = createAdapter(this, initialIntents, rList, mLaunchedFromUid, alwaysUseOption); - final int layoutId; - final boolean useHeader; - if (mAdapter.hasFilteredItem()) { - layoutId = R.layout.resolver_list_with_default; - alwaysUseOption = false; - useHeader = true; - } else { - useHeader = false; - layoutId = getLayoutResource(); - } - mAlwaysUseOption = alwaysUseOption; + configureContentView(mIntents, initialIntents, rList, alwaysUseOption); - if (mLaunchedFromUid < 0 || UserHandle.isIsolated(mLaunchedFromUid)) { - // Gulp! - finish(); - return; - } - - int count = mAdapter.mDisplayList.size(); - if (count > 1 || (count == 1 && mAdapter.getOtherProfile() != null)) { - setContentView(layoutId); - mAdapterView = (AbsListView) findViewById(R.id.resolver_list); - mAdapterView.setAdapter(mAdapter); - mAdapterView.setOnItemClickListener(this); - mAdapterView.setOnItemLongClickListener(new ItemLongClickListener()); - - // Initialize the different types of collection views we may have. Depending - // on which ones are initialized later we'll configure different properties. - if (mAdapterView instanceof ListView) { - mListView = (ListView) mAdapterView; - } - if (mAdapterView instanceof GridView) { - mGridView = (GridView) mAdapterView; - } - - if (alwaysUseOption) { - mAdapterView.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE); - } - - if (useHeader && mListView != null) { - mListView.addHeaderView(LayoutInflater.from(this).inflate( - R.layout.resolver_different_item_header, mListView, false)); - } - } else if (count == 1) { - safelyStartActivity(mAdapter.targetInfoForPosition(0, false)); - mPackageMonitor.unregister(); - mRegistered = false; - finish(); - return; - } else { - setContentView(R.layout.resolver_list); - - final TextView empty = (TextView) findViewById(R.id.empty); - empty.setVisibility(View.VISIBLE); - - mAdapterView = (AbsListView) findViewById(R.id.resolver_list); - mAdapterView.setVisibility(View.GONE); - } // Prevent the Resolver window from becoming the top fullscreen window and thus from taking // control of the system bars. getWindow().clearFlags(FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR); @@ -548,29 +496,6 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic } } - @Override - public void onItemClick(AdapterView<?> parent, View view, int position, long id) { - if (mListView != null) { - position -= mListView.getHeaderViewsCount(); - } - if (position < 0) { - // Header views don't count. - return; - } - final int checkedPos = mAdapterView.getCheckedItemPosition(); - final boolean hasValidSelection = checkedPos != ListView.INVALID_POSITION; - if (mAlwaysUseOption && (!hasValidSelection || mLastSelected != checkedPos)) { - setAlwaysButtonEnabled(hasValidSelection, checkedPos, true); - mOnceButton.setEnabled(hasValidSelection); - if (hasValidSelection) { - mAdapterView.smoothScrollToPosition(checkedPos); - } - mLastSelected = checkedPos; - } else { - startSelected(position, false, true); - } - } - private boolean hasManagedProfile() { UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE); if (userManager == null) { @@ -743,29 +668,37 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic if (r.match > bestMatch) bestMatch = r.match; } if (alwaysCheck) { - PackageManager pm = getPackageManager(); + final int userId = getUserId(); + final PackageManager pm = getPackageManager(); // Set the preferred Activity pm.addPreferredActivity(filter, bestMatch, set, intent.getComponent()); - // Update Domain Verification status - int userId = getUserId(); - ComponentName cn = intent.getComponent(); - String packageName = cn.getPackageName(); - String dataScheme = (data != null) ? data.getScheme() : null; - - boolean isHttpOrHttps = (dataScheme != null) && - (dataScheme.equals(IntentFilter.SCHEME_HTTP) || - dataScheme.equals(IntentFilter.SCHEME_HTTPS)); - - boolean isViewAction = (action != null) && action.equals(Intent.ACTION_VIEW); - boolean hasCategoryBrowsable = (categories != null) && - categories.contains(Intent.CATEGORY_BROWSABLE); - - if (isHttpOrHttps && isViewAction && hasCategoryBrowsable) { - pm.updateIntentVerificationStatus(packageName, - PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS, - userId); + if (ri.handleAllWebDataURI) { + // Set default Browser if needed + final String packageName = pm.getDefaultBrowserPackageName(userId); + if (TextUtils.isEmpty(packageName)) { + pm.setDefaultBrowserPackageName(ri.activityInfo.packageName, userId); + } + } else { + // Update Domain Verification status + ComponentName cn = intent.getComponent(); + String packageName = cn.getPackageName(); + String dataScheme = (data != null) ? data.getScheme() : null; + + boolean isHttpOrHttps = (dataScheme != null) && + (dataScheme.equals(IntentFilter.SCHEME_HTTP) || + dataScheme.equals(IntentFilter.SCHEME_HTTPS)); + + boolean isViewAction = (action != null) && action.equals(Intent.ACTION_VIEW); + boolean hasCategoryBrowsable = (categories != null) && + categories.contains(Intent.CATEGORY_BROWSABLE); + + if (isHttpOrHttps && isViewAction && hasCategoryBrowsable) { + pm.updateIntentVerificationStatus(packageName, + PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS, + userId); + } } } else { try { @@ -831,14 +764,68 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic startActivity(in); } - ResolveListAdapter createAdapter(Context context, Intent[] initialIntents, - List<ResolveInfo> rList, int launchedFromUid, boolean filterLastUsed) { - return new ResolveListAdapter(context, initialIntents, rList, launchedFromUid, - filterLastUsed); + ResolveListAdapter createAdapter(Context context, List<Intent> payloadIntents, + Intent[] initialIntents, List<ResolveInfo> rList, int launchedFromUid, + boolean filterLastUsed) { + return new ResolveListAdapter(context, payloadIntents, initialIntents, rList, + launchedFromUid, filterLastUsed); } - ResolveListAdapter getAdapter() { - return mAdapter; + void configureContentView(List<Intent> payloadIntents, Intent[] initialIntents, + List<ResolveInfo> rList, boolean alwaysUseOption) { + mAdapter = createAdapter(this, payloadIntents, initialIntents, rList, + mLaunchedFromUid, alwaysUseOption); + + final int layoutId; + if (mAdapter.hasFilteredItem()) { + layoutId = R.layout.resolver_list_with_default; + alwaysUseOption = false; + } else { + layoutId = getLayoutResource(); + } + mAlwaysUseOption = alwaysUseOption; + + int count = mAdapter.mDisplayList.size(); + if (count > 1 || (count == 1 && mAdapter.getOtherProfile() != null)) { + setContentView(layoutId); + mAdapterView = (AbsListView) findViewById(R.id.resolver_list); + onPrepareAdapterView(mAdapterView, mAdapter, alwaysUseOption); + } else if (count == 1) { + safelyStartActivity(mAdapter.targetInfoForPosition(0, false)); + mPackageMonitor.unregister(); + mRegistered = false; + finish(); + return; + } else { + setContentView(R.layout.resolver_list); + + final TextView empty = (TextView) findViewById(R.id.empty); + empty.setVisibility(View.VISIBLE); + + mAdapterView = (AbsListView) findViewById(R.id.resolver_list); + mAdapterView.setVisibility(View.GONE); + } + } + + void onPrepareAdapterView(AbsListView adapterView, ResolveListAdapter adapter, + boolean alwaysUseOption) { + final boolean useHeader = adapter.hasFilteredItem(); + final ListView listView = adapterView instanceof ListView ? (ListView) adapterView : null; + + adapterView.setAdapter(mAdapter); + + final ItemClickListener listener = new ItemClickListener(); + adapterView.setOnItemClickListener(listener); + adapterView.setOnItemLongClickListener(listener); + + if (alwaysUseOption) { + listView.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE); + } + + if (useHeader && listView != null) { + listView.addHeaderView(LayoutInflater.from(this).inflate( + R.layout.resolver_different_item_header, listView, false)); + } } final class DisplayResolveInfo implements TargetInfo { @@ -888,6 +875,10 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic return mDisplayIcon; } + public Drawable getBadgeIcon() { + return null; + } + @Override public TargetInfo cloneFilledIn(Intent fillInIntent, int flags) { return new DisplayResolveInfo(this, fillInIntent, flags); @@ -1024,6 +1015,11 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic public Drawable getDisplayIcon(); /** + * @return The (small) icon to badge the target with + */ + public Drawable getBadgeIcon(); + + /** * Clone this target with the given fill-in information. */ public TargetInfo cloneFilledIn(Intent fillInIntent, int flags); @@ -1035,6 +1031,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic } class ResolveListAdapter extends BaseAdapter { + private final List<Intent> mIntents; private final Intent[] mInitialIntents; private final List<ResolveInfo> mBaseResolveList; private ResolveInfo mLastChosen; @@ -1050,8 +1047,10 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic private int mLastChosenPosition = -1; private boolean mFilterLastUsed; - public ResolveListAdapter(Context context, Intent[] initialIntents, - List<ResolveInfo> rList, int launchedFromUid, boolean filterLastUsed) { + public ResolveListAdapter(Context context, List<Intent> payloadIntents, + Intent[] initialIntents, List<ResolveInfo> rList, int launchedFromUid, + boolean filterLastUsed) { + mIntents = payloadIntents; mInitialIntents = initialIntents; mBaseResolveList = rList; mLaunchedFromUid = launchedFromUid; @@ -1430,15 +1429,19 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic View view = convertView; if (view == null) { view = createView(parent); - - final ViewHolder holder = new ViewHolder(view); - view.setTag(holder); } - bindView(view, getItem(position)); + onBindView(view, getItem(position)); + return view; + } + + public final View createView(ViewGroup parent) { + final View view = onCreateView(parent); + final ViewHolder holder = new ViewHolder(view); + view.setTag(holder); return view; } - public View createView(ViewGroup parent) { + public View onCreateView(ViewGroup parent) { return mInflater.inflate( com.android.internal.R.layout.resolve_list_item, parent, false); } @@ -1447,7 +1450,11 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic return !TextUtils.isEmpty(info.getExtendedInfo()); } - private final void bindView(View view, TargetInfo info) { + public final void bindView(int position, View view) { + onBindView(view, getItem(position)); + } + + private void onBindView(View view, TargetInfo info) { final ViewHolder holder = (ViewHolder) view.getTag(); holder.text.setText(info.getDisplayLabel()); if (showsExtendedInfo(info)) { @@ -1461,6 +1468,15 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic new LoadAdapterIconTask((DisplayResolveInfo) info).execute(); } holder.icon.setImageDrawable(info.getDisplayIcon()); + if (holder.badge != null) { + final Drawable badge = info.getBadgeIcon(); + if (badge != null) { + holder.badge.setImageDrawable(badge); + holder.badge.setVisibility(View.VISIBLE); + } else { + holder.badge.setVisibility(View.GONE); + } + } } } @@ -1514,20 +1530,47 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic public TextView text; public TextView text2; public ImageView icon; + public ImageView badge; public ViewHolder(View view) { text = (TextView) view.findViewById(com.android.internal.R.id.text1); text2 = (TextView) view.findViewById(com.android.internal.R.id.text2); icon = (ImageView) view.findViewById(R.id.icon); + badge = (ImageView) view.findViewById(R.id.target_badge); } } - class ItemLongClickListener implements AdapterView.OnItemLongClickListener { + class ItemClickListener implements AdapterView.OnItemClickListener, + AdapterView.OnItemLongClickListener { + @Override + public void onItemClick(AdapterView<?> parent, View view, int position, long id) { + final ListView listView = parent instanceof ListView ? (ListView) parent : null; + if (listView != null) { + position -= listView.getHeaderViewsCount(); + } + if (position < 0) { + // Header views don't count. + return; + } + final int checkedPos = mAdapterView.getCheckedItemPosition(); + final boolean hasValidSelection = checkedPos != ListView.INVALID_POSITION; + if (mAlwaysUseOption && (!hasValidSelection || mLastSelected != checkedPos)) { + setAlwaysButtonEnabled(hasValidSelection, checkedPos, true); + mOnceButton.setEnabled(hasValidSelection); + if (hasValidSelection) { + mAdapterView.smoothScrollToPosition(checkedPos); + } + mLastSelected = checkedPos; + } else { + startSelected(position, false, true); + } + } @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { - if (mListView != null) { - position -= mListView.getHeaderViewsCount(); + final ListView listView = parent instanceof ListView ? (ListView) parent : null; + if (listView != null) { + position -= listView.getHeaderViewsCount(); } if (position < 0) { // Header views don't count. diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java index 9277f9b..cf25cef 100644 --- a/core/java/com/android/internal/logging/MetricsLogger.java +++ b/core/java/com/android/internal/logging/MetricsLogger.java @@ -27,7 +27,6 @@ import android.view.View; */ public class MetricsLogger implements MetricsConstants { // These constants are temporary, they should migrate to MetricsConstants. - // next value is 148; public static final int NOTIFICATION_ZEN_MODE_SCHEDULE_RULE = 144; public static final int NOTIFICATION_ZEN_MODE_EXTERNAL_RULE = 145; @@ -38,6 +37,34 @@ public class MetricsLogger implements MetricsConstants { public static final int QS_BLUETOOTH_DETAILS = 150; public static final int QS_CAST_DETAILS = 151; public static final int QS_WIFI_DETAILS = 152; + public static final int QS_WIFI_TOGGLE = 153; + public static final int QS_BLUETOOTH_TOGGLE = 154; + public static final int QS_CELLULAR_TOGGLE = 155; + public static final int QS_SWITCH_USER = 156; + public static final int QS_CAST_SELECT = 157; + public static final int QS_CAST_DISCONNECT = 158; + public static final int ACTION_BLUETOOTH_TOGGLE = 159; + public static final int ACTION_BLUETOOTH_SCAN = 160; + public static final int ACTION_BLUETOOTH_RENAME = 161; + public static final int ACTION_BLUETOOTH_FILES = 162; + public static final int QS_DND_TIME = 163; + public static final int QS_DND_CONDITION_SELECT = 164; + public static final int QS_DND_ZEN_SELECT = 165; + public static final int QS_DND_TOGGLE = 166; + public static final int ACTION_ZEN_ALLOW_REMINDERS = 167; + public static final int ACTION_ZEN_ALLOW_EVENTS = 168; + public static final int ACTION_ZEN_ALLOW_MESSAGES = 169; + public static final int ACTION_ZEN_ALLOW_CALLS = 170; + public static final int ACTION_ZEN_ALLOW_REPEAT_CALLS = 171; + public static final int ACTION_ZEN_ADD_RULE = 172; + public static final int ACTION_ZEN_ADD_RULE_OK = 173; + public static final int ACTION_ZEN_DELETE_RULE = 174; + public static final int ACTION_ZEN_DELETE_RULE_OK = 175; + public static final int ACTION_ZEN_ENABLE_RULE = 176; + public static final int ACTION_AIRPLANE_TOGGLE = 177; + public static final int ACTION_CELL_DATA_TOGGLE = 178; + public static final int NOTIFICATION_ACCESS = 179; + public static final int NOTIFICATION_ZEN_MODE_ACCESS = 180; public static void visible(Context context, int category) throws IllegalArgumentException { if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) { @@ -71,6 +98,14 @@ public class MetricsLogger implements MetricsConstants { action(context, category, ""); } + public static void action(Context context, int category, int value) { + action(context, category, Integer.toString(value)); + } + + public static void action(Context context, int category, boolean value) { + action(context, category, Boolean.toString(value)); + } + public static void action(Context context, int category, String pkg) { if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) { throw new IllegalArgumentException("Must define metric category"); diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java index 2946456..106272b 100644 --- a/core/java/com/android/internal/widget/ActionBarContextView.java +++ b/core/java/com/android/internal/widget/ActionBarContextView.java @@ -192,10 +192,10 @@ public class ActionBarContextView extends AbsActionBarView implements AnimatorLi mTitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_title); mSubtitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_subtitle); if (mTitleStyleRes != 0) { - mTitleView.setTextAppearance(mContext, mTitleStyleRes); + mTitleView.setTextAppearance(mTitleStyleRes); } if (mSubtitleStyleRes != 0) { - mSubtitleView.setTextAppearance(mContext, mSubtitleStyleRes); + mSubtitleView.setTextAppearance(mSubtitleStyleRes); } } diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java index 6b781c3..825e336 100644 --- a/core/java/com/android/internal/widget/ActionBarView.java +++ b/core/java/com/android/internal/widget/ActionBarView.java @@ -813,14 +813,14 @@ public class ActionBarView extends AbsActionBarView implements DecorToolbar { mSubtitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_subtitle); if (mTitleStyleRes != 0) { - mTitleView.setTextAppearance(mContext, mTitleStyleRes); + mTitleView.setTextAppearance(mTitleStyleRes); } if (mTitle != null) { mTitleView.setText(mTitle); } if (mSubtitleStyleRes != 0) { - mSubtitleView.setTextAppearance(mContext, mSubtitleStyleRes); + mSubtitleView.setTextAppearance(mSubtitleStyleRes); } if (mSubtitle != null) { mSubtitleView.setText(mSubtitle); diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java index 3f7696f..f98fbfc 100644 --- a/core/java/com/android/internal/widget/FloatingToolbar.java +++ b/core/java/com/android/internal/widget/FloatingToolbar.java @@ -1247,9 +1247,13 @@ public final class FloatingToolbar { } private static int getAdjustedToolbarWidth(Context context, int width) { - if (width <= 0 || width > getScreenWidth(context)) { - width = context.getResources() - .getDimensionPixelSize(R.dimen.floating_toolbar_default_width); + int maximumWidth = getScreenWidth(context) - 2 * context.getResources() + .getDimensionPixelSize(R.dimen.floating_toolbar_horizontal_margin); + + if (width <= 0 || width > maximumWidth) { + int defaultWidth = context.getResources() + .getDimensionPixelSize(R.dimen.floating_toolbar_preferred_width); + width = Math.min(defaultWidth, maximumWidth); } return width; } |
