summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/animation/AnimatorInflater.java2
-rw-r--r--core/java/android/app/Activity.java25
-rw-r--r--core/java/android/app/BackStackRecord.java1
-rw-r--r--core/java/android/app/Dialog.java22
-rw-r--r--core/java/android/app/IUserSwitchObserver.aidl1
-rw-r--r--core/java/android/app/KeyguardManager.java26
-rw-r--r--core/java/android/app/SharedElementCallback.java46
-rw-r--r--core/java/android/app/admin/DeviceInitializerStatus.java177
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java204
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl10
-rw-r--r--core/java/android/app/admin/OtaPolicy.java179
-rw-r--r--core/java/android/app/backup/BackupTransport.java7
-rw-r--r--core/java/android/app/trust/ITrustManager.aidl1
-rw-r--r--core/java/android/content/Intent.java8
-rw-r--r--core/java/android/hardware/camera2/CameraCharacteristics.java6
-rw-r--r--core/java/android/hardware/camera2/CameraMetadata.java18
-rw-r--r--core/java/android/hardware/location/GeofenceHardwareImpl.java27
-rw-r--r--core/java/android/hardware/location/GeofenceHardwareService.java11
-rw-r--r--core/java/android/hardware/location/IFusedLocationHardware.aidl29
-rw-r--r--core/java/android/hardware/location/IFusedLocationHardwareSink.aidl16
-rw-r--r--core/java/android/net/IpPrefix.java15
-rw-r--r--core/java/android/net/RouteInfo.java8
-rw-r--r--core/java/android/os/IHardwareService.aidl26
-rw-r--r--core/java/android/os/UserManager.java4
-rw-r--r--core/java/android/provider/Settings.java9
-rw-r--r--core/java/android/provider/VoicemailContract.java5
-rw-r--r--core/java/android/security/keymaster/KeyCharacteristics.java55
-rw-r--r--core/java/android/security/keymaster/KeymasterArguments.java9
-rw-r--r--core/java/android/service/chooser/ChooserTarget.java139
-rw-r--r--core/java/android/service/chooser/ChooserTargetService.java25
-rw-r--r--core/java/android/service/dreams/DreamService.java7
-rw-r--r--core/java/android/service/notification/ZenModeConfig.java11
-rw-r--r--core/java/android/view/PhoneWindow.java11
-rw-r--r--core/java/android/view/SearchEvent.java40
-rw-r--r--core/java/android/view/View.java68
-rw-r--r--core/java/android/view/ViewGroup.java98
-rw-r--r--core/java/android/view/Window.java9
-rw-r--r--core/java/android/view/WindowCallbackWrapper.java5
-rw-r--r--core/java/android/widget/ActionMenuPresenter.java67
-rwxr-xr-xcore/java/android/widget/DatePickerCalendarDelegate.java12
-rw-r--r--core/java/android/widget/DayPickerView.java92
-rw-r--r--core/java/android/widget/SimpleMonthView.java18
-rw-r--r--core/java/android/widget/TextView.java1
-rw-r--r--core/java/android/widget/YearPickerView.java27
-rw-r--r--core/java/com/android/internal/app/AlertController.java59
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java392
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java469
-rw-r--r--core/java/com/android/internal/backup/LocalTransport.java53
-rw-r--r--core/java/com/android/internal/logging/MetricsLogger.java3
-rw-r--r--core/java/com/android/internal/os/PowerProfile.java2
-rw-r--r--core/java/com/android/internal/transition/ActionBarTransition.java58
-rw-r--r--core/java/com/android/internal/widget/ActionBarView.java11
-rw-r--r--core/java/com/android/internal/widget/DialogViewAnimator.java141
-rw-r--r--core/java/com/android/internal/widget/ViewPager.java2
54 files changed, 2276 insertions, 491 deletions
diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java
index df5a4cb..224e8e9 100644
--- a/core/java/android/animation/AnimatorInflater.java
+++ b/core/java/android/animation/AnimatorInflater.java
@@ -698,7 +698,7 @@ public class AnimatorInflater {
int ordering = a.getInt(R.styleable.AnimatorSet_ordering, TOGETHER);
createAnimatorFromXml(res, theme, parser, attrs, (AnimatorSet) anim, ordering,
pixelSize);
- final int hint = a.getInt(R.styleable.Animator_durationScaleHint,
+ final int hint = a.getInt(R.styleable.AnimatorSet_durationScaleHint,
HINT_NO_SCALE);
anim.setDurationScaleHint(hint, res);
a.recycle();
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index a0d59d9..6cf6481 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -89,6 +89,7 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.PhoneWindow;
+import android.view.SearchEvent;
import android.view.View;
import android.view.View.OnCreateContextMenuListener;
import android.view.ViewGroup;
@@ -787,6 +788,8 @@ public class Activity extends ContextThemeWrapper
private TranslucentConversionListener mTranslucentCallback;
private boolean mChangeCanvasToTranslucent;
+ private SearchEvent mSearchEvent;
+
private boolean mTitleReady = false;
private int mActionModeTypeStarting = ActionMode.TYPE_PRIMARY;
@@ -3547,12 +3550,23 @@ public class Activity extends ContextThemeWrapper
* implementation changes to simply return false and you must supply your own custom
* implementation if you want to support search.</p>
*
+ * @param searchEvent The {@link SearchEvent} that signaled this search.
* @return Returns {@code true} if search launched, and {@code false} if the activity does
* not respond to search. The default implementation always returns {@code true}, except
* when in {@link Configuration#UI_MODE_TYPE_TELEVISION} mode where it returns false.
*
* @see android.app.SearchManager
*/
+ public boolean onSearchRequested(@Nullable SearchEvent searchEvent) {
+ mSearchEvent = searchEvent;
+ boolean result = onSearchRequested();
+ mSearchEvent = null;
+ return result;
+ }
+
+ /**
+ * @see #onSearchRequested(SearchEvent)
+ */
public boolean onSearchRequested() {
if ((getResources().getConfiguration().uiMode&Configuration.UI_MODE_TYPE_MASK)
!= Configuration.UI_MODE_TYPE_TELEVISION) {
@@ -3564,6 +3578,17 @@ public class Activity extends ContextThemeWrapper
}
/**
+ * During the onSearchRequested() callbacks, this function will return the
+ * {@link SearchEvent} that triggered the callback, if it exists.
+ *
+ * @return SearchEvent The SearchEvent that triggered the {@link
+ * #onSearchRequested} callback.
+ */
+ public final SearchEvent getSearchEvent() {
+ return mSearchEvent;
+ }
+
+ /**
* This hook is called to launch the search UI.
*
* <p>It is typically called from onSearchRequested(), either directly from
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index 83451aa..8fb048b 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -1368,7 +1368,6 @@ final class BackStackRecord extends FragmentTransaction implements
public boolean onPreDraw() {
sceneRoot.getViewTreeObserver().removeOnPreDrawListener(this);
if (enterTransition != null) {
- enterTransition.removeTarget(nonExistingView);
removeTargets(enterTransition, enteringViews);
}
if (exitTransition != null) {
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 786a52f..d049104 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -49,6 +49,7 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.PhoneWindow;
+import android.view.SearchEvent;
import android.view.View;
import android.view.View.OnCreateContextMenuListener;
import android.view.ViewGroup;
@@ -123,6 +124,8 @@ public class Dialog implements DialogInterface, Window.Callback,
private Handler mListenersHandler;
+ private SearchEvent mSearchEvent;
+
private ActionMode mActionMode;
private int mActionModeTypeStarting = ActionMode.TYPE_PRIMARY;
@@ -995,6 +998,14 @@ public class Dialog implements DialogInterface, Window.Callback,
/**
* This hook is called when the user signals the desire to start a search.
*/
+ public boolean onSearchRequested(SearchEvent searchEvent) {
+ mSearchEvent = searchEvent;
+ return onSearchRequested();
+ }
+
+ /**
+ * This hook is called when the user signals the desire to start a search.
+ */
public boolean onSearchRequested() {
final SearchManager searchManager = (SearchManager) mContext
.getSystemService(Context.SEARCH_SERVICE);
@@ -1011,6 +1022,17 @@ public class Dialog implements DialogInterface, Window.Callback,
}
/**
+ * During the onSearchRequested() callbacks, this function will return the
+ * {@link SearchEvent} that triggered the callback, if it exists.
+ *
+ * @return SearchEvent The SearchEvent that triggered the {@link
+ * #onSearchRequested} callback.
+ */
+ public final SearchEvent getSearchEvent() {
+ return mSearchEvent;
+ }
+
+ /**
* {@inheritDoc}
*/
@Override
diff --git a/core/java/android/app/IUserSwitchObserver.aidl b/core/java/android/app/IUserSwitchObserver.aidl
index 845897b..caee14f 100644
--- a/core/java/android/app/IUserSwitchObserver.aidl
+++ b/core/java/android/app/IUserSwitchObserver.aidl
@@ -22,4 +22,5 @@ import android.os.IRemoteCallback;
oneway interface IUserSwitchObserver {
void onUserSwitching(int newUserId, IRemoteCallback reply);
void onUserSwitchComplete(int newUserId);
+ void onForegroundProfileSwitch(int newProfileId);
}
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index ddd21e6..56cd53e 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -253,6 +253,32 @@ public class KeyguardManager {
}
/**
+ * Returns whether the device is secured with a PIN, pattern or
+ * password.
+ *
+ * @return true if a PIN, pattern or password was set.
+ */
+ public boolean isDeviceSecure() {
+ return isDeviceSecure(UserHandle.getCallingUserId());
+ }
+
+ /**
+ * Returns whether the device is secured with a PIN, pattern or
+ * password.
+ *
+ * @param userId the user for which the secure state should be reported.
+ * @return true if a PIN, pattern or password was set.
+ * @hide
+ */
+ public boolean isDeviceSecure(int userId) {
+ try {
+ return mTrustManager.isDeviceSecure(userId);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+ /**
* @deprecated Use {@link android.view.WindowManager.LayoutParams#FLAG_DISMISS_KEYGUARD}
* and/or {@link android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED}
* instead; this allows you to seamlessly hide the keyguard as your application
diff --git a/core/java/android/app/SharedElementCallback.java b/core/java/android/app/SharedElementCallback.java
index e58b7fb..bac84a4 100644
--- a/core/java/android/app/SharedElementCallback.java
+++ b/core/java/android/app/SharedElementCallback.java
@@ -51,9 +51,23 @@ public abstract class SharedElementCallback {
};
/**
- * Called immediately after the start state is set for the shared element.
- * The shared element will start at the size and position of the shared element
- * in the launching Activity or Fragment.
+ * In Activity Transitions, onSharedElementStart is called immediately before
+ * capturing the start of the shared element state on enter and reenter transitions and
+ * immediately before capturing the end of the shared element state for exit and return
+ * transitions.
+ * <p>
+ * In Fragment Transitions, onSharedElementStart is called immediately before capturing the
+ * start state of all shared element transitions.
+ * <p>
+ * This call can be used to adjust the transition start state by modifying the shared
+ * element Views. Note that no layout step will be executed between onSharedElementStart
+ * and the transition state capture.
+ * <p>
+ * For Activity Transitions, any changes made in {@link #onSharedElementEnd(List, List, List)}
+ * that are not updated during by layout should be corrected in onSharedElementStart for exit and
+ * return transitions. For example, rotation or scale will not be affected by layout and
+ * if changed in {@link #onSharedElementEnd(List, List, List)}, it will also have to be reset
+ * in onSharedElementStart again to correct the end state.
*
* @param sharedElementNames The names of the shared elements that were accepted into
* the View hierarchy.
@@ -68,17 +82,23 @@ public abstract class SharedElementCallback {
List<View> sharedElements, List<View> sharedElementSnapshots) {}
/**
- * Called after the end state is set for the shared element, but before the end state
- * is captured by the shared element transition.
+ * In Activity Transitions, onSharedElementEnd is called immediately before
+ * capturing the end of the shared element state on enter and reenter transitions and
+ * immediately before capturing the start of the shared element state for exit and return
+ * transitions.
* <p>
- * Any customization done in
- * {@link #onSharedElementStart(java.util.List, java.util.List, java.util.List)}
- * may need to be modified to the final state of the shared element if it is not
- * automatically corrected by layout. For example, rotation or scale will not
- * be affected by layout and if changed in {@link #onSharedElementStart(java.util.List,
- * java.util.List, java.util.List)}, it will also have to be set here again to correct
- * the end state.
- * </p>
+ * In Fragment Transitions, onSharedElementEnd is called immediately before capturing the
+ * end state of all shared element transitions.
+ * <p>
+ * This call can be used to adjust the transition end state by modifying the shared
+ * element Views. Note that no layout step will be executed between onSharedElementEnd
+ * and the transition state capture.
+ * <p>
+ * Any changes made in {@link #onSharedElementStart(List, List, List)} that are not updated
+ * during layout should be corrected in onSharedElementEnd. For example, rotation or scale
+ * will not be affected by layout and if changed in
+ * {@link #onSharedElementStart(List, List, List)}, it will also have to be reset in
+ * onSharedElementEnd again to correct the end state.
*
* @param sharedElementNames The names of the shared elements that were accepted into
* the View hierarchy.
diff --git a/core/java/android/app/admin/DeviceInitializerStatus.java b/core/java/android/app/admin/DeviceInitializerStatus.java
new file mode 100644
index 0000000..b58711c
--- /dev/null
+++ b/core/java/android/app/admin/DeviceInitializerStatus.java
@@ -0,0 +1,177 @@
+/*
+ * 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.admin;
+
+/**
+ * Defines constants designating device provisioning status used with {@link
+ * android.app.admin.DevicePolicyManager#sendDeviceInitializerStatus(int,String)}.
+ *
+ * This class contains flag constants that define special status codes:
+ * <ul>
+ * <li>{@link #FLAG_STATUS_ERROR} is used to define provisioning error status codes
+ * <li>{@link #FLAG_STATUS_CUSTOM} is used to define custom status codes
+ * <li>{@link #FLAG_STATUS_HIGH_PRIORITY} is used to define high priority status codes
+ * </ul>
+ *
+ * <p>Status codes used by ManagedProvisioning are also defined in this class. These status codes
+ * include provisioning errors and status codes.
+ * <ul>
+ * <li>{@link #STATUS_ERROR_CONNECT_WIFI}
+ * <li>{@link #STATUS_ERROR_RESET_PROTECTION_BLOCKING_PROVISIONING}
+ * <li>{@link #STATUS_ERROR_DOWNLOAD_PACKAGE}
+ * <li>{@link #STATUS_ERROR_INSTALL_PACKAGE}
+ * <li>{@link #STATUS_ERROR_SET_DEVICE_POLICY}
+ * <li>{@link #STATUS_ERROR_DELETE_APPS}
+ * <li>{@link #STATUS_ERROR_DOUBLE_BUMP}
+ * <li>{@link #STATUS_STATE_CONNECT_BLUETOOTH_PROXY}
+ * <li>{@link #STATUS_STATE_DISCONNECT_BLUETOOTH_PROXY}
+ * <li>{@link #STATUS_STATE_DEVICE_PROVISIONED}
+ * </ul>
+ */
+public class DeviceInitializerStatus {
+ /**
+ * A flag used to designate an error status.
+ *
+ * <p>This flag is used with {@code statusCode} values sent through
+ * {@link android.app.admin.DevicePolicyManager#sendDeviceInitializerStatus(int,String)}
+ * @see #isErrorStatus(int)
+ */
+ public static final int FLAG_STATUS_ERROR = 0x01000000;
+
+ /**
+ * A flag used to designate a custom status. Custom status codes will be defined by device
+ * initializer agents.
+ *
+ * <p>This flag is used with {@code statusCode} values sent through
+ * {@link android.app.admin.DevicePolicyManager#sendDeviceInitializerStatus(int,String)}
+ * @see #isCustomStatus(int)
+ */
+ public static final int FLAG_STATUS_CUSTOM = 0x02000000;
+
+ /**
+ * A bit flag used to designate a reserved status. Reserved status codes will not be defined
+ * in AOSP.
+ *
+ * <p>This flag is used with {@code statusCode} values sent through
+ * {@link android.app.admin.DevicePolicyManager#sendDeviceInitializerStatus(int,String)}
+ */
+ public static final int FLAG_STATUS_RESERVED = 0x04000000;
+
+ /**
+ * A flag used to indicate that a status message is high priority.
+ *
+ * <p>This flag is used with {@code statusCode} values sent through
+ * {@link android.app.admin.DevicePolicyManager#sendDeviceInitializerStatus(int,String)}
+ * @see #isHighPriority(int)
+ */
+ public static final int FLAG_STATUS_HIGH_PRIORITY = 0x08000000;
+
+ /**
+ * Device provisioning status code that indicates that a device is connecting to establish
+ * a Bluetooth network proxy.
+ */
+ public static final int STATUS_STATE_CONNECT_BLUETOOTH_PROXY = FLAG_STATUS_HIGH_PRIORITY | 8;
+
+ /**
+ * Device provisioning status code that indicates that a connected Bluetooth network proxy
+ * is being shut down.
+ */
+ public static final int STATUS_STATE_DISCONNECT_BLUETOOTH_PROXY = FLAG_STATUS_HIGH_PRIORITY | 9;
+
+ /**
+ * Device provisioning status code that indicates that a device has been successfully
+ * provisioned.
+ */
+ public static final int STATUS_STATE_DEVICE_PROVISIONED = FLAG_STATUS_HIGH_PRIORITY | 10;
+
+ /**
+ * Device provisioning error status code that indicates that a device could not connect to
+ * a Wi-Fi network.
+ */
+ public static final int STATUS_ERROR_CONNECT_WIFI = FLAG_STATUS_ERROR | 21;
+
+ /**
+ * Device provisioning error status indicating that factory reset protection is enabled on
+ * the provisioned device and cannot be disabled with the provided data.
+ */
+ public static final int STATUS_ERROR_RESET_PROTECTION_BLOCKING_PROVISIONING =
+ FLAG_STATUS_ERROR | 22;
+
+ /**
+ * Device provisioning error status indicating that device administrator and device initializer
+ * packages could not be downloaded and verified successfully.
+ */
+ public static final int STATUS_ERROR_DOWNLOAD_PACKAGE = FLAG_STATUS_ERROR | 23;
+
+ /**
+ * Device provisioning error status indicating that device owner and device initializer packages
+ * could not be installed.
+ */
+ public static final int STATUS_ERROR_INSTALL_PACKAGE = FLAG_STATUS_ERROR | 24;
+
+ /**
+ * Device provisioning error status indicating that the device owner or device initializer
+ * components could not be set.
+ */
+ public static final int STATUS_ERROR_SET_DEVICE_POLICY = FLAG_STATUS_ERROR | 25;
+
+ /**
+ * Device provisioning error status indicating that deleting non-required applications during
+ * provisioning failed.
+ */
+ public static final int STATUS_ERROR_DELETE_APPS = FLAG_STATUS_ERROR | 26;
+
+ /**
+ * Device provisioning error status code that indicates that a provisioning attempt has failed
+ * because the device has already been provisioned or that provisioning has already started.
+ */
+ public static final int STATUS_ERROR_DOUBLE_BUMP = FLAG_STATUS_ERROR | 30;
+
+ /**
+ * Determine if the specified status code represents an error status.
+ * @param statusCode status code to check
+ * @return {@code true} if the status code is an error status code
+ */
+ public static boolean isErrorStatus(int statusCode) {
+ return isFlagSet(statusCode, FLAG_STATUS_ERROR);
+ }
+
+ /**
+ * Determine if the specified status code is a custom status. Custom status codes are defined
+ * and sent by device initialization agents.
+ * @param statusCode status code to check
+ * @return {@code true} if the status code is a custom status code
+ */
+ public static boolean isCustomStatus(int statusCode) {
+ return isFlagSet(statusCode, FLAG_STATUS_CUSTOM);
+ }
+
+ /**
+ * Determine if the specified status code is a high priority status code.
+ * @param statusCode status code to check
+ * @return {@code true} if the status code is a high priority status code
+ */
+ public static boolean isHighPriority(int statusCode) {
+ return isFlagSet(statusCode, FLAG_STATUS_HIGH_PRIORITY);
+ }
+
+ private static boolean isFlagSet(int statusCode, int flag) {
+ return (statusCode & flag) != 0;
+ }
+
+ private DeviceInitializerStatus() {}
+}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 68f4707..a0a6c4c 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -651,6 +651,45 @@ public class DevicePolicyManager {
= "android.app.action.SET_PROFILE_OWNER";
/**
+ * Protected broadcast action that will be sent to managed provisioning to notify it that a
+ * status update has been reported by the device initializer. The status update will be
+ * reported to the remote setup device over Bluetooth.
+ *
+ * <p>Broadcasts with this action must supply a
+ * {@linkplain DeviceInitializerStatus#isCustomStatus(int) custom} status code in the
+ * {@link EXTRA_DEVICE_INITIALIZER_STATUS_CODE} extra.
+ *
+ * <p>Broadcasts may optionally contain a description in the
+ * {@link EXTRA_DEVICE_INITIALIZER_STATUS_DESCRIPTION} extra.
+ * @hide
+ */
+ @SystemApi
+ public static final String ACTION_SEND_DEVICE_INITIALIZER_STATUS
+ = "android.app.action.SEND_DEVICE_INITIALIZER_STATUS";
+
+ /**
+ * An integer extra that contains the status code that defines a status update. This extra must
+ * sent as part of a broadcast with an action of {@code ACTION_SEND_DEVICE_INITIALIZER_STATUS}.
+ *
+ * <p>The status code sent with this extra must be a custom status code as defined by
+ * {@link DeviceInitializerStatus#isCustomStatus(int)}.
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_DEVICE_INITIALIZER_STATUS_CODE
+ = "android.app.extra.DEVICE_INITIALIZER_STATUS_CODE";
+
+ /**
+ * A {@code String} extra that contains an optional description accompanying a status update.
+ * This extra my be sent as part of a broadcast with an action of
+ * {@code ACTION_SEND_DEVICE_INITIALIZER_STATUS}.
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_DEVICE_INITIALIZER_STATUS_DESCRIPTION
+ = "android.app.extra.DEVICE_INITIALIZER_STATUS_DESCRIPTION";
+
+ /**
* @hide
* Name of the profile owner admin that controls the user.
*/
@@ -715,6 +754,14 @@ public class DevicePolicyManager {
public static final int FLAG_MANAGED_CAN_ACCESS_PARENT = 0x0002;
/**
+ * Broadcast action: notify that a new local OTA policy has been set by the device owner.
+ * The new policy can be retrieved by {@link #getOtaPolicy()}.
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_OTA_POLICY_CHANGED = "android.app.action.OTA_POLICY_CHANGED";
+
+
+ /**
* Return true if the given administrator component is currently
* active (enabled) in the system.
*/
@@ -2170,7 +2217,8 @@ public class DevicePolicyManager {
* Called by a device or profile owner to install a certificate and private key pair. The
* keypair will be visible to all apps within the profile.
*
- * @param who Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param who Which {@link DeviceAdminReceiver} this request is associated with. Use
+ * <code>null</code> if calling from a delegated certificate installer.
* @param privKey The private key to install.
* @param cert The certificate to install.
* @param alias The private key alias under which to install the certificate. If a certificate
@@ -2207,9 +2255,9 @@ public class DevicePolicyManager {
/**
* Called by a profile owner or device owner to grant access to privileged certificate
- * manipulation APIs to a third-party CA certificate installer app. Granted APIs include
+ * manipulation APIs to a third-party certificate installer app. Granted APIs include
* {@link #getInstalledCaCerts}, {@link #hasCaCertInstalled}, {@link #installCaCert},
- * {@link #uninstallCaCert} and {@link #uninstallAllUserCaCerts}.
+ * {@link #uninstallCaCert}, {@link #uninstallAllUserCaCerts} and {@link #installKeyPair}.
* <p>
* Delegated certificate installer is a per-user state. The delegated access is persistent until
* it is later cleared by calling this method with a null value or uninstallling the certificate
@@ -3214,6 +3262,73 @@ public class DevicePolicyManager {
}
/**
+ * Called by a profile owner of a managed profile to set whether bluetooth
+ * devices can access enterprise contacts.
+ * <p>
+ * The calling device admin must be a profile owner. If it is not, a
+ * security exception will be thrown.
+ * <p>
+ * This API works on managed profile only.
+ *
+ * @param who Which {@link DeviceAdminReceiver} this request is associated
+ * with.
+ * @param disabled If true, bluetooth devices cannot access enterprise
+ * contacts.
+ */
+ public void setBluetoothContactSharingDisabled(ComponentName who, boolean disabled) {
+ if (mService != null) {
+ try {
+ mService.setBluetoothContactSharingDisabled(who, disabled);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ }
+
+ /**
+ * Called by a profile owner of a managed profile to determine whether or
+ * not Bluetooth devices cannot access enterprise contacts.
+ * <p>
+ * The calling device admin must be a profile owner. If it is not, a
+ * security exception will be thrown.
+ * <p>
+ * This API works on managed profile only.
+ *
+ * @param who Which {@link DeviceAdminReceiver} this request is associated
+ * with.
+ */
+ public boolean getBluetoothContactSharingDisabled(ComponentName who) {
+ if (mService != null) {
+ try {
+ return mService.getBluetoothContactSharingDisabled(who);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Determine whether or not Bluetooth devices cannot access contacts.
+ * <p>
+ * This API works on managed profile UserHandle only.
+ *
+ * @param userHandle The user for whom to check the caller-id permission
+ * @hide
+ */
+ public boolean getBluetoothContactSharingDisabled(UserHandle userHandle) {
+ if (mService != null) {
+ try {
+ return mService.getBluetoothContactSharingDisabledForUser(userHandle
+ .getIdentifier());
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return true;
+ }
+
+ /**
* Called by the profile owner of a managed profile so that some intents sent in the managed
* profile can also be resolved in the parent, or vice versa.
* Only activity intents are supported.
@@ -4012,4 +4127,87 @@ public class DevicePolicyManager {
Log.w(TAG, "Could not set the user icon ", re);
}
}
+
+ /**
+ * Called by device initializer to send a provisioning status update to the remote setup device.
+ *
+ * @param statusCode a custom status code value as defined by
+ * {@link DeviceInitializerStatus#isCustomStatus(int)}.
+ * @param description custom description of the status code sent
+ */
+ public void sendDeviceInitializerStatus(int statusCode, String description) {
+ try {
+ mService.sendDeviceInitializerStatus(statusCode, description);
+ } catch (RemoteException re) {
+ Log.w(TAG, "Could not send device initializer status", re);
+ }
+ }
+
+ /*
+ * Called by device owners to set a local OTA update policy. When a new OTA policy is set,
+ * {@link #ACTION_OTA_POLICY_CHANGED} is broadcasted.
+ *
+ * @param who Which {@link DeviceAdminReceiver} this request is associated with. All components
+ * in the device owner package can set OTA policies and the most recent policy takes effect.
+ * @param policy the new OTA policy, or null to clear the current policy.
+ * @see OtaPolicy
+ */
+ public void setOtaPolicy(ComponentName who, OtaPolicy policy) {
+ if (mService != null) {
+ try {
+ if (policy != null) {
+ mService.setOtaPolicy(who, policy.getPolicyBundle());
+ } else {
+ mService.setOtaPolicy(who, null);
+ }
+ } catch (RemoteException re) {
+ Log.w(TAG, "Error calling setOtaPolicy", re);
+ }
+ }
+ }
+
+ /**
+ * Retrieve a local OTA update policy set previously by {@link #setOtaPolicy}.
+ *
+ * @return The current OTA policy object, or null if no policy is set or the system does not
+ * support managed OTA.
+ */
+ public OtaPolicy getOtaPolicy() {
+ if (mService != null) {
+ try {
+ PersistableBundle bundle = mService.getOtaPolicy();
+ if (bundle != null) {
+ return new OtaPolicy(bundle);
+ } else {
+ return null;
+ }
+ } catch (RemoteException re) {
+ Log.w(TAG, "Error calling getOtaPolicy", re);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Called by a device owner to disable the keyguard altogether.
+ *
+ * <p>Setting the keyguard to disabled has the same effect as choosing "None" as the screen
+ * lock type. However, this call has no effect if a password, pin or pattern is currently set.
+ * If a password, pin or pattern is set after the keyguard was disabled, the keyguard stops
+ * being disabled.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param enabled New state of the keyguard.
+ *
+ * @return {@code false} if attempting to disable the keyguard while a lock password was in
+ * place. {@code true} otherwise."
+ */
+ public boolean setKeyguardEnabledState(ComponentName admin, boolean enabled) {
+ try {
+ return mService.setKeyguardEnabledState(admin, enabled);
+ } catch (RemoteException re) {
+ Log.w(TAG, "Failed talking with device policy service", re);
+ return false;
+ }
+ }
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index c68311e..131b99c 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -191,6 +191,10 @@ interface IDevicePolicyManager {
boolean getCrossProfileCallerIdDisabledForUser(int userId);
void startManagedQuickContact(String lookupKey, long contactId, in Intent originalIntent);
+ void setBluetoothContactSharingDisabled(in ComponentName who, boolean disabled);
+ boolean getBluetoothContactSharingDisabled(in ComponentName who);
+ boolean getBluetoothContactSharingDisabledForUser(int userId);
+
void setTrustAgentConfiguration(in ComponentName admin, in ComponentName agent,
in PersistableBundle args);
List<PersistableBundle> getTrustAgentConfiguration(in ComponentName admin,
@@ -213,4 +217,10 @@ interface IDevicePolicyManager {
ComponentName getDeviceInitializerComponent();
void setUserIcon(in ComponentName admin, in Bitmap icon);
+
+ void sendDeviceInitializerStatus(int statusCode, String description);
+ void setOtaPolicy(in ComponentName who, in PersistableBundle policy);
+ PersistableBundle getOtaPolicy();
+
+ boolean setKeyguardEnabledState(in ComponentName admin, boolean enabled);
}
diff --git a/core/java/android/app/admin/OtaPolicy.java b/core/java/android/app/admin/OtaPolicy.java
new file mode 100644
index 0000000..98581a7
--- /dev/null
+++ b/core/java/android/app/admin/OtaPolicy.java
@@ -0,0 +1,179 @@
+/*
+ * 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.admin;
+
+import android.annotation.IntDef;
+import android.os.PersistableBundle;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * A class that represents a local OTA policy set by the device owner.
+ *
+ * @see DevicePolicyManager#setOtaPolicy
+ * @see DevicePolicyManager#getOtaPolicy
+ */
+public class OtaPolicy {
+
+ /** @hide */
+ @IntDef({
+ TYPE_INSTALL_AUTOMATIC,
+ TYPE_INSTALL_WINDOWED,
+ TYPE_POSTPONE})
+ @Retention(RetentionPolicy.SOURCE)
+ @interface OtaPolicyType {}
+
+ /**
+ * Install OTA update automatically as soon as one is available.
+ */
+ public static final int TYPE_INSTALL_AUTOMATIC = 1;
+
+ /**
+ * Install OTA update automatically within a daily maintenance window, for a maximum of two-week
+ * period. After that period the OTA will be installed automatically.
+ */
+ public static final int TYPE_INSTALL_WINDOWED = 2;
+
+ /**
+ * Incoming OTA will be blocked for a maximum of two weeks, after which it will be installed
+ * automatically.
+ */
+ public static final int TYPE_POSTPONE = 3;
+
+ 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";
+
+ private PersistableBundle mPolicy;
+
+ public OtaPolicy() {
+ mPolicy = new PersistableBundle();
+ }
+
+ /**
+ * Construct an OtaPolicy object from a bundle.
+ * @hide
+ */
+ public OtaPolicy(PersistableBundle in) {
+ mPolicy = new PersistableBundle(in);
+ }
+
+ /**
+ * Retrieve the underlying bundle where the policy is stored.
+ * @hide
+ */
+ public PersistableBundle getPolicyBundle() {
+ return new PersistableBundle(mPolicy);
+ }
+
+ /**
+ * Set the OTA policy to: install OTA update automatically as soon as one is available.
+ */
+ public void setAutomaticInstallPolicy() {
+ mPolicy.clear();
+ mPolicy.putInt(KEY_POLICY_TYPE, TYPE_INSTALL_AUTOMATIC);
+ }
+
+ /**
+ * Set the OTA policy to: new OTA 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, OTAs can install at any time. If
+ * the given window in invalid, a {@link OtaPolicy.InvalidWindowException} 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 two weeks, after which
+ * the OTA will be installed automatically.
+ *
+ * @param startTime the start of the maintenance window, measured as the number of minutes from
+ * midnight in the device's local time. Must be in the range of [0, 1440).
+ * @param endTime the end of the maintenance window, measured as the number of minutes from
+ * midnight in the device's local time. Must be in the range of [0, 1440).
+ */
+ 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)");
+ }
+ mPolicy.clear();
+ mPolicy.putInt(KEY_POLICY_TYPE, TYPE_INSTALL_WINDOWED);
+ mPolicy.putInt(KEY_INSTALL_WINDOW_START, startTime);
+ mPolicy.putInt(KEY_INSTALL_WINDOW_END, endTime);
+ }
+
+ /**
+ * Set the OTA policy to: block installation for a maximum period of two weeks. After the
+ * block expires the OTA will be installed automatically.
+ */
+ public void setPostponeInstallPolicy() {
+ mPolicy.clear();
+ mPolicy.putInt(KEY_POLICY_TYPE, TYPE_POSTPONE);
+ }
+
+ /**
+ * Returns the type of OTA policy.
+ *
+ * @return an integer, either one of {@link #TYPE_INSTALL_AUTOMATIC},
+ * {@link #TYPE_INSTALL_WINDOWED} and {@link #TYPE_POSTPONE}, or -1 if no policy has been set.
+ */
+ @OtaPolicyType
+ public int getPolicyType() {
+ return mPolicy.getInt(KEY_POLICY_TYPE, -1);
+ }
+
+ /**
+ * Get the start of the maintenance window.
+ *
+ * @return the start of the maintenance window measured as the number of minutes from midnight,
+ * 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);
+ } else {
+ return -1;
+ }
+ }
+
+ /**
+ * Get the end of the maintenance window.
+ *
+ * @return the end of the maintenance window measured as the number of minutes from midnight,
+ * 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);
+ } else {
+ return -1;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return mPolicy.toString();
+ }
+
+ /**
+ * Exception thrown by {@link OtaPolicy#setWindowedInstallPolicy(int, int)} in case the
+ * specified window is invalid.
+ */
+ public static class InvalidWindowException extends Exception {
+ public InvalidWindowException(String reason) {
+ super(reason);
+ }
+ }
+}
+
diff --git a/core/java/android/app/backup/BackupTransport.java b/core/java/android/app/backup/BackupTransport.java
index 1131ff9..9540eb1 100644
--- a/core/java/android/app/backup/BackupTransport.java
+++ b/core/java/android/app/backup/BackupTransport.java
@@ -399,6 +399,13 @@ public class BackupTransport {
* operation will be skipped (and {@link #finishBackup() invoked} with no data for that
* package being passed to {@link #sendBackupData}.
*
+ * <p class="note">The platform does no size-based rejection of full backup attempts on
+ * its own: it is always the responsibility of the transport to implement its own policy.
+ * In particular, even if the preflighted payload size is zero, the platform will still call
+ * this method and will proceed to back up an archive metadata header with no file content
+ * if this method returns TRANSPORT_OK. To avoid storing such payloads the transport
+ * must recognize this case and return TRANSPORT_PACKAGE_REJECTED.
+ *
* Added in MNC (API 23).
*
* @param size The estimated size of the full-data payload for this app. This includes
diff --git a/core/java/android/app/trust/ITrustManager.aidl b/core/java/android/app/trust/ITrustManager.aidl
index 68ea0aa..17cff5c 100644
--- a/core/java/android/app/trust/ITrustManager.aidl
+++ b/core/java/android/app/trust/ITrustManager.aidl
@@ -31,4 +31,5 @@ interface ITrustManager {
void unregisterTrustListener(in ITrustListener trustListener);
void reportKeyguardShowingChanged();
boolean isDeviceLocked(int userId);
+ boolean isDeviceSecure(int userId);
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index eea47b7..54fe786 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3311,6 +3311,14 @@ 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/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index f01c540..8f7aed4 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -639,7 +639,8 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
/**
* <p>Whether the camera device supports {@link CaptureRequest#CONTROL_AE_LOCK android.control.aeLock}</p>
- * <p>LIMITED or FULL devices will always list <code>true</code></p>
+ * <p>Devices with MANUAL_SENSOR capability or BURST_CAPTURE capability will always
+ * list <code>true</code>. This includes FULL devices.</p>
* <p>This key is available on all devices.</p>
*
* @see CaptureRequest#CONTROL_AE_LOCK
@@ -650,7 +651,8 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
/**
* <p>Whether the camera device supports {@link CaptureRequest#CONTROL_AWB_LOCK android.control.awbLock}</p>
- * <p>LIMITED or FULL devices will always list <code>true</code></p>
+ * <p>Devices with MANUAL_POST_PROCESSING capability or BURST_CAPTURE capability will
+ * always list <code>true</code>. This includes FULL devices.</p>
* <p>This key is available on all devices.</p>
*
* @see CaptureRequest#CONTROL_AWB_LOCK
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 2192ab7..4a5bd08 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -347,6 +347,10 @@ public abstract class CameraMetadata<TKey> {
* <li>{@link CaptureRequest#BLACK_LEVEL_LOCK android.blackLevel.lock}</li>
* </ul>
* </li>
+ * <li>Auto exposure lock<ul>
+ * <li>{@link CaptureRequest#CONTROL_AE_LOCK android.control.aeLock}</li>
+ * </ul>
+ * </li>
* </ul>
* <p>If any of the above 3A algorithms are enabled, then the camera
* device will accurately report the values applied by 3A in the
@@ -358,6 +362,7 @@ public abstract class CameraMetadata<TKey> {
* zero for each supported size-format combination.</p>
*
* @see CaptureRequest#BLACK_LEVEL_LOCK
+ * @see CaptureRequest#CONTROL_AE_LOCK
* @see CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP
* @see CaptureRequest#SENSOR_EXPOSURE_TIME
* @see CaptureRequest#SENSOR_FRAME_DURATION
@@ -403,6 +408,10 @@ public abstract class CameraMetadata<TKey> {
* <li>{@link CameraCharacteristics#COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES android.colorCorrection.availableAberrationModes}</li>
* </ul>
* </li>
+ * <li>Auto white balance lock<ul>
+ * <li>{@link CaptureRequest#CONTROL_AWB_LOCK android.control.awbLock}</li>
+ * </ul>
+ * </li>
* </ul>
* <p>If auto white balance is enabled, then the camera device
* will accurately report the values applied by AWB in the result.</p>
@@ -413,6 +422,7 @@ public abstract class CameraMetadata<TKey> {
* @see CameraCharacteristics#COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES
* @see CaptureRequest#COLOR_CORRECTION_GAINS
* @see CaptureRequest#COLOR_CORRECTION_TRANSFORM
+ * @see CaptureRequest#CONTROL_AWB_LOCK
* @see CaptureRequest#SHADING_MODE
* @see CaptureRequest#STATISTICS_LENS_SHADING_MAP_MODE
* @see CaptureRequest#TONEMAP_CURVE
@@ -530,9 +540,15 @@ public abstract class CameraMetadata<TKey> {
* YUV_420_888 format.</p>
* </blockquote>
* <p>In addition, the {@link CameraCharacteristics#SYNC_MAX_LATENCY android.sync.maxLatency} field is
- * guaranted to have a value between 0 and 4, inclusive.</p>
+ * guaranted to have a value between 0 and 4, inclusive.
+ * {@link CameraCharacteristics#CONTROL_AE_LOCK_AVAILABLE android.control.aeLockAvailable} and
+ * {@link CameraCharacteristics#CONTROL_AWB_LOCK_AVAILABLE android.control.awbLockAvailable} are also guaranteed
+ * to be <code>true</code> so burst capture with these two locks ON
+ * yields consistent image output.</p>
*
* @see CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES
+ * @see CameraCharacteristics#CONTROL_AE_LOCK_AVAILABLE
+ * @see CameraCharacteristics#CONTROL_AWB_LOCK_AVAILABLE
* @see CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP
* @see CameraCharacteristics#SYNC_MAX_LATENCY
* @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
diff --git a/core/java/android/hardware/location/GeofenceHardwareImpl.java b/core/java/android/hardware/location/GeofenceHardwareImpl.java
index 4696b2a..5d40e94 100644
--- a/core/java/android/hardware/location/GeofenceHardwareImpl.java
+++ b/core/java/android/hardware/location/GeofenceHardwareImpl.java
@@ -53,6 +53,7 @@ public final class GeofenceHardwareImpl {
private IFusedGeofenceHardware mFusedService;
private IGpsGeofenceHardware mGpsService;
+ private int mCapabilities;
private int[] mSupportedMonitorTypes = new int[GeofenceHardware.NUM_MONITORS];
@@ -89,6 +90,9 @@ public final class GeofenceHardwareImpl {
private static final int RESOLUTION_LEVEL_COARSE = 2;
private static final int RESOLUTION_LEVEL_FINE = 3;
+ // Capability constant corresponding to fused_location.h entry when geofencing supports GNNS.
+ private static final int CAPABILITY_GNSS = 1;
+
public synchronized static GeofenceHardwareImpl getInstance(Context context) {
if (sInstance == null) {
sInstance = new GeofenceHardwareImpl(context);
@@ -141,7 +145,9 @@ public final class GeofenceHardwareImpl {
private void updateFusedHardwareAvailability() {
boolean fusedSupported;
try {
- fusedSupported = (mFusedService != null ? mFusedService.isSupported() : false);
+ fusedSupported = (mFusedService != null
+ ? mFusedService.isSupported() && (mCapabilities & CAPABILITY_GNSS) != 0
+ : false);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException calling LocationManagerService");
fusedSupported = false;
@@ -166,6 +172,11 @@ public final class GeofenceHardwareImpl {
}
}
+ public void onCapabilities(int capabilities) {
+ mCapabilities = capabilities;
+ updateFusedHardwareAvailability();
+ }
+
public void setFusedGeofenceHardware(IFusedGeofenceHardware service) {
if(mFusedService == null) {
mFusedService = service;
@@ -212,6 +223,20 @@ public final class GeofenceHardwareImpl {
}
}
+ public int getCapabilitiesForMonitoringType(int monitoringType) {
+ switch (mSupportedMonitorTypes[monitoringType]) {
+ case GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE:
+ switch (monitoringType) {
+ case GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE:
+ return CAPABILITY_GNSS;
+ case GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE:
+ return mCapabilities;
+ }
+ break;
+ }
+ return 0;
+ }
+
public boolean addCircularFence(
int monitoringType,
GeofenceHardwareRequestParcelable request,
diff --git a/core/java/android/hardware/location/GeofenceHardwareService.java b/core/java/android/hardware/location/GeofenceHardwareService.java
index 4816c5f..c0bcb27 100644
--- a/core/java/android/hardware/location/GeofenceHardwareService.java
+++ b/core/java/android/hardware/location/GeofenceHardwareService.java
@@ -65,14 +65,17 @@ public class GeofenceHardwareService extends Service {
}
private IBinder mBinder = new IGeofenceHardware.Stub() {
+ @Override
public void setGpsGeofenceHardware(IGpsGeofenceHardware service) {
mGeofenceHardwareImpl.setGpsHardwareGeofence(service);
}
+ @Override
public void setFusedGeofenceHardware(IFusedGeofenceHardware service) {
mGeofenceHardwareImpl.setFusedGeofenceHardware(service);
}
+ @Override
public int[] getMonitoringTypes() {
mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
"Location Hardware permission not granted to access hardware geofence");
@@ -80,12 +83,15 @@ public class GeofenceHardwareService extends Service {
return mGeofenceHardwareImpl.getMonitoringTypes();
}
+ @Override
public int getStatusOfMonitoringType(int monitoringType) {
mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
"Location Hardware permission not granted to access hardware geofence");
return mGeofenceHardwareImpl.getStatusOfMonitoringType(monitoringType);
}
+
+ @Override
public boolean addCircularFence(
int monitoringType,
GeofenceHardwareRequestParcelable request,
@@ -96,6 +102,7 @@ public class GeofenceHardwareService extends Service {
return mGeofenceHardwareImpl.addCircularFence(monitoringType, request, callback);
}
+ @Override
public boolean removeGeofence(int id, int monitoringType) {
mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
"Location Hardware permission not granted to access hardware geofence");
@@ -104,6 +111,7 @@ public class GeofenceHardwareService extends Service {
return mGeofenceHardwareImpl.removeGeofence(id, monitoringType);
}
+ @Override
public boolean pauseGeofence(int id, int monitoringType) {
mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
"Location Hardware permission not granted to access hardware geofence");
@@ -112,6 +120,7 @@ public class GeofenceHardwareService extends Service {
return mGeofenceHardwareImpl.pauseGeofence(id, monitoringType);
}
+ @Override
public boolean resumeGeofence(int id, int monitoringType, int monitorTransitions) {
mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
"Location Hardware permission not granted to access hardware geofence");
@@ -120,6 +129,7 @@ public class GeofenceHardwareService extends Service {
return mGeofenceHardwareImpl.resumeGeofence(id, monitoringType, monitorTransitions);
}
+ @Override
public boolean registerForMonitorStateChangeCallback(int monitoringType,
IGeofenceHardwareMonitorCallback callback) {
mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
@@ -130,6 +140,7 @@ public class GeofenceHardwareService extends Service {
callback);
}
+ @Override
public boolean unregisterForMonitorStateChangeCallback(int monitoringType,
IGeofenceHardwareMonitorCallback callback) {
mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
diff --git a/core/java/android/hardware/location/IFusedLocationHardware.aidl b/core/java/android/hardware/location/IFusedLocationHardware.aidl
index 382c12c..3de766a 100644
--- a/core/java/android/hardware/location/IFusedLocationHardware.aidl
+++ b/core/java/android/hardware/location/IFusedLocationHardware.aidl
@@ -32,21 +32,21 @@ interface IFusedLocationHardware {
*
* @param eventSink The sink to register.
*/
- void registerSink(in IFusedLocationHardwareSink eventSink);
+ void registerSink(in IFusedLocationHardwareSink eventSink) = 0;
/**
* Unregisters a sink with the Location Hardware object.
*
* @param eventSink The sink to unregister.
*/
- void unregisterSink(in IFusedLocationHardwareSink eventSink);
+ void unregisterSink(in IFusedLocationHardwareSink eventSink) = 1;
/**
* Provides access to the batch size available in Hardware.
*
* @return The batch size the hardware supports.
*/
- int getSupportedBatchSize();
+ int getSupportedBatchSize() = 2;
/**
* Requests the Hardware to start batching locations.
@@ -56,7 +56,7 @@ interface IFusedLocationHardware {
*
* @throws RuntimeException if the request Id exists.
*/
- void startBatching(in int id, in FusedBatchOptions batchOptions);
+ void startBatching(in int id, in FusedBatchOptions batchOptions) = 3;
/**
* Requests the Hardware to stop batching for the given Id.
@@ -64,7 +64,7 @@ interface IFusedLocationHardware {
* @param id The request that needs to be stopped.
* @throws RuntimeException if the request Id is unknown.
*/
- void stopBatching(in int id);
+ void stopBatching(in int id) = 4;
/**
* Updates a batching operation in progress.
@@ -74,7 +74,7 @@ interface IFusedLocationHardware {
*
* @throws RuntimeException if the Id of the request is unknown.
*/
- void updateBatchingOptions(in int id, in FusedBatchOptions batchOptions);
+ void updateBatchingOptions(in int id, in FusedBatchOptions batchOptions) = 5;
/**
* Requests the most recent locations available in Hardware.
@@ -83,14 +83,14 @@ interface IFusedLocationHardware {
*
* @param batchSizeRequested The number of locations requested.
*/
- void requestBatchOfLocations(in int batchSizeRequested);
+ void requestBatchOfLocations(in int batchSizeRequested) = 6;
/**
* Flags if the Hardware supports injection of diagnostic data.
*
* @return True if data injection is supported, false otherwise.
*/
- boolean supportsDiagnosticDataInjection();
+ boolean supportsDiagnosticDataInjection() = 7;
/**
* Injects diagnostic data into the Hardware subsystem.
@@ -98,14 +98,14 @@ interface IFusedLocationHardware {
* @param data The data to inject.
* @throws RuntimeException if injection is not supported.
*/
- void injectDiagnosticData(in String data);
+ void injectDiagnosticData(in String data) = 8;
/**
* Flags if the Hardware supports injection of device context information.
*
* @return True if device context injection is supported, false otherwise.
*/
- boolean supportsDeviceContextInjection();
+ boolean supportsDeviceContextInjection() = 9;
/**
* Injects device context information into the Hardware subsystem.
@@ -113,5 +113,12 @@ interface IFusedLocationHardware {
* @param deviceEnabledContext The context to inject.
* @throws RuntimeException if injection is not supported.
*/
- void injectDeviceContext(in int deviceEnabledContext);
+ void injectDeviceContext(in int deviceEnabledContext) = 10;
+
+ /**
+ * Requests all batched locations currently available in Hardware
+ * and clears the buffer. Any subsequent calls will not return any
+ * of the locations returned in this call.
+ */
+ void flushBatchedLocations() = 11;
}
diff --git a/core/java/android/hardware/location/IFusedLocationHardwareSink.aidl b/core/java/android/hardware/location/IFusedLocationHardwareSink.aidl
index a11d8ab..c99cb0c 100644
--- a/core/java/android/hardware/location/IFusedLocationHardwareSink.aidl
+++ b/core/java/android/hardware/location/IFusedLocationHardwareSink.aidl
@@ -30,12 +30,24 @@ interface IFusedLocationHardwareSink {
*
* @param locations The batch of location information available.
*/
- void onLocationAvailable(in Location[] locations);
+ void onLocationAvailable(in Location[] locations) = 0;
/**
* Event generated from FLP HAL to provide diagnostic data to the platform.
*
* @param data The diagnostic data provided by FLP HAL.
*/
- void onDiagnosticDataAvailable(in String data);
+ void onDiagnosticDataAvailable(in String data) = 1;
+
+ /**
+ * Event generated from FLP HAL to provide a mask of supported
+ * capabilities. Should be called immediatly after init.
+ */
+ void onCapabilities(int capabilities) = 2;
+
+ /**
+ * Event generated from FLP HAL when the status of location batching
+ * changes (location is successful/unsuccessful).
+ */
+ void onStatusChanged(int status) = 3;
} \ No newline at end of file
diff --git a/core/java/android/net/IpPrefix.java b/core/java/android/net/IpPrefix.java
index b268986..6b4f2d5 100644
--- a/core/java/android/net/IpPrefix.java
+++ b/core/java/android/net/IpPrefix.java
@@ -170,6 +170,21 @@ public final class IpPrefix implements Parcelable {
}
/**
+ * Determines whether the prefix contains the specified address.
+ *
+ * @param address An {@link InetAddress} to test.
+ * @return {@code true} if the prefix covers the given address.
+ */
+ public boolean contains(InetAddress address) {
+ byte[] addrBytes = (address == null) ? null : address.getAddress();
+ if (addrBytes == null || addrBytes.length != this.address.length) {
+ return false;
+ }
+ NetworkUtils.maskRawAddress(addrBytes, prefixLength);
+ return Arrays.equals(this.address, addrBytes);
+ }
+
+ /**
* Returns a string representation of this {@code IpPrefix}.
*
* @return a string such as {@code "192.0.2.0/24"} or {@code "2001:db8:1:2::/64"}.
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
index cfd20a0..90a2460 100644
--- a/core/java/android/net/RouteInfo.java
+++ b/core/java/android/net/RouteInfo.java
@@ -367,13 +367,7 @@ public final class RouteInfo implements Parcelable {
* @return {@code true} if the destination and prefix length cover the given address.
*/
public boolean matches(InetAddress destination) {
- if (destination == null) return false;
-
- // match the route destination and destination with prefix length
- InetAddress dstNet = NetworkUtils.getNetworkPart(destination,
- mDestination.getPrefixLength());
-
- return mDestination.getAddress().equals(dstNet);
+ return mDestination.contains(destination);
}
/**
diff --git a/core/java/android/os/IHardwareService.aidl b/core/java/android/os/IHardwareService.aidl
deleted file mode 100644
index 38abfc0..0000000
--- a/core/java/android/os/IHardwareService.aidl
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- * Copyright (c) 2007, 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.os;
-
-/** {@hide} */
-interface IHardwareService
-{
- // obsolete flashlight support
- boolean getFlashlightEnabled();
- void setFlashlightEnabled(boolean on);
-}
-
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index afd9950..b9e307f 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1327,9 +1327,9 @@ public class UserManager {
* calling user.
* @return creation time in milliseconds since Epoch time.
*/
- public long getUserCreationTime(int userHandle) {
+ public long getUserCreationTime(UserHandle userHandle) {
try {
- return mService.getUserCreationTime(userHandle);
+ return mService.getUserCreationTime(userHandle.getIdentifier());
} catch (RemoteException re) {
Log.w(TAG, "Could not get user creation time", re);
return 0;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 3087e1d..9edf6ad 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -889,6 +889,15 @@ public final class Settings {
= "android.settings.ZEN_MODE_SCHEDULE_RULE_SETTINGS";
/**
+ * Activity Action: Show Zen Mode external rule configuration settings.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_ZEN_MODE_EXTERNAL_RULE_SETTINGS
+ = "android.settings.ZEN_MODE_EXTERNAL_RULE_SETTINGS";
+
+ /**
* Activity Action: Show the regulatory information screen for the device.
* <p>
* In some cases, a matching Activity may not exist, so ensure you safeguard
diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java
index 4712f97..879f26c 100644
--- a/core/java/android/provider/VoicemailContract.java
+++ b/core/java/android/provider/VoicemailContract.java
@@ -19,7 +19,6 @@ package android.provider;
import android.Manifest;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SystemApi;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
@@ -258,7 +257,6 @@ public class VoicemailContract {
*
* @hide
*/
- @SystemApi
public static Uri insert(Context context, Voicemail voicemail) {
ContentResolver contentResolver = context.getContentResolver();
ContentValues contentValues = getContentValues(voicemail);
@@ -274,7 +272,6 @@ public class VoicemailContract {
*
* @hide
*/
- @SystemApi
public static int insert(Context context, List<Voicemail> voicemails) {
ContentResolver contentResolver = context.getContentResolver();
int count = voicemails.size();
@@ -293,7 +290,6 @@ public class VoicemailContract {
*
* @hide
*/
- @SystemApi
public static int deleteAll(Context context) {
return context.getContentResolver().delete(
buildSourceUri(context.getPackageName()), "", new String[0]);
@@ -452,7 +448,6 @@ public class VoicemailContract {
*
* @hide
*/
- @SystemApi
public static void setStatus(Context context, PhoneAccountHandle accountHandle,
int configurationState, int dataChannelState, int notificationChannelState) {
ContentResolver contentResolver = context.getContentResolver();
diff --git a/core/java/android/security/keymaster/KeyCharacteristics.java b/core/java/android/security/keymaster/KeyCharacteristics.java
index 0f1d422..b3a3aad 100644
--- a/core/java/android/security/keymaster/KeyCharacteristics.java
+++ b/core/java/android/security/keymaster/KeyCharacteristics.java
@@ -19,6 +19,10 @@ package android.security.keymaster;
import android.os.Parcel;
import android.os.Parcelable;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
/**
* @hide
*/
@@ -28,10 +32,12 @@ public class KeyCharacteristics implements Parcelable {
public static final Parcelable.Creator<KeyCharacteristics> CREATOR = new
Parcelable.Creator<KeyCharacteristics>() {
+ @Override
public KeyCharacteristics createFromParcel(Parcel in) {
return new KeyCharacteristics(in);
}
+ @Override
public KeyCharacteristics[] newArray(int length) {
return new KeyCharacteristics[length];
}
@@ -48,6 +54,7 @@ public class KeyCharacteristics implements Parcelable {
return 0;
}
+ @Override
public void writeToParcel(Parcel out, int flags) {
swEnforced.writeToParcel(out, flags);
hwEnforced.writeToParcel(out, flags);
@@ -57,5 +64,53 @@ public class KeyCharacteristics implements Parcelable {
swEnforced = KeymasterArguments.CREATOR.createFromParcel(in);
hwEnforced = KeymasterArguments.CREATOR.createFromParcel(in);
}
+
+ public Integer getInteger(int tag) {
+ if (hwEnforced.containsTag(tag)) {
+ return hwEnforced.getInt(tag, -1);
+ } else if (swEnforced.containsTag(tag)) {
+ return swEnforced.getInt(tag, -1);
+ } else {
+ return null;
+ }
+ }
+
+ public int getInt(int tag, int defaultValue) {
+ Integer result = getInteger(tag);
+ return (result != null) ? result : defaultValue;
+ }
+
+ public List<Integer> getInts(int tag) {
+ List<Integer> result = new ArrayList<Integer>();
+ result.addAll(hwEnforced.getInts(tag));
+ result.addAll(swEnforced.getInts(tag));
+ return result;
+ }
+
+ public Date getDate(int tag) {
+ Date result = hwEnforced.getDate(tag, null);
+ if (result == null) {
+ result = swEnforced.getDate(tag, null);
+ }
+ return result;
+ }
+
+ public Date getDate(int tag, Date defaultValue) {
+ if (hwEnforced.containsTag(tag)) {
+ return hwEnforced.getDate(tag, null);
+ } else if (hwEnforced.containsTag(tag)) {
+ return swEnforced.getDate(tag, null);
+ } else {
+ return defaultValue;
+ }
+ }
+
+ public boolean getBoolean(KeyCharacteristics keyCharacteristics, int tag) {
+ if (keyCharacteristics.hwEnforced.containsTag(tag)) {
+ return keyCharacteristics.hwEnforced.getBoolean(tag, false);
+ } else {
+ return keyCharacteristics.swEnforced.getBoolean(tag, false);
+ }
+ }
}
diff --git a/core/java/android/security/keymaster/KeymasterArguments.java b/core/java/android/security/keymaster/KeymasterArguments.java
index b5fd4bd..8ed288c 100644
--- a/core/java/android/security/keymaster/KeymasterArguments.java
+++ b/core/java/android/security/keymaster/KeymasterArguments.java
@@ -34,9 +34,12 @@ public class KeymasterArguments implements Parcelable {
public static final Parcelable.Creator<KeymasterArguments> CREATOR = new
Parcelable.Creator<KeymasterArguments>() {
+ @Override
public KeymasterArguments createFromParcel(Parcel in) {
return new KeymasterArguments(in);
}
+
+ @Override
public KeymasterArguments[] newArray(int size) {
return new KeymasterArguments[size];
}
@@ -54,6 +57,12 @@ public class KeymasterArguments implements Parcelable {
mArguments.add(new KeymasterIntArgument(tag, value));
}
+ public void addInts(int tag, int... values) {
+ for (int value : values) {
+ addInt(tag, value);
+ }
+ }
+
public void addBoolean(int tag) {
mArguments.add(new KeymasterBooleanArgument(tag));
}
diff --git a/core/java/android/service/chooser/ChooserTarget.java b/core/java/android/service/chooser/ChooserTarget.java
index 7fd1d10..d21cc3c 100644
--- a/core/java/android/service/chooser/ChooserTarget.java
+++ b/core/java/android/service/chooser/ChooserTarget.java
@@ -17,6 +17,7 @@
package android.service.chooser;
+import android.app.Activity;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
@@ -24,8 +25,10 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
import android.graphics.Bitmap;
+import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.UserHandle;
import android.util.Log;
/**
@@ -55,6 +58,12 @@ 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;
@@ -135,6 +144,17 @@ public final class ChooserTarget implements Parcelable {
mIntentSender = intentSender;
}
+ 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) {
@@ -144,6 +164,9 @@ public final class ChooserTarget implements Parcelable {
}
mScore = in.readFloat();
mIntentSender = IntentSender.readIntentSenderOrNullFromParcel(in);
+ if (in.readInt() != 0) {
+ mIntent = Intent.CREATOR.createFromParcel(in);
+ }
}
/**
@@ -179,6 +202,7 @@ public final class ChooserTarget implements Parcelable {
/**
* Returns the raw IntentSender supplied by the ChooserTarget's creator.
+ * This may be null if the creator specified a regular Intent instead.
*
* <p>To fill in and send the intent, see {@link #sendIntent(Context, Intent)}.</p>
*
@@ -189,6 +213,18 @@ 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
@@ -200,18 +236,109 @@ public final class ChooserTarget implements Parcelable {
fillInIntent.migrateExtraStreamToClipData();
fillInIntent.prepareToLeaveProcess();
}
- try {
- mIntentSender.sendIntent(context, 0, fillInIntent, null, null);
- return true;
- } catch (IntentSender.SendIntentException e) {
- Log.e(TAG, "sendIntent " + this + " failed", e);
+ 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.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");
return false;
}
}
@Override
public String toString() {
- return "ChooserTarget{" + mIntentSender.getCreatorPackage() + "'" + mTitle
+ return "ChooserTarget{"
+ + (mIntentSender != null ? mIntentSender.getCreatorPackage() : mIntent)
+ + ", "
+ + "'" + mTitle
+ "', " + mScore + "}";
}
diff --git a/core/java/android/service/chooser/ChooserTargetService.java b/core/java/android/service/chooser/ChooserTargetService.java
index 9188806..699bd0a 100644
--- a/core/java/android/service/chooser/ChooserTargetService.java
+++ b/core/java/android/service/chooser/ChooserTargetService.java
@@ -24,6 +24,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.os.RemoteException;
+import android.util.Log;
import java.util.List;
@@ -77,9 +78,26 @@ public abstract class ChooserTargetService extends Service {
private final String TAG = ChooserTargetService.class.getSimpleName()
+ '[' + getClass().getSimpleName() + ']';
+ private static final boolean DEBUG = false;
+
+ /**
+ * The Intent action that a ChooserTargetService must respond to
+ */
@SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
public static final String SERVICE_INTERFACE = "android.service.chooser.ChooserTargetService";
+ /**
+ * The name of the <code>meta-data</code> element that must be present on an
+ * <code>activity</code> element in a manifest to link it to a ChooserTargetService
+ */
+ public static final String META_DATA_NAME = "android.service.chooser.chooser_target_service";
+
+ /**
+ * The permission that a ChooserTargetService must require in order to bind to it.
+ * If this permission is not enforced the system will skip that ChooserTargetService.
+ */
+ public static final String BIND_PERMISSION = "android.permission.BIND_CHOOSER_TARGET_SERVICE";
+
private IChooserTargetServiceWrapper mWrapper = null;
/**
@@ -105,7 +123,9 @@ public abstract class ChooserTargetService extends Service {
@Override
public IBinder onBind(Intent intent) {
+ if (DEBUG) Log.d(TAG, "onBind " + intent);
if (!SERVICE_INTERFACE.equals(intent.getAction())) {
+ if (DEBUG) Log.d(TAG, "bad intent action " + intent.getAction() + "; returning null");
return null;
}
@@ -121,9 +141,14 @@ public abstract class ChooserTargetService extends Service {
IntentFilter matchedFilter, IChooserTargetResult result) throws RemoteException {
List<ChooserTarget> targets = null;
try {
+ if (DEBUG) {
+ Log.d(TAG, "getChooserTargets calling onGetChooserTargets; "
+ + targetComponentName + " filter: " + matchedFilter);
+ }
targets = onGetChooserTargets(targetComponentName, matchedFilter);
} finally {
result.sendResult(targets);
+ if (DEBUG) Log.d(TAG, "Sent results");
}
}
}
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 822bfcc..29aaf30 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -41,6 +41,7 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.PhoneWindow;
+import android.view.SearchEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
@@ -332,6 +333,12 @@ public class DreamService extends Service implements Window.Callback {
/** {@inheritDoc} */
@Override
+ public boolean onSearchRequested(SearchEvent event) {
+ return onSearchRequested();
+ }
+
+ /** {@inheritDoc} */
+ @Override
public boolean onSearchRequested() {
return false;
}
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 56eb510..1ed4779 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -654,8 +654,7 @@ public class ZenModeConfig implements Parcelable {
}
String summary = "";
for (ZenRule automaticRule : config.automaticRules.values()) {
- if (automaticRule.enabled && !automaticRule.snoozing
- && automaticRule.isTrueOrUnknown()) {
+ if (automaticRule.isAutomaticActive()) {
if (summary.isEmpty()) {
summary = automaticRule.name;
} else {
@@ -745,9 +744,13 @@ public class ZenModeConfig implements Parcelable {
component);
}
+ public boolean isAutomaticActive() {
+ return enabled && !snoozing && component != null && isTrueOrUnknown();
+ }
+
public boolean isTrueOrUnknown() {
- return condition == null || condition.state == Condition.STATE_TRUE
- || condition.state == Condition.STATE_UNKNOWN;
+ return condition != null && (condition.state == Condition.STATE_TRUE
+ || condition.state == Condition.STATE_UNKNOWN);
}
public static final Parcelable.Creator<ZenRule> CREATOR
diff --git a/core/java/android/view/PhoneWindow.java b/core/java/android/view/PhoneWindow.java
index 38f4d1c..5af2832 100644
--- a/core/java/android/view/PhoneWindow.java
+++ b/core/java/android/view/PhoneWindow.java
@@ -1916,7 +1916,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
break;
}
if (event.isTracking() && !event.isCanceled()) {
- launchDefaultSearch();
+ launchDefaultSearch(event);
}
return true;
}
@@ -4245,14 +4245,19 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
*
* @return true if search window opened
*/
- private boolean launchDefaultSearch() {
+ private boolean launchDefaultSearch(KeyEvent event) {
boolean result;
final Callback cb = getCallback();
if (cb == null || isDestroyed()) {
result = false;
} else {
sendCloseSystemWindows("search");
- result = cb.onSearchRequested();
+ int deviceId = event.getDeviceId();
+ SearchEvent searchEvent = null;
+ if (deviceId != 0) {
+ searchEvent = new SearchEvent(InputDevice.getDevice(deviceId));
+ }
+ result = cb.onSearchRequested(searchEvent);
}
if (!result && (getContext().getResources().getConfiguration().uiMode
& Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) {
diff --git a/core/java/android/view/SearchEvent.java b/core/java/android/view/SearchEvent.java
new file mode 100644
index 0000000..ef51e7d
--- /dev/null
+++ b/core/java/android/view/SearchEvent.java
@@ -0,0 +1,40 @@
+/*
+ * 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.view;
+
+import android.view.InputDevice;
+
+/**
+ * Class that contains information about an event that triggers a search.
+ */
+public class SearchEvent {
+
+ private InputDevice mInputDevice;
+
+ /** @hide */
+ public SearchEvent(InputDevice inputDevice) {
+ mInputDevice = inputDevice;
+ }
+
+ /**
+ * Returns the {@link InputDevice} that triggered the search.
+ * @return InputDevice the InputDevice that triggered the search.
+ */
+ public InputDevice getInputDevice() {
+ return mInputDevice;
+ }
+}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 60d2ceb..3fa8c81 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -15087,7 +15087,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
* case of an active Animation being run on the view.
*/
- private boolean drawAnimation(ViewGroup parent, long drawingTime,
+ private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
Animation a, boolean scalingRequired) {
Transformation invalidationTransform;
final int flags = parent.mGroupFlags;
@@ -15204,23 +15204,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
Transformation transformToApply = null;
boolean concatMatrix = false;
- boolean scalingRequired = false;
- boolean caching;
+ boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
int layerType = getLayerType();
-
final boolean hardwareAccelerated = canvas.isHardwareAccelerated();
- if ((flags & ViewGroup.FLAG_CHILDREN_DRAWN_WITH_CACHE) != 0 ||
- (flags & ViewGroup.FLAG_ALWAYS_DRAWN_WITH_CACHE) != 0) {
- caching = true;
- // Auto-scaled apps are not hw-accelerated, no need to set scaling flag on DisplayList
- if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired;
- } else {
- caching = (layerType != LAYER_TYPE_NONE) || hardwareAccelerated;
- }
final Animation a = getAnimation();
if (a != null) {
- more = drawAnimation(parent, drawingTime, a, scalingRequired);
+ more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
concatMatrix = a.willChangeTransformationMatrix();
if (concatMatrix) {
mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
@@ -15270,34 +15260,32 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
RenderNode renderNode = null;
Bitmap cache = null;
boolean hasDisplayList = false;
- if (caching) {
- if (!hardwareAccelerated) {
- if (layerType != LAYER_TYPE_NONE) {
- layerType = LAYER_TYPE_SOFTWARE;
- buildDrawingCache(true);
- }
- cache = getDrawingCache(true);
- } else {
- switch (layerType) {
- case LAYER_TYPE_SOFTWARE:
- if (usingRenderNodeProperties) {
- hasDisplayList = canHaveDisplayList();
- } else {
- buildDrawingCache(true);
- cache = getDrawingCache(true);
- }
- break;
- case LAYER_TYPE_HARDWARE:
- if (usingRenderNodeProperties) {
- hasDisplayList = canHaveDisplayList();
- }
- break;
- case LAYER_TYPE_NONE:
- // Delay getting the display list until animation-driven alpha values are
- // set up and possibly passed on to the view
+ if (!hardwareAccelerated) {
+ if (layerType != LAYER_TYPE_NONE) {
+ layerType = LAYER_TYPE_SOFTWARE;
+ buildDrawingCache(true);
+ }
+ cache = getDrawingCache(true);
+ } else {
+ switch (layerType) {
+ case LAYER_TYPE_SOFTWARE:
+ if (usingRenderNodeProperties) {
hasDisplayList = canHaveDisplayList();
- break;
- }
+ } else {
+ buildDrawingCache(true);
+ cache = getDrawingCache(true);
+ }
+ break;
+ case LAYER_TYPE_HARDWARE:
+ if (usingRenderNodeProperties) {
+ hasDisplayList = canHaveDisplayList();
+ }
+ break;
+ case LAYER_TYPE_NONE:
+ // Delay getting the display list until animation-driven alpha values are
+ // set up and possibly passed on to the view
+ hasDisplayList = canHaveDisplayList();
+ break;
}
}
usingRenderNodeProperties &= hasDisplayList;
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 8d06ce2..98b895d 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -245,8 +245,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
// to clip it, even if FLAG_CLIP_TO_PADDING is set
private static final int FLAG_PADDING_NOT_NULL = 0x20;
- // When set, this ViewGroup caches its children in a Bitmap before starting a layout animation
- // Set by default
+ /** @deprecated - functionality removed */
private static final int FLAG_ANIMATION_CACHE = 0x40;
// When set, this ViewGroup converts calls to invalidate(Rect) to invalidate() during a
@@ -292,16 +291,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
*/
private static final int FLAG_ADD_STATES_FROM_CHILDREN = 0x2000;
- /**
- * When set, this ViewGroup tries to always draw its children using their drawing cache.
- */
- static final int FLAG_ALWAYS_DRAWN_WITH_CACHE = 0x4000;
+ /** @deprecated functionality removed */
+ private static final int FLAG_ALWAYS_DRAWN_WITH_CACHE = 0x4000;
- /**
- * When set, and if FLAG_ALWAYS_DRAWN_WITH_CACHE is not set, this ViewGroup will try to
- * draw its children with their drawing cache.
- */
- static final int FLAG_CHILDREN_DRAWN_WITH_CACHE = 0x8000;
+ /** @deprecated functionality removed */
+ private static final int FLAG_CHILDREN_DRAWN_WITH_CACHE = 0x8000;
/**
* When set, this group will go through its list of children to notify them of
@@ -584,8 +578,6 @@ 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;
@@ -3088,44 +3080,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
@Override
- protected void onAnimationStart() {
- super.onAnimationStart();
-
- // When this ViewGroup's animation starts, build the cache for the children
- if ((mGroupFlags & FLAG_ANIMATION_CACHE) == FLAG_ANIMATION_CACHE) {
- final int count = mChildrenCount;
- final View[] children = mChildren;
- final boolean buildCache = !isHardwareAccelerated();
-
- for (int i = 0; i < count; i++) {
- final View child = children[i];
- if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
- child.setDrawingCacheEnabled(true);
- if (buildCache) {
- child.buildDrawingCache(true);
- }
- }
- }
-
- mGroupFlags |= FLAG_CHILDREN_DRAWN_WITH_CACHE;
- }
- }
-
- @Override
- protected void onAnimationEnd() {
- super.onAnimationEnd();
-
- // When this ViewGroup's animation ends, destroy the cache of the children
- if ((mGroupFlags & FLAG_ANIMATION_CACHE) == FLAG_ANIMATION_CACHE) {
- mGroupFlags &= ~FLAG_CHILDREN_DRAWN_WITH_CACHE;
-
- if ((mPersistentDrawingCache & PERSISTENT_ANIMATION_CACHE) == 0) {
- setChildrenDrawingCacheEnabled(false);
- }
- }
- }
-
- @Override
Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
int count = mChildrenCount;
int[] visibilities = null;
@@ -3295,8 +3249,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
int flags = mGroupFlags;
if ((flags & FLAG_RUN_ANIMATION) != 0 && canAnimate()) {
- final boolean cache = (mGroupFlags & FLAG_ANIMATION_CACHE) == FLAG_ANIMATION_CACHE;
-
final boolean buildCache = !isHardwareAccelerated();
for (int i = 0; i < childrenCount; i++) {
final View child = children[i];
@@ -3304,12 +3256,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
final LayoutParams params = child.getLayoutParams();
attachLayoutAnimationParameters(child, params, i, childrenCount);
bindLayoutAnimation(child);
- if (cache) {
- child.setDrawingCacheEnabled(true);
- if (buildCache) {
- child.buildDrawingCache(true);
- }
- }
}
}
@@ -3323,10 +3269,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
mGroupFlags &= ~FLAG_RUN_ANIMATION;
mGroupFlags &= ~FLAG_ANIMATION_DONE;
- if (cache) {
- mGroupFlags |= FLAG_CHILDREN_DRAWN_WITH_CACHE;
- }
-
if (mAnimationListener != null) {
mAnimationListener.onAnimationStart(controller.getAnimation());
}
@@ -3504,13 +3446,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
post(end);
}
- if ((mGroupFlags & FLAG_ANIMATION_CACHE) == FLAG_ANIMATION_CACHE) {
- mGroupFlags &= ~FLAG_CHILDREN_DRAWN_WITH_CACHE;
- if ((mPersistentDrawingCache & PERSISTENT_ANIMATION_CACHE) == 0) {
- setChildrenDrawingCacheEnabled(false);
- }
- }
-
invalidate(true);
}
@@ -5278,8 +5213,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
*
* @see #setAnimationCacheEnabled(boolean)
* @see View#setDrawingCacheEnabled(boolean)
+ *
+ * @deprecated As of {@link android.os.Build.VERSION_CODES#MNC}, this property is ignored.
+ * Caching behavior of children may be controlled through {@link View#setLayerType(int, Paint)}.
*/
- @ViewDebug.ExportedProperty
public boolean isAnimationCacheEnabled() {
return (mGroupFlags & FLAG_ANIMATION_CACHE) == FLAG_ANIMATION_CACHE;
}
@@ -5294,6 +5231,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
*
* @see #isAnimationCacheEnabled()
* @see View#setDrawingCacheEnabled(boolean)
+ *
+ * @deprecated As of {@link android.os.Build.VERSION_CODES#MNC}, this property is ignored.
+ * Caching behavior of children may be controlled through {@link View#setLayerType(int, Paint)}.
*/
public void setAnimationCacheEnabled(boolean enabled) {
setBooleanFlag(FLAG_ANIMATION_CACHE, enabled);
@@ -5308,8 +5248,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* @see #setAlwaysDrawnWithCacheEnabled(boolean)
* @see #setChildrenDrawnWithCacheEnabled(boolean)
* @see View#setDrawingCacheEnabled(boolean)
+ *
+ * @deprecated As of {@link android.os.Build.VERSION_CODES#MNC}, this property is ignored.
+ * Child views may no longer have their caching behavior disabled by parents.
*/
- @ViewDebug.ExportedProperty(category = "drawing")
public boolean isAlwaysDrawnWithCacheEnabled() {
return (mGroupFlags & FLAG_ALWAYS_DRAWN_WITH_CACHE) == FLAG_ALWAYS_DRAWN_WITH_CACHE;
}
@@ -5330,6 +5272,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* @see #setChildrenDrawnWithCacheEnabled(boolean)
* @see View#setDrawingCacheEnabled(boolean)
* @see View#setDrawingCacheQuality(int)
+ *
+ * @deprecated As of {@link android.os.Build.VERSION_CODES#MNC}, this property is ignored.
+ * Child views may no longer have their caching behavior disabled by parents.
*/
public void setAlwaysDrawnWithCacheEnabled(boolean always) {
setBooleanFlag(FLAG_ALWAYS_DRAWN_WITH_CACHE, always);
@@ -5343,8 +5288,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
*
* @see #setAlwaysDrawnWithCacheEnabled(boolean)
* @see #setChildrenDrawnWithCacheEnabled(boolean)
+ *
+ * @deprecated As of {@link android.os.Build.VERSION_CODES#MNC}, this property is ignored.
+ * Child views may no longer be forced to cache their rendering state by their parents.
+ * Use {@link View#setLayerType(int, Paint)} on individual Views instead.
*/
- @ViewDebug.ExportedProperty(category = "drawing")
protected boolean isChildrenDrawnWithCacheEnabled() {
return (mGroupFlags & FLAG_CHILDREN_DRAWN_WITH_CACHE) == FLAG_CHILDREN_DRAWN_WITH_CACHE;
}
@@ -5361,6 +5309,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
*
* @see #setAlwaysDrawnWithCacheEnabled(boolean)
* @see #isChildrenDrawnWithCacheEnabled()
+ *
+ * @deprecated As of {@link android.os.Build.VERSION_CODES#MNC}, this property is ignored.
+ * Child views may no longer be forced to cache their rendering state by their parents.
+ * Use {@link View#setLayerType(int, Paint)} on individual Views instead.
*/
protected void setChildrenDrawnWithCacheEnabled(boolean enabled) {
setBooleanFlag(FLAG_CHILDREN_DRAWN_WITH_CACHE, enabled);
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 36f047e..9d0d5ff 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -414,6 +414,15 @@ public abstract class Window {
public boolean onSearchRequested();
/**
+ * Called when the user signals the desire to start a search.
+ *
+ * @param searchEvent A {@link SearchEvent} describing the signal to
+ * start a search.
+ * @return true if search launched, false if activity refuses (blocks)
+ */
+ public boolean onSearchRequested(SearchEvent searchEvent);
+
+ /**
* Called when an action mode is being started for this window. Gives the
* callback an opportunity to handle the action mode in its own unique and
* beautiful way. If this method returns null the system can choose a way
diff --git a/core/java/android/view/WindowCallbackWrapper.java b/core/java/android/view/WindowCallbackWrapper.java
index 979ee95..8ce1f8c 100644
--- a/core/java/android/view/WindowCallbackWrapper.java
+++ b/core/java/android/view/WindowCallbackWrapper.java
@@ -122,6 +122,11 @@ public class WindowCallbackWrapper implements Window.Callback {
}
@Override
+ public boolean onSearchRequested(SearchEvent searchEvent) {
+ return mWrapped.onSearchRequested(searchEvent);
+ }
+
+ @Override
public boolean onSearchRequested() {
return mWrapped.onSearchRequested();
}
diff --git a/core/java/android/widget/ActionMenuPresenter.java b/core/java/android/widget/ActionMenuPresenter.java
index f951dc2..e0b0e1f 100644
--- a/core/java/android/widget/ActionMenuPresenter.java
+++ b/core/java/android/widget/ActionMenuPresenter.java
@@ -40,7 +40,6 @@ import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.ListPopupWindow.ForwardingListener;
-import com.android.internal.transition.ActionBarTransition;
import com.android.internal.view.ActionBarPolicy;
import com.android.internal.view.menu.ActionMenuItemView;
import com.android.internal.view.menu.BaseMenuPresenter;
@@ -99,7 +98,30 @@ public class ActionMenuPresenter extends BaseMenuPresenter
// The list of currently running animations on menu items.
private List<ItemAnimationInfo> mRunningItemAnimations = new ArrayList<ItemAnimationInfo>();
+ private ViewTreeObserver.OnPreDrawListener mItemAnimationPreDrawListener =
+ new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ computeMenuItemAnimationInfo(false);
+ ((View) mMenuView).getViewTreeObserver().removeOnPreDrawListener(this);
+ runItemAnimations();
+ return true;
+ }
+ };
+ private View.OnAttachStateChangeListener mAttachStateChangeListener =
+ new View.OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ }
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ ((View) mMenuView).getViewTreeObserver().removeOnPreDrawListener(
+ mItemAnimationPreDrawListener);
+ mPreLayoutItems.clear();
+ mPostLayoutItems.clear();
+ }
+ };
public ActionMenuPresenter(Context context) {
@@ -177,8 +199,15 @@ public class ActionMenuPresenter extends BaseMenuPresenter
@Override
public MenuView getMenuView(ViewGroup root) {
+ MenuView oldMenuView = mMenuView;
MenuView result = super.getMenuView(root);
- ((ActionMenuView) result).setPresenter(this);
+ if (oldMenuView != result) {
+ ((ActionMenuView) result).setPresenter(this);
+ if (oldMenuView != null) {
+ ((View) oldMenuView).removeOnAttachStateChangeListener(mAttachStateChangeListener);
+ }
+ ((View) result).addOnAttachStateChangeListener(mAttachStateChangeListener);
+ }
return result;
}
@@ -226,11 +255,11 @@ public class ActionMenuPresenter extends BaseMenuPresenter
* into the MenuItemLayoutInfo structure to store the appropriate position values.
*/
private void computeMenuItemAnimationInfo(boolean preLayout) {
- final ViewGroup menuViewParent = (ViewGroup) mMenuView;
- final int count = menuViewParent.getChildCount();
+ final ViewGroup menuView = (ViewGroup) mMenuView;
+ final int count = menuView.getChildCount();
SparseArray items = preLayout ? mPreLayoutItems : mPostLayoutItems;
for (int i = 0; i < count; ++i) {
- View child = menuViewParent.getChildAt(i);
+ View child = menuView.getChildAt(i);
final int id = child.getId();
if (id > 0 && child.getWidth() != 0 && child.getHeight() != 0) {
MenuItemLayoutInfo info = new MenuItemLayoutInfo(child, preLayout);
@@ -377,28 +406,16 @@ public class ActionMenuPresenter extends BaseMenuPresenter
* which is then fed into runItemAnimations()
*/
private void setupItemAnimations() {
- final ViewGroup menuViewParent = (ViewGroup) mMenuView;
computeMenuItemAnimationInfo(true);
- final ViewTreeObserver observer = menuViewParent.getViewTreeObserver();
- if (observer != null) {
- observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
- @Override
- public boolean onPreDraw() {
- computeMenuItemAnimationInfo(false);
- observer.removeOnPreDrawListener(this);
- runItemAnimations();
- return true;
- }
- });
- }
+ ((View) mMenuView).getViewTreeObserver().
+ addOnPreDrawListener(mItemAnimationPreDrawListener);
}
@Override
public void updateMenuView(boolean cleared) {
final ViewGroup menuViewParent = (ViewGroup) ((View) mMenuView).getParent();
if (menuViewParent != null) {
-// setupItemAnimations();
- ActionBarTransition.beginDelayedTransition(menuViewParent);
+ setupItemAnimations();
}
super.updateMenuView(cleared);
@@ -736,8 +753,14 @@ public class ActionMenuPresenter extends BaseMenuPresenter
}
public void setMenuView(ActionMenuView menuView) {
- mMenuView = menuView;
- menuView.initialize(mMenu);
+ if (menuView != mMenuView) {
+ if (mMenuView != null) {
+ ((View) mMenuView).removeOnAttachStateChangeListener(mAttachStateChangeListener);
+ }
+ mMenuView = menuView;
+ menuView.initialize(mMenu);
+ menuView.addOnAttachStateChangeListener(mAttachStateChangeListener);
+ }
}
public void setOverflowTintList(ColorStateList tint) {
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index a157087..06a5bd2 100755
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -534,22 +534,23 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate {
@Override
public void onRestoreInstanceState(Parcelable state) {
- SavedState ss = (SavedState) state;
+ final SavedState ss = (SavedState) state;
// TODO: Move instance state into DayPickerView, YearPickerView.
mCurrentDate.set(ss.getSelectedYear(), ss.getSelectedMonth(), ss.getSelectedDay());
- mCurrentView = ss.getCurrentView();
mMinDate.setTimeInMillis(ss.getMinDate());
mMaxDate.setTimeInMillis(ss.getMaxDate());
onCurrentDateChanged(false);
- setCurrentView(mCurrentView);
+
+ final int currentView = ss.getCurrentView();
+ setCurrentView(currentView);
final int listPosition = ss.getListPosition();
if (listPosition != -1) {
- if (mCurrentView == VIEW_MONTH_DAY) {
+ if (currentView == VIEW_MONTH_DAY) {
mDayPickerView.setCurrentItem(listPosition);
- } else if (mCurrentView == VIEW_YEAR) {
+ } else if (currentView == VIEW_YEAR) {
final int listPositionOffset = ss.getListPositionOffset();
mYearPickerView.setSelectionFromTop(listPosition, listPositionOffset);
}
@@ -601,7 +602,6 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate {
* Class for managing state storing/restoring.
*/
private static class SavedState extends View.BaseSavedState {
-
private final int mSelectedYear;
private final int mSelectedMonth;
private final int mSelectedDay;
diff --git a/core/java/android/widget/DayPickerView.java b/core/java/android/widget/DayPickerView.java
index ec2528f..0e0b2d3 100644
--- a/core/java/android/widget/DayPickerView.java
+++ b/core/java/android/widget/DayPickerView.java
@@ -22,9 +22,12 @@ import com.android.internal.R;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.MathUtils;
+import android.view.View;
+import java.util.ArrayList;
import java.util.Calendar;
import java.util.Locale;
@@ -41,6 +44,8 @@ class DayPickerView extends ViewPager {
private final Calendar mMinDate = Calendar.getInstance();
private final Calendar mMaxDate = Calendar.getInstance();
+ private final ArrayList<View> mMatchParentChildren = new ArrayList<>(1);
+
private final DayPickerAdapter mAdapter;
/** Temporary calendar used for date calculations. */
@@ -140,6 +145,93 @@ class DayPickerView extends ViewPager {
});
}
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ populate();
+
+ // Everything below is mostly copied from FrameLayout.
+ int count = getChildCount();
+
+ final boolean measureMatchParentChildren =
+ MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY ||
+ MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY;
+
+ int maxHeight = 0;
+ int maxWidth = 0;
+ int childState = 0;
+
+ for (int i = 0; i < count; i++) {
+ final View child = getChildAt(i);
+ if (child.getVisibility() != GONE) {
+ measureChild(child, widthMeasureSpec, heightMeasureSpec);
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ maxWidth = Math.max(maxWidth, child.getMeasuredWidth());
+ maxHeight = Math.max(maxHeight, child.getMeasuredHeight());
+ childState = combineMeasuredStates(childState, child.getMeasuredState());
+ if (measureMatchParentChildren) {
+ if (lp.width == LayoutParams.MATCH_PARENT ||
+ lp.height == LayoutParams.MATCH_PARENT) {
+ mMatchParentChildren.add(child);
+ }
+ }
+ }
+ }
+
+ // Account for padding too
+ maxWidth += getPaddingLeft() + getPaddingRight();
+ maxHeight += getPaddingTop() + getPaddingBottom();
+
+ // Check against our minimum height and width
+ maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
+ maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
+
+ // Check against our foreground's minimum height and width
+ final Drawable drawable = getForeground();
+ if (drawable != null) {
+ maxHeight = Math.max(maxHeight, drawable.getMinimumHeight());
+ maxWidth = Math.max(maxWidth, drawable.getMinimumWidth());
+ }
+
+ setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
+ resolveSizeAndState(maxHeight, heightMeasureSpec,
+ childState << MEASURED_HEIGHT_STATE_SHIFT));
+
+ count = mMatchParentChildren.size();
+ if (count > 1) {
+ for (int i = 0; i < count; i++) {
+ final View child = mMatchParentChildren.get(i);
+
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ final int childWidthMeasureSpec;
+ final int childHeightMeasureSpec;
+
+ if (lp.width == LayoutParams.MATCH_PARENT) {
+ childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
+ getMeasuredWidth() - getPaddingLeft() - getPaddingRight(),
+ MeasureSpec.EXACTLY);
+ } else {
+ childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
+ getPaddingLeft() + getPaddingRight(),
+ lp.width);
+ }
+
+ if (lp.height == LayoutParams.MATCH_PARENT) {
+ childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
+ getMeasuredHeight() - getPaddingTop() - getPaddingBottom(),
+ MeasureSpec.EXACTLY);
+ } else {
+ childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
+ getPaddingTop() + getPaddingBottom(),
+ lp.height);
+ }
+
+ child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+ }
+ }
+
+ mMatchParentChildren.clear();
+ }
+
public void setDayOfWeekTextAppearance(int resId) {
mAdapter.setDayOfWeekTextAppearance(resId);
}
diff --git a/core/java/android/widget/SimpleMonthView.java b/core/java/android/widget/SimpleMonthView.java
index d9f1f0e..aa7f0b6 100644
--- a/core/java/android/widget/SimpleMonthView.java
+++ b/core/java/android/widget/SimpleMonthView.java
@@ -585,7 +585,6 @@ class SimpleMonthView extends View {
mToday = day;
}
}
- mNumWeeks = calculateNumRows();
// Invalidate the old title.
mTitle = null;
@@ -616,18 +615,6 @@ class SimpleMonthView extends View {
}
}
- public void reuse() {
- mNumWeeks = MAX_WEEKS_IN_MONTH;
- requestLayout();
- }
-
- private int calculateNumRows() {
- final int offset = findDayOffset();
- final int dividend = (offset + mDaysInMonth) / DAYS_IN_WEEK;
- final int remainder = (offset + mDaysInMonth) % DAYS_IN_WEEK;
- return dividend + (remainder > 0 ? 1 : 0);
- }
-
private boolean sameDay(int day, Calendar today) {
return mYear == today.get(Calendar.YEAR) && mMonth == today.get(Calendar.MONTH)
&& day == today.get(Calendar.DAY_OF_MONTH);
@@ -635,8 +622,9 @@ class SimpleMonthView extends View {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- final int preferredHeight = mDesiredDayHeight * mNumWeeks + mDesiredDayOfWeekHeight
- + mDesiredMonthHeight + getPaddingTop() + getPaddingBottom();
+ final int preferredHeight = mDesiredDayHeight * MAX_WEEKS_IN_MONTH
+ + mDesiredDayOfWeekHeight + mDesiredMonthHeight
+ + getPaddingTop() + getPaddingBottom();
final int preferredWidth = mDesiredCellWidth * DAYS_IN_WEEK
+ getPaddingStart() + getPaddingEnd();
final int resolvedWidth = resolveSize(preferredWidth, widthMeasureSpec);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 5d60f99..9bbf375 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -540,6 +540,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private Layout mLayout;
private boolean mLocaleChanged = false;
+ @ViewDebug.ExportedProperty(category = "text")
private int mGravity = Gravity.TOP | Gravity.START;
private boolean mHorizontallyScrolling;
diff --git a/core/java/android/widget/YearPickerView.java b/core/java/android/widget/YearPickerView.java
index 7182414..89e59f9 100644
--- a/core/java/android/widget/YearPickerView.java
+++ b/core/java/android/widget/YearPickerView.java
@@ -178,24 +178,29 @@ class YearPickerView extends ListView {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
- if (convertView == null) {
- convertView = mInflater.inflate(ITEM_LAYOUT, parent, false);
+ final TextView v;
+ final boolean hasNewView = convertView == null;
+ if (hasNewView) {
+ v = (TextView) mInflater.inflate(ITEM_LAYOUT, parent, false);
+ } else {
+ v = (TextView) convertView;
}
final int year = getYearForPosition(position);
final boolean activated = mActivatedYear == year;
- final int textAppearanceResId;
- if (activated && ITEM_TEXT_ACTIVATED_APPEARANCE != 0) {
- textAppearanceResId = ITEM_TEXT_ACTIVATED_APPEARANCE;
- } else {
- textAppearanceResId = ITEM_TEXT_APPEARANCE;
+ if (hasNewView || v.isActivated() != activated) {
+ final int textAppearanceResId;
+ if (activated && ITEM_TEXT_ACTIVATED_APPEARANCE != 0) {
+ textAppearanceResId = ITEM_TEXT_ACTIVATED_APPEARANCE;
+ } else {
+ textAppearanceResId = ITEM_TEXT_APPEARANCE;
+ }
+ v.setTextAppearance(textAppearanceResId);
+ v.setActivated(activated);
}
- final TextView v = (TextView) convertView;
- v.setText("" + year);
- v.setTextAppearance(v.getContext(), textAppearanceResId);
- v.setActivated(activated);
+ v.setText(Integer.toString(year));
return v;
}
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index 9dabb4e..b8110e3 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -170,9 +170,8 @@ public class AlertController {
}
private static boolean shouldCenterSingleButton(Context context) {
- TypedValue outValue = new TypedValue();
- context.getTheme().resolveAttribute(com.android.internal.R.attr.alertDialogCenterButtons,
- outValue, true);
+ final TypedValue outValue = new TypedValue();
+ context.getTheme().resolveAttribute(R.attr.alertDialogCenterButtons, outValue, true);
return outValue.data != 0;
}
@@ -182,27 +181,25 @@ public class AlertController {
mWindow = window;
mHandler = new ButtonHandler(di);
- TypedArray a = context.obtainStyledAttributes(null,
- com.android.internal.R.styleable.AlertDialog,
- com.android.internal.R.attr.alertDialogStyle, 0);
+ final TypedArray a = context.obtainStyledAttributes(null,
+ R.styleable.AlertDialog, R.attr.alertDialogStyle, 0);
- mAlertDialogLayout = a.getResourceId(com.android.internal.R.styleable.AlertDialog_layout,
- com.android.internal.R.layout.alert_dialog);
+ mAlertDialogLayout = a.getResourceId(
+ R.styleable.AlertDialog_layout, R.layout.alert_dialog);
mButtonPanelSideLayout = a.getResourceId(
- com.android.internal.R.styleable.AlertDialog_buttonPanelSideLayout, 0);
-
+ R.styleable.AlertDialog_buttonPanelSideLayout, 0);
mListLayout = a.getResourceId(
- com.android.internal.R.styleable.AlertDialog_listLayout,
- com.android.internal.R.layout.select_dialog);
+ R.styleable.AlertDialog_listLayout, R.layout.select_dialog);
+
mMultiChoiceItemLayout = a.getResourceId(
- com.android.internal.R.styleable.AlertDialog_multiChoiceItemLayout,
- com.android.internal.R.layout.select_dialog_multichoice);
+ R.styleable.AlertDialog_multiChoiceItemLayout,
+ R.layout.select_dialog_multichoice);
mSingleChoiceItemLayout = a.getResourceId(
- com.android.internal.R.styleable.AlertDialog_singleChoiceItemLayout,
- com.android.internal.R.layout.select_dialog_singlechoice);
+ R.styleable.AlertDialog_singleChoiceItemLayout,
+ R.layout.select_dialog_singlechoice);
mListItemLayout = a.getResourceId(
- com.android.internal.R.styleable.AlertDialog_listItemLayout,
- com.android.internal.R.layout.select_dialog_item);
+ R.styleable.AlertDialog_listItemLayout,
+ R.layout.select_dialog_item);
a.recycle();
}
@@ -1067,9 +1064,9 @@ public class AlertController {
}
private void createListView(final AlertController dialog) {
- final RecycleListView listView = (RecycleListView)
- mInflater.inflate(dialog.mListLayout, null);
- ListAdapter adapter;
+ final RecycleListView listView =
+ (RecycleListView) mInflater.inflate(dialog.mListLayout, null);
+ final ListAdapter adapter;
if (mIsMultiChoice) {
if (mCursor == null) {
@@ -1115,14 +1112,20 @@ public class AlertController {
};
}
} else {
- int layout = mIsSingleChoice
- ? dialog.mSingleChoiceItemLayout : dialog.mListItemLayout;
- if (mCursor == null) {
- adapter = (mAdapter != null) ? mAdapter
- : new CheckedItemAdapter(mContext, layout, R.id.text1, mItems);
+ final int layout;
+ if (mIsSingleChoice) {
+ layout = dialog.mSingleChoiceItemLayout;
+ } else {
+ layout = dialog.mListItemLayout;
+ }
+
+ if (mCursor != null) {
+ adapter = new SimpleCursorAdapter(mContext, layout, mCursor,
+ new String[] { mLabelColumn }, new int[] { R.id.text1 });
+ } else if (mAdapter != null) {
+ adapter = mAdapter;
} else {
- adapter = new SimpleCursorAdapter(mContext, layout,
- mCursor, new String[]{mLabelColumn}, new int[]{R.id.text1});
+ adapter = new CheckedItemAdapter(mContext, layout, R.id.text1, mItems);
}
}
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 64bd6b6..8403e77 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -18,20 +18,87 @@ package com.android.internal.app;
import android.app.Activity;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
+import android.content.ServiceConnection;
import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
import android.os.Parcelable;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.service.chooser.ChooserTarget;
+import android.service.chooser.ChooserTargetService;
+import android.service.chooser.IChooserTargetResult;
+import android.service.chooser.IChooserTargetService;
+import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.util.ArrayList;
+import java.util.List;
public class ChooserActivity extends ResolverActivity {
private static final String TAG = "ChooserActivity";
+ private static final boolean DEBUG = false;
+
+ private static final int QUERY_TARGET_LIMIT = 5;
+ private static final int WATCHDOG_TIMEOUT_MILLIS = 5000;
+
private Bundle mReplacementExtras;
private IntentSender mChosenComponentSender;
+ private ChooserTarget[] mCallerChooserTargets;
+
+ private final List<ChooserTargetServiceConnection> mServiceConnections = new ArrayList<>();
+
+ private static final int CHOOSER_TARGET_SERVICE_RESULT = 1;
+ private static final int CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT = 2;
+
+ private Handler mTargetResultHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case CHOOSER_TARGET_SERVICE_RESULT:
+ if (DEBUG) Log.d(TAG, "CHOOSER_TARGET_SERVICE_RESULT");
+ if (isDestroyed()) break;
+ final ServiceResultInfo sri = (ServiceResultInfo) msg.obj;
+ if (!mServiceConnections.contains(sri.connection)) {
+ Log.w(TAG, "ChooserTargetServiceConnection " + sri.connection
+ + " returned after being removed from active connections."
+ + " Have you considered returning results faster?");
+ break;
+ }
+ final ChooserListAdapter cla = (ChooserListAdapter) getAdapter();
+ cla.addServiceResults(sri.originalTarget, sri.resultTargets);
+ unbindService(sri.connection);
+ mServiceConnections.remove(sri.connection);
+ break;
+
+ case CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT:
+ if (DEBUG) {
+ Log.d(TAG, "CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT; unbinding services");
+ }
+ unbindRemainingServices();
+ break;
+
+ default:
+ super.handleMessage(msg);
+ }
+ }
+ };
+
@Override
protected void onCreate(Bundle savedInstanceState) {
Intent intent = getIntent();
@@ -42,7 +109,7 @@ public class ChooserActivity extends ResolverActivity {
super.onCreate(null);
return;
}
- Intent target = (Intent)targetParcelable;
+ Intent target = (Intent) targetParcelable;
if (target != null) {
modifyTargetIntent(target);
}
@@ -68,6 +135,22 @@ public class ChooserActivity extends ResolverActivity {
initialIntents[i] = in;
}
}
+
+ 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("ChooserActivity", "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);
setSafeForwardingMode(true);
@@ -94,9 +177,9 @@ public class ChooserActivity extends ResolverActivity {
}
@Override
- public void onActivityStarted(Intent intent) {
+ void onActivityStarted(TargetInfo cti) {
if (mChosenComponentSender != null) {
- final ComponentName target = intent.getComponent();
+ final ComponentName target = cti.getResolvedComponentName();
if (target != null) {
final Intent fillIn = new Intent().putExtra(Intent.EXTRA_CHOSEN_COMPONENT, target);
try {
@@ -109,6 +192,16 @@ public class ChooserActivity extends ResolverActivity {
}
}
+ @Override
+ int getLayoutResource() {
+ return com.android.internal.R.layout.chooser_grid;
+ }
+
+ @Override
+ boolean shouldGetActivityMetadata() {
+ return true;
+ }
+
private void modifyTargetIntent(Intent in) {
final String action = in.getAction();
if (Intent.ACTION_SEND.equals(action) ||
@@ -117,4 +210,297 @@ public class ChooserActivity extends ResolverActivity {
Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
}
}
+
+ void queryTargetServices(ChooserListAdapter adapter) {
+ final PackageManager pm = getPackageManager();
+ int targetsToQuery = 0;
+ for (int i = 0, N = adapter.getDisplayResolveInfoCount(); i < N; i++) {
+ final DisplayResolveInfo dri = adapter.getDisplayResolveInfo(i);
+ final ActivityInfo ai = dri.getResolveInfo().activityInfo;
+ final Bundle md = ai.metaData;
+ final String serviceName = md != null ? convertServiceName(ai.packageName,
+ md.getString(ChooserTargetService.META_DATA_NAME)) : null;
+ if (serviceName != null) {
+ final ComponentName serviceComponent = new ComponentName(
+ ai.packageName, serviceName);
+ final Intent serviceIntent = new Intent(ChooserTargetService.SERVICE_INTERFACE)
+ .setComponent(serviceComponent);
+
+ if (DEBUG) {
+ Log.d(TAG, "queryTargets found target with service " + serviceComponent);
+ }
+
+ try {
+ final String perm = pm.getServiceInfo(serviceComponent, 0).permission;
+ if (!ChooserTargetService.BIND_PERMISSION.equals(perm)) {
+ Log.w(TAG, "ChooserTargetService " + serviceComponent + " does not require"
+ + " permission " + ChooserTargetService.BIND_PERMISSION
+ + " - this service will not be queried for ChooserTargets."
+ + " add android:permission=\""
+ + ChooserTargetService.BIND_PERMISSION + "\""
+ + " to the <service> tag for " + serviceComponent
+ + " in the manifest.");
+ continue;
+ }
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Could not look up service " + serviceComponent, e);
+ continue;
+ }
+
+ final ChooserTargetServiceConnection conn = new ChooserTargetServiceConnection(dri);
+ if (bindServiceAsUser(serviceIntent, conn, BIND_AUTO_CREATE | BIND_NOT_FOREGROUND,
+ UserHandle.CURRENT)) {
+ if (DEBUG) {
+ Log.d(TAG, "Binding service connection for target " + dri
+ + " intent " + serviceIntent);
+ }
+ mServiceConnections.add(conn);
+ targetsToQuery++;
+ }
+ }
+ if (targetsToQuery >= QUERY_TARGET_LIMIT) {
+ if (DEBUG) Log.d(TAG, "queryTargets hit query target limit " + QUERY_TARGET_LIMIT);
+ break;
+ }
+ }
+
+ if (!mServiceConnections.isEmpty()) {
+ if (DEBUG) Log.d(TAG, "queryTargets setting watchdog timer for "
+ + WATCHDOG_TIMEOUT_MILLIS + "ms");
+ mTargetResultHandler.sendEmptyMessageDelayed(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT,
+ WATCHDOG_TIMEOUT_MILLIS);
+ }
+ }
+
+ private String convertServiceName(String packageName, String serviceName) {
+ if (TextUtils.isEmpty(serviceName)) {
+ return null;
+ }
+
+ final String fullName;
+ if (serviceName.startsWith(".")) {
+ // Relative to the app package. Prepend the app package name.
+ fullName = packageName + serviceName;
+ } else if (serviceName.indexOf('.') >= 0) {
+ // Fully qualified package name.
+ fullName = serviceName;
+ } else {
+ fullName = null;
+ }
+ return fullName;
+ }
+
+ void unbindRemainingServices() {
+ if (DEBUG) {
+ Log.d(TAG, "unbindRemainingServices, " + mServiceConnections.size() + " left");
+ }
+ for (int i = 0, N = mServiceConnections.size(); i < N; i++) {
+ final ChooserTargetServiceConnection conn = mServiceConnections.get(i);
+ if (DEBUG) Log.d(TAG, "unbinding " + conn);
+ unbindService(conn);
+ }
+ mServiceConnections.clear();
+ mTargetResultHandler.removeMessages(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT);
+ }
+
+ @Override
+ ResolveListAdapter createAdapter(Context context, Intent[] initialIntents,
+ List<ResolveInfo> rList, int launchedFromUid, boolean filterLastUsed) {
+ final ChooserListAdapter adapter = new ChooserListAdapter(context, initialIntents, rList,
+ launchedFromUid, filterLastUsed);
+ if (DEBUG) Log.d(TAG, "Adapter created; querying services");
+ queryTargetServices(adapter);
+ return adapter;
+ }
+
+ class ChooserTargetInfo implements TargetInfo {
+ private final TargetInfo mSourceInfo;
+ private final ChooserTarget mChooserTarget;
+ private final Drawable mDisplayIcon;
+
+ public ChooserTargetInfo(TargetInfo sourceInfo, ChooserTarget chooserTarget) {
+ mSourceInfo = sourceInfo;
+ mChooserTarget = chooserTarget;
+ mDisplayIcon = new BitmapDrawable(getResources(), chooserTarget.getIcon());
+ }
+
+ @Override
+ public Intent getResolvedIntent() {
+ final Intent targetIntent = mChooserTarget.getIntent();
+ return targetIntent != null ? targetIntent : mSourceInfo.getResolvedIntent();
+ }
+
+ @Override
+ public ComponentName getResolvedComponentName() {
+ return mSourceInfo.getResolvedComponentName();
+ }
+
+ @Override
+ public boolean start(Activity activity, Bundle options) {
+ return mChooserTarget.sendIntent(activity, mSourceInfo.getResolvedIntent());
+ }
+
+ @Override
+ public boolean startAsCaller(Activity activity, Bundle options, int userId) {
+ return mChooserTarget.sendIntentAsCaller(activity, mSourceInfo.getResolvedIntent(),
+ userId);
+ }
+
+ @Override
+ public boolean startAsUser(Activity activity, Bundle options, UserHandle user) {
+ return mChooserTarget.sendIntentAsUser(activity, mSourceInfo.getResolvedIntent(), user);
+ }
+
+ @Override
+ public ResolveInfo getResolveInfo() {
+ return mSourceInfo.getResolveInfo();
+ }
+
+ @Override
+ public CharSequence getDisplayLabel() {
+ return mChooserTarget.getTitle();
+ }
+
+ @Override
+ public CharSequence getExtendedInfo() {
+ return mSourceInfo.getExtendedInfo();
+ }
+
+ @Override
+ public Drawable getDisplayIcon() {
+ return mDisplayIcon;
+ }
+ }
+
+ public class ChooserListAdapter extends ResolveListAdapter {
+ private final List<ChooserTargetInfo> mServiceTargets = new ArrayList<>();
+
+ public ChooserListAdapter(Context context, Intent[] initialIntents, List<ResolveInfo> rList,
+ int launchedFromUid, boolean filterLastUsed) {
+ super(context, initialIntents, rList, launchedFromUid, filterLastUsed);
+ }
+
+ @Override
+ public boolean showsExtendedInfo(TargetInfo info) {
+ // Reserve space to show extended info if any one of the items in the adapter has
+ // extended info. This keeps grid item sizes uniform.
+ return hasExtendedInfo();
+ }
+
+ @Override
+ public View createView(ViewGroup parent) {
+ return mInflater.inflate(
+ com.android.internal.R.layout.resolve_grid_item, parent, false);
+ }
+
+ @Override
+ public void onListRebuilt() {
+ if (mServiceTargets != null) {
+ pruneServiceTargets();
+ }
+ }
+
+ @Override
+ public int getCount() {
+ int count = super.getCount();
+ if (mServiceTargets != null) {
+ count += mServiceTargets.size();
+ }
+ return count;
+ }
+
+ @Override
+ public TargetInfo getItem(int position) {
+ int offset = 0;
+ if (mServiceTargets != null) {
+ final int serviceTargetCount = mServiceTargets.size();
+ if (position < serviceTargetCount) {
+ return mServiceTargets.get(position);
+ }
+ offset += serviceTargetCount;
+ }
+ return super.getItem(position - offset);
+ }
+
+ public void addServiceResults(DisplayResolveInfo origTarget, List<ChooserTarget> targets) {
+ if (DEBUG) Log.d(TAG, "addServiceResults " + origTarget + ", " + targets.size()
+ + " targets");
+ for (int i = 0, N = targets.size(); i < N; i++) {
+ mServiceTargets.add(new ChooserTargetInfo(origTarget, targets.get(i)));
+ }
+
+ // TODO: Maintain sort by ranking scores.
+
+ notifyDataSetChanged();
+ }
+
+ private void pruneServiceTargets() {
+ if (DEBUG) Log.d(TAG, "pruneServiceTargets");
+ for (int i = mServiceTargets.size() - 1; i >= 0; i--) {
+ final ChooserTargetInfo cti = mServiceTargets.get(i);
+ if (!hasResolvedTarget(cti.getResolveInfo())) {
+ if (DEBUG) Log.d(TAG, " => " + i + " " + cti);
+ mServiceTargets.remove(i);
+ }
+ }
+ }
+ }
+
+ class ChooserTargetServiceConnection implements ServiceConnection {
+ private final DisplayResolveInfo mOriginalTarget;
+
+ private final IChooserTargetResult mChooserTargetResult = new IChooserTargetResult.Stub() {
+ @Override
+ public void sendResult(List<ChooserTarget> targets) throws RemoteException {
+ final Message msg = Message.obtain();
+ msg.what = CHOOSER_TARGET_SERVICE_RESULT;
+ msg.obj = new ServiceResultInfo(mOriginalTarget, targets,
+ ChooserTargetServiceConnection.this);
+ mTargetResultHandler.sendMessage(msg);
+ }
+ };
+
+ public ChooserTargetServiceConnection(DisplayResolveInfo dri) {
+ mOriginalTarget = dri;
+ }
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ if (DEBUG) Log.d(TAG, "onServiceConnected: " + name);
+ final IChooserTargetService icts = IChooserTargetService.Stub.asInterface(service);
+ try {
+ icts.getChooserTargets(mOriginalTarget.getResolvedComponentName(),
+ mOriginalTarget.getResolveInfo().filter, mChooserTargetResult);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Querying ChooserTargetService " + name + " failed.", e);
+ unbindService(this);
+ mServiceConnections.remove(this);
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ if (DEBUG) Log.d(TAG, "onServiceDisconnected: " + name);
+ unbindService(this);
+ mServiceConnections.remove(this);
+ }
+
+ @Override
+ public String toString() {
+ return mOriginalTarget.getResolveInfo().activityInfo.toString();
+ }
+ }
+
+ static class ServiceResultInfo {
+ public final DisplayResolveInfo originalTarget;
+ public final List<ChooserTarget> resultTargets;
+ public final ChooserTargetServiceConnection connection;
+
+ public ServiceResultInfo(DisplayResolveInfo ot, List<ChooserTarget> rt,
+ ChooserTargetServiceConnection c) {
+ originalTarget = ot;
+ resultTargets = rt;
+ connection = c;
+ }
+ }
}
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 6b35f3f..3cd69a1 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -25,6 +25,7 @@ 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;
@@ -91,15 +92,14 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
private PackageManager mPm;
private boolean mSafeForwardingMode;
private boolean mAlwaysUseOption;
- private boolean mShowExtended;
+ private AbsListView mAdapterView;
private ListView mListView;
+ private GridView mGridView;
private Button mAlwaysButton;
private Button mOnceButton;
private View mProfileView;
private int mIconDpi;
- private int mIconSize;
- private int mMaxColumns;
- private int mLastSelected = ListView.INVALID_POSITION;
+ private int mLastSelected = AbsListView.INVALID_POSITION;
private boolean mResolvingHome = false;
private int mProfileSwitchMessageId = -1;
private Intent mIntent;
@@ -192,7 +192,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
}
/**
- * Compatibility version for other bundled services that use this ocerload without
+ * Compatibility version for other bundled services that use this overload without
* a default title resource
*/
protected void onCreate(Bundle savedInstanceState, Intent intent,
@@ -223,18 +223,14 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
final long sinceTime = System.currentTimeMillis() - USAGE_STATS_PERIOD;
mStats = mUsm.queryAndAggregateUsageStats(sinceTime, System.currentTimeMillis());
- mMaxColumns = getResources().getInteger(R.integer.config_maxResolverActivityColumns);
-
mPackageMonitor.register(this, getMainLooper(), false);
mRegistered = true;
final ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
mIconDpi = am.getLauncherLargeIconDensity();
- mIconSize = am.getLauncherLargeIconSize();
mIntent = new Intent(intent);
- mAdapter = new ResolveListAdapter(this, initialIntents, rList,
- mLaunchedFromUid, alwaysUseOption);
+ mAdapter = createAdapter(this, initialIntents, rList, mLaunchedFromUid, alwaysUseOption);
final int layoutId;
final boolean useHeader;
@@ -244,7 +240,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
useHeader = true;
} else {
useHeader = false;
- layoutId = R.layout.resolver_list;
+ layoutId = getLayoutResource();
}
mAlwaysUseOption = alwaysUseOption;
@@ -257,21 +253,30 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
int count = mAdapter.mList.size();
if (count > 1 || (count == 1 && mAdapter.getOtherProfile() != null)) {
setContentView(layoutId);
- mListView = (ListView) findViewById(R.id.resolver_list);
- mListView.setAdapter(mAdapter);
- mListView.setOnItemClickListener(this);
- mListView.setOnItemLongClickListener(new ItemLongClickListener());
+ 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) {
- mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+ mAdapterView.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
}
- if (useHeader) {
+ if (useHeader && mListView != null) {
mListView.addHeaderView(LayoutInflater.from(this).inflate(
R.layout.resolver_different_item_header, mListView, false));
}
} else if (count == 1) {
- safelyStartActivity(mAdapter.intentForPosition(0, false));
+ safelyStartActivity(mAdapter.targetInfoForPosition(0, false));
mPackageMonitor.unregister();
mRegistered = false;
finish();
@@ -282,8 +287,8 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
final TextView empty = (TextView) findViewById(R.id.empty);
empty.setVisibility(View.VISIBLE);
- mListView = (ListView) findViewById(R.id.resolver_list);
- mListView.setVisibility(View.GONE);
+ 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.
@@ -308,12 +313,30 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
titleView.setText(title);
}
setTitle(title);
+
+ // Try to initialize the title icon if we have a view for it and a title to match
+ final ImageView titleIcon = (ImageView) findViewById(R.id.title_icon);
+ if (titleIcon != null) {
+ final String referrerPackage = getReferrerPackageName();
+ ApplicationInfo ai = null;
+ try {
+ if (!TextUtils.isEmpty(referrerPackage)) {
+ ai = mPm.getApplicationInfo(referrerPackage, 0);
+ }
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Could not find referrer package " + referrerPackage);
+ }
+
+ if (ai != null) {
+ titleIcon.setImageDrawable(ai.loadIcon(mPm));
+ }
+ }
}
final ImageView iconView = (ImageView) findViewById(R.id.icon);
final DisplayResolveInfo iconInfo = mAdapter.getFilteredItem();
if (iconView != null && iconInfo != null) {
- new LoadIconIntoViewTask(iconView).execute(iconInfo);
+ new LoadIconIntoViewTask(iconInfo, iconView).execute();
}
if (alwaysUseOption || mAdapter.hasFilteredItem()) {
@@ -345,8 +368,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
// Do not show the profile switch message anymore.
mProfileSwitchMessageId = -1;
- final Intent intent = intentForDisplayResolveInfo(dri);
- onIntentSelected(dri.ri, intent, false);
+ onTargetSelected(dri, false);
finish();
}
});
@@ -354,17 +376,29 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
}
}
+ private String getReferrerPackageName() {
+ final Uri referrer = getReferrer();
+ if (referrer != null && "android-app".equals(referrer.getScheme())) {
+ return referrer.getHost();
+ }
+ return null;
+ }
+
+ int getLayoutResource() {
+ return R.layout.resolver_list;
+ }
+
void bindProfileView() {
final DisplayResolveInfo dri = mAdapter.getOtherProfile();
if (dri != null) {
mProfileView.setVisibility(View.VISIBLE);
final ImageView icon = (ImageView) mProfileView.findViewById(R.id.icon);
final TextView text = (TextView) mProfileView.findViewById(R.id.text1);
- if (dri.displayIcon == null) {
- new LoadIconTask().execute(dri);
+ if (!dri.hasDisplayIcon()) {
+ new LoadIconIntoViewTask(dri, icon).execute();
}
- icon.setImageDrawable(dri.displayIcon);
- text.setText(dri.displayLabel);
+ icon.setImageDrawable(dri.getDisplayIcon());
+ text.setText(dri.getDisplayLabel());
} else {
mProfileView.setVisibility(View.GONE);
}
@@ -408,8 +442,9 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
if (title == ActionTitle.DEFAULT && defaultTitleRes != 0) {
return getString(defaultTitleRes);
} else {
- return named ? getString(title.namedTitleRes, mAdapter.getFilteredItem().displayLabel) :
- getString(title.titleRes);
+ return named
+ ? getString(title.namedTitleRes, mAdapter.getFilteredItem().getDisplayLabel())
+ : getString(title.titleRes);
}
}
@@ -490,31 +525,33 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if (mAlwaysUseOption) {
- final int checkedPos = mListView.getCheckedItemPosition();
+ final int checkedPos = mAdapterView.getCheckedItemPosition();
final boolean hasValidSelection = checkedPos != ListView.INVALID_POSITION;
mLastSelected = checkedPos;
setAlwaysButtonEnabled(hasValidSelection, checkedPos, true);
mOnceButton.setEnabled(hasValidSelection);
if (hasValidSelection) {
- mListView.setSelection(checkedPos);
+ mAdapterView.setSelection(checkedPos);
}
}
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- position -= mListView.getHeaderViewsCount();
+ if (mListView != null) {
+ position -= mListView.getHeaderViewsCount();
+ }
if (position < 0) {
// Header views don't count.
return;
}
- final int checkedPos = mListView.getCheckedItemPosition();
+ 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) {
- mListView.smoothScrollToPosition(checkedPos);
+ mAdapterView.smoothScrollToPosition(checkedPos);
}
mLastSelected = checkedPos;
} else {
@@ -570,7 +607,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
public void onButtonClick(View v) {
final int id = v.getId();
startSelected(mAlwaysUseOption ?
- mListView.getCheckedItemPosition() : mAdapter.getFilteredPosition(),
+ mAdapterView.getCheckedItemPosition() : mAdapter.getFilteredPosition(),
id == R.id.button_always,
mAlwaysUseOption);
}
@@ -588,8 +625,8 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
return;
}
- Intent intent = mAdapter.intentForPosition(which, filtered);
- onIntentSelected(ri, intent, always);
+ TargetInfo target = mAdapter.targetInfoForPosition(which, filtered);
+ onTargetSelected(target, always);
finish();
}
@@ -600,8 +637,12 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
return defIntent;
}
- protected void onIntentSelected(ResolveInfo ri, Intent intent, boolean alwaysCheck) {
- if ((mAlwaysUseOption || mAdapter.hasFilteredItem()) && mAdapter.mOrigResolveList != null) {
+ protected void onTargetSelected(TargetInfo target, boolean alwaysCheck) {
+ final ResolveInfo ri = target.getResolveInfo();
+ final Intent intent = target != null ? target.getResolvedIntent() : null;
+
+ if (intent != null && (mAlwaysUseOption || mAdapter.hasFilteredItem())
+ && mAdapter.mOrigResolveList != null) {
// Build a reasonable intent filter, based on what matched.
IntentFilter filter = new IntentFilter();
String action = intent.getAction();
@@ -617,7 +658,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
}
filter.addCategory(Intent.CATEGORY_DEFAULT);
- int cat = ri.match&IntentFilter.MATCH_CATEGORY_MASK;
+ int cat = ri.match & IntentFilter.MATCH_CATEGORY_MASK;
Uri data = intent.getData();
if (cat == IntentFilter.MATCH_CATEGORY_TYPE) {
String mimeType = intent.resolveType(this);
@@ -726,25 +767,27 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
}
}
- if (intent != null) {
- safelyStartActivity(intent);
+ if (target != null) {
+ safelyStartActivity(target);
}
}
- public void safelyStartActivity(Intent intent) {
+ void safelyStartActivity(TargetInfo cti) {
// If needed, show that intent is forwarded
// from managed profile to owner or other way around.
if (mProfileSwitchMessageId != -1) {
Toast.makeText(this, getString(mProfileSwitchMessageId), Toast.LENGTH_LONG).show();
}
if (!mSafeForwardingMode) {
- startActivity(intent);
- onActivityStarted(intent);
+ if (cti.start(this, null)) {
+ onActivityStarted(cti);
+ }
return;
}
try {
- startActivityAsCaller(intent, null, UserHandle.USER_NULL);
- onActivityStarted(intent);
+ if (cti.startAsCaller(this, null, UserHandle.USER_NULL)) {
+ onActivityStarted(cti);
+ }
} catch (RuntimeException e) {
String launchedFromPackage;
try {
@@ -759,51 +802,197 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
}
}
- public void onActivityStarted(Intent intent) {
+ void onActivityStarted(TargetInfo cti) {
// Do nothing
}
+ boolean shouldGetActivityMetadata() {
+ return false;
+ }
+
void showAppDetails(ResolveInfo ri) {
Intent in = new Intent().setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
.setData(Uri.fromParts("package", ri.activityInfo.packageName, null))
- .addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
startActivity(in);
}
- Intent intentForDisplayResolveInfo(DisplayResolveInfo dri) {
- Intent intent = new Intent(dri.origIntent != null ? dri.origIntent :
- getReplacementIntent(dri.ri.activityInfo, mIntent));
- intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT
- |Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
- ActivityInfo ai = dri.ri.activityInfo;
- intent.setComponent(new ComponentName(
- ai.applicationInfo.packageName, ai.name));
- return intent;
+ ResolveListAdapter createAdapter(Context context, Intent[] initialIntents,
+ List<ResolveInfo> rList, int launchedFromUid, boolean filterLastUsed) {
+ return new ResolveListAdapter(context, initialIntents, rList, launchedFromUid,
+ filterLastUsed);
+ }
+
+ ResolveListAdapter getAdapter() {
+ return mAdapter;
}
- private final class DisplayResolveInfo {
- ResolveInfo ri;
- CharSequence displayLabel;
- Drawable displayIcon;
- CharSequence extendedInfo;
- Intent origIntent;
+ final class DisplayResolveInfo implements TargetInfo {
+ private final ResolveInfo mResolveInfo;
+ private final CharSequence mDisplayLabel;
+ private Drawable mDisplayIcon;
+ private final CharSequence mExtendedInfo;
+ private final Intent mResolvedIntent;
DisplayResolveInfo(ResolveInfo pri, CharSequence pLabel,
CharSequence pInfo, Intent pOrigIntent) {
- ri = pri;
- displayLabel = pLabel;
- extendedInfo = pInfo;
- origIntent = pOrigIntent;
+ mResolveInfo = pri;
+ mDisplayLabel = pLabel;
+ mExtendedInfo = pInfo;
+
+ final Intent intent = new Intent(pOrigIntent != null ? pOrigIntent :
+ getReplacementIntent(pri.activityInfo, mIntent));
+ intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT
+ | Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
+ final ActivityInfo ai = mResolveInfo.activityInfo;
+ intent.setComponent(new ComponentName(ai.applicationInfo.packageName, ai.name));
+
+ mResolvedIntent = intent;
+ }
+
+ public ResolveInfo getResolveInfo() {
+ return mResolveInfo;
+ }
+
+ public CharSequence getDisplayLabel() {
+ return mDisplayLabel;
+ }
+
+ public Drawable getDisplayIcon() {
+ return mDisplayIcon;
+ }
+
+ public void setDisplayIcon(Drawable icon) {
+ mDisplayIcon = icon;
+ }
+
+ public boolean hasDisplayIcon() {
+ return mDisplayIcon != null;
+ }
+
+ public CharSequence getExtendedInfo() {
+ return mExtendedInfo;
+ }
+
+ public Intent getResolvedIntent() {
+ return mResolvedIntent;
+ }
+
+ @Override
+ public ComponentName getResolvedComponentName() {
+ return new ComponentName(mResolveInfo.activityInfo.packageName,
+ mResolveInfo.activityInfo.name);
+ }
+
+ @Override
+ public boolean start(Activity activity, Bundle options) {
+ activity.startActivity(mResolvedIntent, options);
+ return true;
}
+
+ @Override
+ public boolean startAsCaller(Activity activity, Bundle options, int userId) {
+ activity.startActivityAsCaller(mResolvedIntent, options, userId);
+ return true;
+ }
+
+ @Override
+ public boolean startAsUser(Activity activity, Bundle options, UserHandle user) {
+ activity.startActivityAsUser(mResolvedIntent, options, user);
+ return false;
+ }
+ }
+
+ /**
+ * A single target as represented in the chooser.
+ */
+ public interface TargetInfo {
+ /**
+ * Get the resolved intent that represents this target. Note that this may not be the
+ * intent that will be launched by calling one of the <code>start</code> methods provided;
+ * this is the intent that will be credited with the launch.
+ *
+ * @return the resolved intent for this target
+ */
+ public Intent getResolvedIntent();
+
+ /**
+ * Get the resolved component name that represents this target. Note that this may not
+ * be the component that will be directly launched by calling one of the <code>start</code>
+ * methods provided; this is the component that will be credited with the launch.
+ *
+ * @return the resolved ComponentName for this target
+ */
+ public ComponentName getResolvedComponentName();
+
+ /**
+ * Start the activity referenced by this target.
+ *
+ * @param activity calling Activity performing the launch
+ * @param options ActivityOptions bundle
+ * @return true if the start completed successfully
+ */
+ public boolean start(Activity activity, Bundle options);
+
+ /**
+ * Start the activity referenced by this target as if the ResolverActivity's caller
+ * was performing the start operation.
+ *
+ * @param activity calling Activity (actually) performing the launch
+ * @param options ActivityOptions bundle
+ * @param userId userId to start as or {@link UserHandle#USER_NULL} for activity's caller
+ * @return true if the start completed successfully
+ */
+ public boolean startAsCaller(Activity activity, Bundle options, int userId);
+
+ /**
+ * Start the activity referenced by this target as a given user.
+ *
+ * @param activity calling activity performing the launch
+ * @param options ActivityOptions bundle
+ * @param user handle for the user to start the activity as
+ * @return true if the start completed successfully
+ */
+ public boolean startAsUser(Activity activity, Bundle options, UserHandle user);
+
+ /**
+ * Return the ResolveInfo about how and why this target matched the original query
+ * for available targets.
+ *
+ * @return ResolveInfo representing this target's match
+ */
+ public ResolveInfo getResolveInfo();
+
+ /**
+ * Return the human-readable text label for this target.
+ *
+ * @return user-visible target label
+ */
+ public CharSequence getDisplayLabel();
+
+ /**
+ * Return any extended info for this target. This may be used to disambiguate
+ * otherwise identical targets.
+ *
+ * @return human-readable disambig string or null if none present
+ */
+ public CharSequence getExtendedInfo();
+
+ /**
+ * @return The drawable that should be used to represent this target
+ */
+ public Drawable getDisplayIcon();
}
- private final class ResolveListAdapter extends BaseAdapter {
+ class ResolveListAdapter extends BaseAdapter {
private final Intent[] mInitialIntents;
private final List<ResolveInfo> mBaseResolveList;
private ResolveInfo mLastChosen;
private DisplayResolveInfo mOtherProfile;
private final int mLaunchedFromUid;
- private final LayoutInflater mInflater;
+ private boolean mHasExtendedInfo;
+
+ protected final LayoutInflater mInflater;
List<DisplayResolveInfo> mList;
List<ResolveInfo> mOrigResolveList;
@@ -817,7 +1006,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
mBaseResolveList = rList;
mLaunchedFromUid = launchedFromUid;
mInflater = LayoutInflater.from(context);
- mList = new ArrayList<DisplayResolveInfo>();
+ mList = new ArrayList<>();
mFilterLastUsed = filterLastUsed;
rebuildList();
}
@@ -871,9 +1060,11 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
if (mBaseResolveList != null) {
currentResolveList = mOrigResolveList = mBaseResolveList;
} else {
- currentResolveList = mOrigResolveList = mPm.queryIntentActivities(
- mIntent, PackageManager.MATCH_DEFAULT_ONLY
- | (mFilterLastUsed ? PackageManager.GET_RESOLVED_FILTER : 0));
+ currentResolveList = mOrigResolveList = mPm.queryIntentActivities(mIntent,
+ PackageManager.MATCH_DEFAULT_ONLY
+ | (mFilterLastUsed ? PackageManager.GET_RESOLVED_FILTER : 0)
+ | (shouldGetActivityMetadata() ? PackageManager.GET_META_DATA : 0)
+ );
// Filter out any activities that the launched uid does not
// have permission for. We don't do this when we have an explicit
// list of resolved activities, because that only happens when
@@ -961,7 +1152,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
r0 = currentResolveList.get(0);
int start = 0;
CharSequence r0Label = r0.loadLabel(mPm);
- mShowExtended = false;
+ mHasExtendedInfo = false;
for (int i = 1; i < N; i++) {
if (r0Label == null) {
r0Label = r0.activityInfo.packageName;
@@ -989,6 +1180,12 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
mLastChosenPosition = -1;
mFilterLastUsed = false;
}
+
+ onListRebuilt();
+ }
+
+ public void onListRebuilt() {
+ // This space for rent
}
private void processGroup(List<ResolveInfo> rList, int start, int end, ResolveInfo ro,
@@ -1000,7 +1197,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
addResolveInfo(new DisplayResolveInfo(ro, roLabel, null, null));
updateLastChosenPosition(ro);
} else {
- mShowExtended = true;
+ mHasExtendedInfo = true;
boolean usePkg = false;
CharSequence startApp = ro.activityInfo.applicationInfo.loadLabel(mPm);
if (startApp == null) {
@@ -1049,7 +1246,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
}
private void addResolveInfo(DisplayResolveInfo dri) {
- if (dri.ri.targetUserId != UserHandle.USER_CURRENT && mOtherProfile == null) {
+ if (dri.mResolveInfo.targetUserId != UserHandle.USER_CURRENT && mOtherProfile == null) {
// So far we only support a single other profile at a time.
// The first one we see gets special treatment.
mOtherProfile = dri;
@@ -1059,12 +1256,11 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
}
public ResolveInfo resolveInfoForPosition(int position, boolean filtered) {
- return (filtered ? getItem(position) : mList.get(position)).ri;
+ return (filtered ? getItem(position) : mList.get(position)).getResolveInfo();
}
- public Intent intentForPosition(int position, boolean filtered) {
- DisplayResolveInfo dri = filtered ? getItem(position) : mList.get(position);
- return intentForDisplayResolveInfo(dri);
+ public TargetInfo targetInfoForPosition(int position, boolean filtered) {
+ return filtered ? getItem(position) : mList.get(position);
}
public int getCount() {
@@ -1075,7 +1271,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
return result;
}
- public DisplayResolveInfo getItem(int position) {
+ public TargetInfo getItem(int position) {
if (mFilterLastUsed && mLastChosenPosition >= 0 && position >= mLastChosenPosition) {
position++;
}
@@ -1086,11 +1282,31 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
return position;
}
- public View getView(int position, View convertView, ViewGroup parent) {
+ public boolean hasExtendedInfo() {
+ return mHasExtendedInfo;
+ }
+
+ public boolean hasResolvedTarget(ResolveInfo info) {
+ for (int i = 0, N = mList.size(); i < N; i++) {
+ if (info.equals(mList.get(i).getResolveInfo())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ protected int getDisplayResolveInfoCount() {
+ return mList.size();
+ }
+
+ protected DisplayResolveInfo getDisplayResolveInfo(int index) {
+ return mList.get(index);
+ }
+
+ public final View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null) {
- view = mInflater.inflate(
- com.android.internal.R.layout.resolve_list_item, parent, false);
+ view = createView(parent);
final ViewHolder holder = new ViewHolder(view);
view.setTag(holder);
@@ -1099,19 +1315,29 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
return view;
}
- private final void bindView(View view, DisplayResolveInfo info) {
+ public View createView(ViewGroup parent) {
+ return mInflater.inflate(
+ com.android.internal.R.layout.resolve_list_item, parent, false);
+ }
+
+ public boolean showsExtendedInfo(TargetInfo info) {
+ return !TextUtils.isEmpty(info.getExtendedInfo());
+ }
+
+ private final void bindView(View view, TargetInfo info) {
final ViewHolder holder = (ViewHolder) view.getTag();
- holder.text.setText(info.displayLabel);
- if (mShowExtended) {
+ holder.text.setText(info.getDisplayLabel());
+ if (showsExtendedInfo(info)) {
holder.text2.setVisibility(View.VISIBLE);
- holder.text2.setText(info.extendedInfo);
+ holder.text2.setText(info.getExtendedInfo());
} else {
holder.text2.setVisibility(View.GONE);
}
- if (info.displayIcon == null) {
- new LoadIconTask().execute(info);
+ if (info instanceof DisplayResolveInfo
+ && !((DisplayResolveInfo) info).hasDisplayIcon()) {
+ new LoadAdapterIconTask((DisplayResolveInfo) info).execute();
}
- holder.icon.setImageDrawable(info.displayIcon);
+ holder.icon.setImageDrawable(info.getDisplayIcon());
}
}
@@ -1131,7 +1357,9 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
- position -= mListView.getHeaderViewsCount();
+ if (mListView != null) {
+ position -= mListView.getHeaderViewsCount();
+ }
if (position < 0) {
// Header views don't count.
return false;
@@ -1143,44 +1371,53 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
}
- class LoadIconTask extends AsyncTask<DisplayResolveInfo, Void, DisplayResolveInfo> {
+ abstract class LoadIconTask extends AsyncTask<Void, Void, Drawable> {
+ protected final DisplayResolveInfo mDisplayResolveInfo;
+ private final ResolveInfo mResolveInfo;
+
+ public LoadIconTask(DisplayResolveInfo dri) {
+ mDisplayResolveInfo = dri;
+ mResolveInfo = dri.getResolveInfo();
+ }
+
@Override
- protected DisplayResolveInfo doInBackground(DisplayResolveInfo... params) {
- final DisplayResolveInfo info = params[0];
- if (info.displayIcon == null) {
- info.displayIcon = loadIconForResolveInfo(info.ri);
- }
- return info;
+ protected Drawable doInBackground(Void... params) {
+ return loadIconForResolveInfo(mResolveInfo);
+ }
+
+ @Override
+ protected void onPostExecute(Drawable d) {
+ mDisplayResolveInfo.setDisplayIcon(d);
+ }
+ }
+
+ class LoadAdapterIconTask extends LoadIconTask {
+ public LoadAdapterIconTask(DisplayResolveInfo dri) {
+ super(dri);
}
@Override
- protected void onPostExecute(DisplayResolveInfo info) {
- if (mProfileView != null && mAdapter.getOtherProfile() == info) {
+ protected void onPostExecute(Drawable d) {
+ super.onPostExecute(d);
+ if (mProfileView != null && mAdapter.getOtherProfile() == mDisplayResolveInfo) {
bindProfileView();
}
mAdapter.notifyDataSetChanged();
}
}
- class LoadIconIntoViewTask extends AsyncTask<DisplayResolveInfo, Void, DisplayResolveInfo> {
- final ImageView mTargetView;
+ class LoadIconIntoViewTask extends LoadIconTask {
+ private final ImageView mTargetView;
- public LoadIconIntoViewTask(ImageView target) {
+ public LoadIconIntoViewTask(DisplayResolveInfo dri, ImageView target) {
+ super(dri);
mTargetView = target;
}
@Override
- protected DisplayResolveInfo doInBackground(DisplayResolveInfo... params) {
- final DisplayResolveInfo info = params[0];
- if (info.displayIcon == null) {
- info.displayIcon = loadIconForResolveInfo(info.ri);
- }
- return info;
- }
-
- @Override
- protected void onPostExecute(DisplayResolveInfo info) {
- mTargetView.setImageDrawable(info.displayIcon);
+ protected void onPostExecute(Drawable d) {
+ super.onPostExecute(d);
+ mTargetView.setImageDrawable(d);
}
}
diff --git a/core/java/com/android/internal/backup/LocalTransport.java b/core/java/com/android/internal/backup/LocalTransport.java
index e32a3a2..22d35f2 100644
--- a/core/java/com/android/internal/backup/LocalTransport.java
+++ b/core/java/com/android/internal/backup/LocalTransport.java
@@ -45,8 +45,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashSet;
-import static android.system.OsConstants.*;
+import static android.system.OsConstants.SEEK_CUR;
/**
* Backup transport for stashing stuff into a known location on disk, and
@@ -284,8 +283,10 @@ public class LocalTransport extends BackupTransport {
private int tearDownFullBackup() {
if (mSocket != null) {
try {
- mFullBackupOutputStream.flush();
- mFullBackupOutputStream.close();
+ if (mFullBackupOutputStream != null) {
+ mFullBackupOutputStream.flush();
+ mFullBackupOutputStream.close();
+ }
mSocketInputStream = null;
mFullTargetPackage = null;
mSocket.close();
@@ -296,6 +297,7 @@ public class LocalTransport extends BackupTransport {
return TRANSPORT_ERROR;
} finally {
mSocket = null;
+ mFullBackupOutputStream = null;
}
}
return TRANSPORT_OK;
@@ -311,6 +313,18 @@ public class LocalTransport extends BackupTransport {
}
@Override
+ public int checkFullBackupSize(long size) {
+ // Decline zero-size "backups"
+ final int result = (size > 0) ? TRANSPORT_OK : TRANSPORT_PACKAGE_REJECTED;
+ if (result != TRANSPORT_OK) {
+ if (DEBUG) {
+ Log.v(TAG, "Declining backup of size " + size);
+ }
+ }
+ return result;
+ }
+
+ @Override
public int performFullBackup(PackageInfo targetPackage, ParcelFileDescriptor socket) {
if (mSocket != null) {
Log.e(TAG, "Attempt to initiate full backup while one is in progress");
@@ -333,22 +347,14 @@ public class LocalTransport extends BackupTransport {
}
mFullTargetPackage = targetPackage.packageName;
- FileOutputStream tarstream;
- try {
- File tarball = tarballFile(mFullTargetPackage);
- tarstream = new FileOutputStream(tarball);
- } catch (FileNotFoundException e) {
- return TRANSPORT_ERROR;
- }
- mFullBackupOutputStream = new BufferedOutputStream(tarstream);
mFullBackupBuffer = new byte[4096];
return TRANSPORT_OK;
}
@Override
- public int sendBackupData(int numBytes) {
- if (mFullBackupBuffer == null) {
+ public int sendBackupData(final int numBytes) {
+ if (mSocket == null) {
Log.w(TAG, "Attempted sendBackupData before performFullBackup");
return TRANSPORT_ERROR;
}
@@ -356,16 +362,29 @@ public class LocalTransport extends BackupTransport {
if (numBytes > mFullBackupBuffer.length) {
mFullBackupBuffer = new byte[numBytes];
}
- while (numBytes > 0) {
+
+ if (mFullBackupOutputStream == null) {
+ FileOutputStream tarstream;
+ try {
+ File tarball = tarballFile(mFullTargetPackage);
+ tarstream = new FileOutputStream(tarball);
+ } catch (FileNotFoundException e) {
+ return TRANSPORT_ERROR;
+ }
+ mFullBackupOutputStream = new BufferedOutputStream(tarstream);
+ }
+
+ int bytesLeft = numBytes;
+ while (bytesLeft > 0) {
try {
- int nRead = mSocketInputStream.read(mFullBackupBuffer, 0, numBytes);
+ int nRead = mSocketInputStream.read(mFullBackupBuffer, 0, bytesLeft);
if (nRead < 0) {
// Something went wrong if we expect data but saw EOD
Log.w(TAG, "Unexpected EOD; failing backup");
return TRANSPORT_ERROR;
}
mFullBackupOutputStream.write(mFullBackupBuffer, 0, nRead);
- numBytes -= nRead;
+ bytesLeft -= nRead;
} catch (IOException e) {
Log.e(TAG, "Error handling backup data for " + mFullTargetPackage);
return TRANSPORT_ERROR;
diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java
index 6be6389..24b5d0d 100644
--- a/core/java/com/android/internal/logging/MetricsLogger.java
+++ b/core/java/com/android/internal/logging/MetricsLogger.java
@@ -26,9 +26,10 @@ import android.os.Build;
*/
public class MetricsLogger implements MetricsConstants {
// These constants are temporary, they should migrate to MetricsConstants.
- // next value is 145;
+ // next value is 146;
public static final int NOTIFICATION_ZEN_MODE_SCHEDULE_RULE = 144;
+ public static final int NOTIFICATION_ZEN_MODE_EXTERNAL_RULE = 145;
public static void visible(Context context, int category) throws IllegalArgumentException {
if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) {
diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java
index 7e6706c..1efa565 100644
--- a/core/java/com/android/internal/os/PowerProfile.java
+++ b/core/java/com/android/internal/os/PowerProfile.java
@@ -316,7 +316,7 @@ public class PowerProfile {
final Double[] values = (Double[]) data;
if (values.length > level && level >= 0) {
return values[level];
- } else if (level < 0) {
+ } else if (level < 0 || values.length == 0) {
return 0;
} else {
return values[values.length - 1];
diff --git a/core/java/com/android/internal/transition/ActionBarTransition.java b/core/java/com/android/internal/transition/ActionBarTransition.java
deleted file mode 100644
index c1065e7..0000000
--- a/core/java/com/android/internal/transition/ActionBarTransition.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2013 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 com.android.internal.transition;
-
-import android.transition.ChangeBounds;
-import android.transition.Fade;
-import android.transition.ChangeText;
-import android.transition.Transition;
-import android.transition.TransitionManager;
-import android.transition.TransitionSet;
-import android.view.ViewGroup;
-
-public class ActionBarTransition {
-
- private static boolean TRANSITIONS_ENABLED = false;
-
- private static final int TRANSITION_DURATION = 120; // ms
-
- private static final Transition sTransition;
-
- static {
- if (TRANSITIONS_ENABLED) {
- final ChangeText tc = new ChangeText();
- tc.setChangeBehavior(ChangeText.CHANGE_BEHAVIOR_OUT_IN);
- final TransitionSet inner = new TransitionSet();
- inner.addTransition(tc).addTransition(new ChangeBounds());
- final TransitionSet tg = new TransitionSet();
- tg.addTransition(new Fade(Fade.OUT)).addTransition(inner).
- addTransition(new Fade(Fade.IN));
- tg.setOrdering(TransitionSet.ORDERING_SEQUENTIAL);
- tg.setDuration(TRANSITION_DURATION);
- sTransition = tg;
- } else {
- sTransition = null;
- }
- }
-
- public static void beginDelayedTransition(ViewGroup sceneRoot) {
- if (TRANSITIONS_ENABLED) {
- TransitionManager.beginDelayedTransition(sceneRoot, sTransition);
- }
- }
-}
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 88436f8..6b781c3 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -49,7 +49,6 @@ import android.widget.Spinner;
import android.widget.SpinnerAdapter;
import android.widget.TextView;
import com.android.internal.R;
-import com.android.internal.transition.ActionBarTransition;
import com.android.internal.view.menu.ActionMenuItem;
import com.android.internal.view.menu.MenuBuilder;
import com.android.internal.view.menu.MenuItemImpl;
@@ -459,9 +458,6 @@ public class ActionBarView extends AbsActionBarView implements DecorToolbar {
public void setCustomView(View view) {
final boolean showCustom = (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0;
- if (showCustom) {
- ActionBarTransition.beginDelayedTransition(this);
- }
if (mCustomNavView != null && showCustom) {
removeView(mCustomNavView);
}
@@ -499,7 +495,6 @@ public class ActionBarView extends AbsActionBarView implements DecorToolbar {
}
private void setTitleImpl(CharSequence title) {
- ActionBarTransition.beginDelayedTransition(this);
mTitle = title;
if (mTitleView != null) {
mTitleView.setText(title);
@@ -519,7 +514,6 @@ public class ActionBarView extends AbsActionBarView implements DecorToolbar {
}
public void setSubtitle(CharSequence subtitle) {
- ActionBarTransition.beginDelayedTransition(this);
mSubtitle = subtitle;
if (mSubtitleView != null) {
mSubtitleView.setText(subtitle);
@@ -604,7 +598,6 @@ public class ActionBarView extends AbsActionBarView implements DecorToolbar {
mDisplayOptions = options;
if ((flagsChanged & DISPLAY_RELAYOUT_MASK) != 0) {
- ActionBarTransition.beginDelayedTransition(this);
if ((flagsChanged & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
final boolean setUp = (options & ActionBar.DISPLAY_HOME_AS_UP) != 0;
@@ -706,7 +699,6 @@ public class ActionBarView extends AbsActionBarView implements DecorToolbar {
public void setNavigationMode(int mode) {
final int oldMode = mNavigationMode;
if (mode != oldMode) {
- ActionBarTransition.beginDelayedTransition(this);
switch (oldMode) {
case ActionBar.NAVIGATION_MODE_LIST:
if (mListNavLayout != null) {
@@ -836,7 +828,6 @@ public class ActionBarView extends AbsActionBarView implements DecorToolbar {
}
}
- ActionBarTransition.beginDelayedTransition(this);
mUpGoerFive.addView(mTitleLayout);
if (mExpandedActionView != null ||
(TextUtils.isEmpty(mTitle) && TextUtils.isEmpty(mSubtitle))) {
@@ -1659,7 +1650,6 @@ public class ActionBarView extends AbsActionBarView implements DecorToolbar {
@Override
public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) {
- ActionBarTransition.beginDelayedTransition(ActionBarView.this);
mExpandedActionView = item.getActionView();
mExpandedHomeLayout.setIcon(mIcon.getConstantState().newDrawable(getResources()));
@@ -1688,7 +1678,6 @@ public class ActionBarView extends AbsActionBarView implements DecorToolbar {
@Override
public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) {
- ActionBarTransition.beginDelayedTransition(ActionBarView.this);
// Do this before detaching the actionview from the hierarchy, in case
// it needs to dismiss the soft keyboard, etc.
diff --git a/core/java/com/android/internal/widget/DialogViewAnimator.java b/core/java/com/android/internal/widget/DialogViewAnimator.java
new file mode 100644
index 0000000..bdfc1af
--- /dev/null
+++ b/core/java/com/android/internal/widget/DialogViewAnimator.java
@@ -0,0 +1,141 @@
+/*
+ * 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 com.android.internal.widget;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ViewAnimator;
+
+import java.util.ArrayList;
+
+/**
+ * ViewAnimator with a more reasonable handling of MATCH_PARENT.
+ */
+public class DialogViewAnimator extends ViewAnimator {
+ private final ArrayList<View> mMatchParentChildren = new ArrayList<>(1);
+
+ public DialogViewAnimator(Context context) {
+ super(context);
+ }
+
+ public DialogViewAnimator(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ final boolean measureMatchParentChildren =
+ MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY ||
+ MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY;
+
+ int maxHeight = 0;
+ int maxWidth = 0;
+ int childState = 0;
+
+ // First measure all children and record maximum dimensions where the
+ // spec isn't MATCH_PARENT.
+ final int count = getChildCount();
+ for (int i = 0; i < count; i++) {
+ final View child = getChildAt(i);
+ if (getMeasureAllChildren() || child.getVisibility() != GONE) {
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ final boolean matchWidth = lp.width == LayoutParams.MATCH_PARENT;
+ final boolean matchHeight = lp.height == LayoutParams.MATCH_PARENT;
+ if (measureMatchParentChildren && (matchWidth || matchHeight)) {
+ mMatchParentChildren.add(child);
+ }
+
+ measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
+
+ // Measured dimensions only count against the maximum
+ // dimensions if they're not MATCH_PARENT.
+ int state = 0;
+
+ if (measureMatchParentChildren && !matchWidth) {
+ maxWidth = Math.max(maxWidth, child.getMeasuredWidth()
+ + lp.leftMargin + lp.rightMargin);
+ state |= child.getMeasuredWidthAndState() & MEASURED_STATE_MASK;
+ }
+
+ if (measureMatchParentChildren && !matchHeight) {
+ maxHeight = Math.max(maxHeight, child.getMeasuredHeight()
+ + lp.topMargin + lp.bottomMargin);
+ state |= (child.getMeasuredHeightAndState() >> MEASURED_HEIGHT_STATE_SHIFT)
+ & (MEASURED_STATE_MASK >> MEASURED_HEIGHT_STATE_SHIFT);
+ }
+
+ childState = combineMeasuredStates(childState, state);
+ }
+ }
+
+ // Account for padding too.
+ maxWidth += getPaddingLeft() + getPaddingRight();
+ maxHeight += getPaddingTop() + getPaddingBottom();
+
+ // Check against our minimum height and width.
+ maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
+ maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
+
+ // Check against our foreground's minimum height and width.
+ final Drawable drawable = getForeground();
+ if (drawable != null) {
+ maxHeight = Math.max(maxHeight, drawable.getMinimumHeight());
+ maxWidth = Math.max(maxWidth, drawable.getMinimumWidth());
+ }
+
+ setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
+ resolveSizeAndState(maxHeight, heightMeasureSpec,
+ childState << MEASURED_HEIGHT_STATE_SHIFT));
+
+ // Measure remaining MATCH_PARENT children again using real dimensions.
+ final int matchCount = mMatchParentChildren.size();
+ for (int i = 0; i < matchCount; i++) {
+ final View child = mMatchParentChildren.get(i);
+ final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
+
+ final int childWidthMeasureSpec;
+ if (lp.width == LayoutParams.MATCH_PARENT) {
+ childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
+ getMeasuredWidth() - getPaddingLeft() - getPaddingRight()
+ - lp.leftMargin - lp.rightMargin,
+ MeasureSpec.EXACTLY);
+ } else {
+ childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
+ getPaddingLeft() + getPaddingRight() + lp.leftMargin + lp.rightMargin,
+ lp.width);
+ }
+
+ final int childHeightMeasureSpec;
+ if (lp.height == LayoutParams.MATCH_PARENT) {
+ childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
+ getMeasuredHeight() - getPaddingTop() - getPaddingBottom()
+ - lp.topMargin - lp.bottomMargin,
+ MeasureSpec.EXACTLY);
+ } else {
+ childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
+ getPaddingTop() + getPaddingBottom() + lp.topMargin + lp.bottomMargin,
+ lp.height);
+ }
+
+ child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+ }
+
+ mMatchParentChildren.clear();
+ }
+}
diff --git a/core/java/com/android/internal/widget/ViewPager.java b/core/java/com/android/internal/widget/ViewPager.java
index 8d66191..5c08daf 100644
--- a/core/java/com/android/internal/widget/ViewPager.java
+++ b/core/java/com/android/internal/widget/ViewPager.java
@@ -889,7 +889,7 @@ public class ViewPager extends ViewGroup {
}
}
- void populate() {
+ public void populate() {
populate(mCurItem);
}