summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/app/Activity.java26
-rw-r--r--core/java/android/app/ActivityManagerNative.java2
-rw-r--r--core/java/android/app/ActivityThread.java2
-rw-r--r--core/java/android/app/ApplicationPackageManager.java10
-rw-r--r--core/java/android/app/AssistContent.java36
-rw-r--r--core/java/android/app/AssistStructure.java63
-rw-r--r--core/java/android/app/BackStackRecord.java8
-rw-r--r--core/java/android/app/Fragment.java27
-rw-r--r--core/java/android/app/IActivityManager.java2
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java504
-rw-r--r--core/java/android/app/assist/AssistContent.aidl (renamed from core/java/android/app/AssistContent.aidl)2
-rw-r--r--core/java/android/app/assist/AssistContent.java44
-rw-r--r--core/java/android/app/assist/AssistStructure.aidl (renamed from core/java/android/app/AssistStructure.aidl)2
-rw-r--r--core/java/android/app/assist/AssistStructure.java56
-rw-r--r--core/java/android/app/usage/IUsageStatsManager.aidl1
-rw-r--r--core/java/android/app/usage/UsageStatsManager.java22
-rw-r--r--core/java/android/bluetooth/BluetoothAdapter.java48
-rw-r--r--core/java/android/bluetooth/BluetoothServerSocket.java20
-rw-r--r--core/java/android/bluetooth/BluetoothSocket.java28
-rw-r--r--core/java/android/bluetooth/SdpSapsRecord.java91
-rw-r--r--core/java/android/content/ContentResolver.java14
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl3
-rw-r--r--core/java/android/content/pm/PackageManager.java13
-rw-r--r--core/java/android/hardware/camera2/CameraCaptureSession.java11
-rw-r--r--core/java/android/hardware/camera2/CameraCharacteristics.java91
-rw-r--r--core/java/android/hardware/camera2/CameraDevice.java141
-rw-r--r--core/java/android/hardware/camera2/CameraManager.java18
-rw-r--r--core/java/android/hardware/camera2/CameraMetadata.java99
-rw-r--r--core/java/android/hardware/camera2/CaptureResult.java33
-rw-r--r--core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java6
-rw-r--r--core/java/android/hardware/camera2/impl/CameraDeviceImpl.java21
-rw-r--r--core/java/android/hardware/camera2/marshal/impl/MarshalQueryableHighSpeedVideoConfiguration.java6
-rw-r--r--core/java/android/hardware/camera2/params/HighSpeedVideoConfiguration.java25
-rw-r--r--core/java/android/net/IpReachabilityMonitor.java8
-rw-r--r--core/java/android/os/IDeviceIdleController.aidl4
-rw-r--r--core/java/android/os/PowerManager.java8
-rw-r--r--core/java/android/os/PowerManagerInternal.java2
-rw-r--r--core/java/android/provider/ContactsContract.java15
-rw-r--r--core/java/android/provider/MediaStore.java40
-rw-r--r--core/java/android/security/IKeystoreService.aidl5
-rw-r--r--core/java/android/security/keymaster/KeymasterDefs.java15
-rw-r--r--core/java/android/security/keymaster/OperationResult.java3
-rw-r--r--core/java/android/service/carrier/CarrierService.java10
-rw-r--r--core/java/android/service/media/CameraPrewarmService.java96
-rw-r--r--core/java/android/service/voice/IVoiceInteractionSession.aidl4
-rw-r--r--core/java/android/service/voice/VoiceInteractionSession.java43
-rw-r--r--core/java/android/text/Annotation.java10
-rw-r--r--core/java/android/text/DynamicLayout.java2
-rw-r--r--core/java/android/text/Hyphenator.java122
-rw-r--r--core/java/android/text/ParcelableSpan.java19
-rw-r--r--core/java/android/text/StaticLayout.java4
-rw-r--r--core/java/android/text/TextUtils.java11
-rw-r--r--core/java/android/text/style/AbsoluteSizeSpan.java10
-rw-r--r--core/java/android/text/style/AlignmentSpan.java15
-rw-r--r--core/java/android/text/style/BackgroundColorSpan.java10
-rw-r--r--core/java/android/text/style/BulletSpan.java10
-rw-r--r--core/java/android/text/style/EasyEditSpan.java10
-rw-r--r--core/java/android/text/style/ForegroundColorSpan.java12
-rw-r--r--core/java/android/text/style/LeadingMarginSpan.java10
-rw-r--r--core/java/android/text/style/LocaleSpan.java10
-rw-r--r--core/java/android/text/style/QuoteSpan.java10
-rw-r--r--core/java/android/text/style/RelativeSizeSpan.java10
-rw-r--r--core/java/android/text/style/ScaleXSpan.java10
-rw-r--r--core/java/android/text/style/SpellCheckSpan.java10
-rw-r--r--core/java/android/text/style/StrikethroughSpan.java10
-rw-r--r--core/java/android/text/style/StyleSpan.java10
-rw-r--r--core/java/android/text/style/SubscriptSpan.java10
-rw-r--r--core/java/android/text/style/SuggestionRangeSpan.java10
-rw-r--r--core/java/android/text/style/SuggestionSpan.java10
-rw-r--r--core/java/android/text/style/SuperscriptSpan.java10
-rw-r--r--core/java/android/text/style/TextAppearanceSpan.java10
-rw-r--r--core/java/android/text/style/TtsSpan.java10
-rw-r--r--core/java/android/text/style/TypefaceSpan.java10
-rw-r--r--core/java/android/text/style/URLSpan.java10
-rw-r--r--core/java/android/text/style/UnderlineSpan.java10
-rw-r--r--core/java/android/util/DisplayMetrics.java8
-rw-r--r--core/java/android/util/StateSet.java7
-rw-r--r--core/java/android/view/AccessibilityInteractionController.java51
-rw-r--r--core/java/android/view/View.java72
-rw-r--r--core/java/android/view/ViewGroup.java6
-rw-r--r--core/java/android/view/ViewStructure.java1
-rw-r--r--core/java/android/view/WindowInsets.java2
-rw-r--r--core/java/android/view/WindowManager.java1
-rw-r--r--core/java/android/view/WindowManagerPolicy.java7
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java4
-rw-r--r--core/java/android/view/inputmethod/InputMethodSubtype.java16
-rw-r--r--core/java/android/view/textservice/SpellCheckerSession.java2
-rw-r--r--core/java/android/widget/AbsListView.java5
-rw-r--r--core/java/android/widget/ArrayAdapter.java22
-rw-r--r--core/java/android/widget/CursorAdapter.java2
-rwxr-xr-xcore/java/android/widget/DatePickerCalendarDelegate.java12
-rw-r--r--core/java/android/widget/Editor.java98
-rw-r--r--core/java/android/widget/HorizontalScrollView.java24
-rw-r--r--core/java/android/widget/NumberPicker.java44
-rw-r--r--core/java/android/widget/SimpleAdapter.java9
-rw-r--r--core/java/android/widget/Spinner.java38
-rw-r--r--core/java/android/widget/TabHost.java25
-rw-r--r--core/java/android/widget/TextView.java4
-rw-r--r--core/java/android/widget/ThemedSpinnerAdapter.java53
-rw-r--r--core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java33
-rw-r--r--core/java/com/android/internal/inputmethod/InputMethodUtils.java10
-rw-r--r--core/java/com/android/internal/policy/PhoneWindow.java8
-rw-r--r--core/java/com/android/internal/widget/FloatingToolbar.java99
-rw-r--r--core/java/com/android/internal/widget/LockPatternUtils.java18
104 files changed, 2146 insertions, 668 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 49f5099..90567c7 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -38,6 +38,7 @@ import com.android.internal.app.ToolbarActionBar;
import android.annotation.SystemApi;
import android.app.admin.DevicePolicyManager;
+import android.app.assist.AssistContent;
import android.content.ComponentCallbacks2;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -3746,6 +3747,7 @@ public class Activity extends ContextThemeWrapper
*
* @see #onRequestPermissionsResult(int, String[], int[])
* @see #checkSelfPermission(String)
+ * @see #shouldShowRequestPermissionRationale(String)
*/
public final void requestPermissions(@NonNull String[] permissions, int requestCode) {
Intent intent = getPackageManager().buildRequestPermissionsIntent(permissions);
@@ -3770,6 +3772,30 @@ public class Activity extends ContextThemeWrapper
}
/**
+ * Gets whether you should show UI with rationale for requesting a permission.
+ * You should do this only if you do not have the permission and the context in
+ * which the permission is requested does not clearly communicate to the user
+ * what would be the benefit from granting this permission.
+ * <p>
+ * For example, if you write a camera app, requesting the camera permission
+ * would be expected by the user and no rationale for why it is requested is
+ * needed. If however, the app needs location for tagging photos then a non-tech
+ * savvy user may wonder how location is related to taking photos. In this case
+ * you may choose to show UI with rationale of requesting this permission.
+ * </p>
+ *
+ * @param permission A permission your app wants to request.
+ * @return Whether you can show permission rationale UI.
+ *
+ * @see #checkSelfPermission(String)
+ * @see #requestPermissions(String[], int)
+ * @see #onRequestPermissionsResult(int, String[], int[])
+ */
+ public boolean shouldShowRequestPermissionRationale(@NonNull String permission) {
+ return getPackageManager().shouldShowRequestPermissionRationale(permission);
+ }
+
+ /**
* Same as calling {@link #startActivityForResult(Intent, int, Bundle)}
* with no options.
*
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index e4def1e..b6cec60 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -17,6 +17,8 @@
package android.app;
import android.app.ActivityManager.StackInfo;
+import android.app.assist.AssistContent;
+import android.app.assist.AssistStructure;
import android.content.ComponentName;
import android.content.IIntentReceiver;
import android.content.IIntentSender;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 2a98b6c..3224d41 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -16,6 +16,8 @@
package android.app;
+import android.app.assist.AssistContent;
+import android.app.assist.AssistStructure;
import android.app.backup.BackupAgent;
import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks2;
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 04f6430..41e3db8 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -486,6 +486,16 @@ final class ApplicationPackageManager extends PackageManager {
}
@Override
+ public boolean shouldShowRequestPermissionRationale(String permission) {
+ try {
+ return mPM.shouldShowRequestPermissionRationale(permission,
+ mContext.getPackageName(), mContext.getUserId());
+ } catch (RemoteException e) {
+ throw new RuntimeException("Package manager has died", e);
+ }
+ }
+
+ @Override
public int checkSignatures(String pkg1, String pkg2) {
try {
return mPM.checkSignatures(pkg1, pkg2);
diff --git a/core/java/android/app/AssistContent.java b/core/java/android/app/AssistContent.java
index f271af1..4cb89a8 100644
--- a/core/java/android/app/AssistContent.java
+++ b/core/java/android/app/AssistContent.java
@@ -26,9 +26,11 @@ import android.os.Parcelable;
/**
* Holds information about the content an application is viewing, to hand to an
* assistant at the user's request. This is filled in by
- * {@link Activity#onProvideAssistContent Activity.onProvideAssistContent}.
+ * {@link android.app.Activity#onProvideAssistContent Activity.onProvideAssistContent}.
+ * @deprecated use {@link android.app.assist.AssistContent}.
*/
-public class AssistContent implements Parcelable {
+@Deprecated
+public class AssistContent {
private Intent mIntent;
private ClipData mClipData;
private Uri mUri;
@@ -36,16 +38,16 @@ public class AssistContent implements Parcelable {
/**
* @hide
* Key name this data structure is stored in the Bundle generated by
- * {@link Activity#onProvideAssistData}.
+ * {@link android.app.Activity#onProvideAssistData}.
*/
public static final String ASSIST_KEY = "android:assist_content";
/**
* @hide
* Retrieve the framework-generated AssistContent that is stored within
- * the Bundle filled in by {@link Activity#onProvideAssistContent}.
+ * the Bundle filled in by {@link android.app.Activity#onProvideAssistContent}.
*/
- public static AssistContent getAssistContent(Bundle assistBundle) {
+ public static android.app.assist.AssistContent getAssistContent(Bundle assistBundle) {
return assistBundle.getParcelable(ASSIST_KEY);
}
@@ -71,6 +73,7 @@ public class AssistContent implements Parcelable {
/**
* Return the current {@link #setIntent}, which you can modify in-place.
+ * @hide
*/
public Intent getIntent() {
return mIntent;
@@ -116,7 +119,8 @@ public class AssistContent implements Parcelable {
return mUri;
}
- AssistContent(Parcel in) {
+ /** @hide */
+ public AssistContent(Parcel in) {
if (in.readInt() != 0) {
mIntent = Intent.CREATOR.createFromParcel(in);
}
@@ -128,13 +132,8 @@ public class AssistContent implements Parcelable {
}
}
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
+ /** @hide */
+ public void writeToParcelInternal(Parcel dest, int flags) {
if (mIntent != null) {
dest.writeInt(1);
mIntent.writeToParcel(dest, flags);
@@ -154,15 +153,4 @@ public class AssistContent implements Parcelable {
dest.writeInt(0);
}
}
-
- public static final Parcelable.Creator<AssistContent> CREATOR
- = new Parcelable.Creator<AssistContent>() {
- public AssistContent createFromParcel(Parcel in) {
- return new AssistContent(in);
- }
-
- public AssistContent[] newArray(int size) {
- return new AssistContent[size];
- }
- };
}
diff --git a/core/java/android/app/AssistStructure.java b/core/java/android/app/AssistStructure.java
index ca47a5e..ef7fde4 100644
--- a/core/java/android/app/AssistStructure.java
+++ b/core/java/android/app/AssistStructure.java
@@ -17,9 +17,7 @@
package android.app;
import android.content.ComponentName;
-import android.graphics.Paint;
import android.graphics.Rect;
-import android.graphics.Typeface;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
@@ -29,7 +27,6 @@ import android.os.PooledStringReader;
import android.os.PooledStringWriter;
import android.os.RemoteException;
import android.os.SystemClock;
-import android.text.TextPaint;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
@@ -42,19 +39,22 @@ import java.util.ArrayList;
/**
* Assist data automatically created by the platform's implementation
- * of {@link Activity#onProvideAssistData}.
+ * of {@link android.app.Activity#onProvideAssistData}.
+ * @deprecated use {@link android.app.assist.AssistStructure}.
*/
-final public class AssistStructure implements Parcelable {
+@Deprecated
+public class AssistStructure {
static final String TAG = "AssistStructure";
/**
* @hide
* Key name this data structure is stored in the Bundle generated by
- * {@link Activity#onProvideAssistData}.
+ * {@link android.app.Activity#onProvideAssistData}.
*/
public static final String ASSIST_KEY = "android:assist_structure";
- boolean mHaveData;
+ /** @hide */
+ public boolean mHaveData;
ComponentName mActivityComponent;
@@ -62,15 +62,18 @@ final public class AssistStructure implements Parcelable {
final ArrayList<ViewNodeBuilder> mPendingAsyncChildren = new ArrayList<>();
- SendChannel mSendChannel;
- IBinder mReceiveChannel;
+ /** @hide */
+ public SendChannel mSendChannel;
+ /** @hide */
+ public IBinder mReceiveChannel;
Rect mTmpRect = new Rect();
static final int TRANSACTION_XFER = Binder.FIRST_CALL_TRANSACTION+1;
static final String DESCRIPTOR = "android.app.AssistStructure";
- final class SendChannel extends Binder {
+ /** @hide */
+ public final class SendChannel extends Binder {
@Override protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
if (code == TRANSACTION_XFER) {
@@ -702,7 +705,8 @@ final public class AssistStructure implements Parcelable {
}
}
- AssistStructure(Activity activity) {
+ /** @hide */
+ public AssistStructure(Activity activity) {
mHaveData = true;
mActivityComponent = activity.getComponentName();
ArrayList<ViewRootImpl> views = WindowManagerGlobal.getInstance().getRootViews(
@@ -713,12 +717,13 @@ final public class AssistStructure implements Parcelable {
}
}
- AssistStructure() {
+ public AssistStructure() {
mHaveData = true;
mActivityComponent = null;
}
- AssistStructure(Parcel in) {
+ /** @hide */
+ public AssistStructure(Parcel in) {
mReceiveChannel = in.readStrongBinder();
}
@@ -792,7 +797,7 @@ final public class AssistStructure implements Parcelable {
* Retrieve the framework-generated AssistStructure that is stored within
* the Bundle filled in by {@link Activity#onProvideAssistData}.
*/
- public static AssistStructure getAssistStructure(Bundle assistBundle) {
+ public static android.app.assist.AssistStructure getAssistStructure(Bundle assistBundle) {
return assistBundle.getParcelable(ASSIST_KEY);
}
@@ -812,16 +817,13 @@ final public class AssistStructure implements Parcelable {
/**
* Return one of the windows in the assist data.
* @param index Which window to retrieve, may be 0 to {@link #getWindowNodeCount()}-1.
+ * @hide
*/
public WindowNode getWindowNodeAt(int index) {
ensureData();
return mWindowNodes.get(index);
}
- public int describeContents() {
- return 0;
- }
-
/** @hide */
public void ensureData() {
if (mHaveData) {
@@ -880,29 +882,4 @@ final public class AssistStructure implements Parcelable {
}
//dump();
}
-
- public void writeToParcel(Parcel out, int flags) {
- if (mHaveData) {
- // This object holds its data. We want to write a send channel that the
- // other side can use to retrieve that data.
- if (mSendChannel == null) {
- mSendChannel = new SendChannel();
- }
- out.writeStrongBinder(mSendChannel);
- } else {
- // This object doesn't hold its data, so just propagate along its receive channel.
- out.writeStrongBinder(mReceiveChannel);
- }
- }
-
- public static final Parcelable.Creator<AssistStructure> CREATOR
- = new Parcelable.Creator<AssistStructure>() {
- public AssistStructure createFromParcel(Parcel in) {
- return new AssistStructure(in);
- }
-
- public AssistStructure[] newArray(int size) {
- return new AssistStructure[size];
- }
- };
}
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index 1fb88a9..02e26a5 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -1107,6 +1107,7 @@ final class BackStackRecord extends FragmentTransaction implements
}
if (enterTransition != null) {
+ enterTransition.removeTarget(state.nonExistentView);
View view = inFragment.getView();
if (view != null) {
view.captureTransitioningViews(enteringViews);
@@ -1115,7 +1116,6 @@ final class BackStackRecord extends FragmentTransaction implements
}
enteringViews.add(state.nonExistentView);
// We added this earlier to prevent any views being targeted.
- enterTransition.removeTarget(state.nonExistentView);
addTargets(enterTransition, enteringViews);
}
setSharedElementEpicenter(enterTransition, state);
@@ -1170,7 +1170,7 @@ final class BackStackRecord extends FragmentTransaction implements
Transition exitTransition, Transition sharedElementTransition, Fragment inFragment,
boolean isBack) {
boolean overlap = true;
- if (enterTransition != null && exitTransition != null) {
+ if (enterTransition != null && exitTransition != null && inFragment != null) {
overlap = isBack ? inFragment.getAllowReturnTransitionOverlap() :
inFragment.getAllowEnterTransitionOverlap();
}
@@ -1638,7 +1638,7 @@ final class BackStackRecord extends FragmentTransaction implements
private void setBackNameOverrides(TransitionState state, ArrayMap<String, View> namedViews,
boolean isEnd) {
- int count = mSharedElementTargetNames.size();
+ int count = mSharedElementTargetNames == null ? 0 : mSharedElementTargetNames.size();
for (int i = 0; i < count; i++) {
String source = mSharedElementSourceNames.get(i);
String originalTarget = mSharedElementTargetNames.get(i);
@@ -1656,7 +1656,7 @@ final class BackStackRecord extends FragmentTransaction implements
private void setNameOverrides(TransitionState state, ArrayMap<String, View> namedViews,
boolean isEnd) {
- int count = namedViews.size();
+ int count = namedViews == null ? 0 : namedViews.size();
for (int i = 0; i < count; i++) {
String source = namedViews.keyAt(i);
String target = namedViews.valueAt(i).getTransitionName();
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 40c5c64..26d4fd4 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -1223,6 +1223,33 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
}
/**
+ * Gets whether you should show UI with rationale for requesting a permission.
+ * You should do this only if you do not have the permission and the context in
+ * which the permission is requested does not clearly communicate to the user
+ * what would be the benefit from granting this permission.
+ * <p>
+ * For example, if you write a camera app, requesting the camera permission
+ * would be expected by the user and no rationale for why it is requested is
+ * needed. If however, the app needs location for tagging photos then a non-tech
+ * savvy user may wonder how location is related to taking photos. In this case
+ * you may choose to show UI with rationale of requesting this permission.
+ * </p>
+ *
+ * @param permission A permission your app wants to request.
+ * @return Whether you can show permission rationale UI.
+ *
+ * @see Context#checkSelfPermission(String)
+ * @see #requestPermissions(String[], int)
+ * @see #onRequestPermissionsResult(int, String[], int[])
+ */
+ public boolean shouldShowRequestPermissionRationale(@NonNull String permission) {
+ if (mHost != null) {
+ mHost.getContext().getPackageManager().shouldShowRequestPermissionRationale(permission);
+ }
+ return false;
+ }
+
+ /**
* @hide Hack so that DialogFragment can make its Dialog before creating
* its views, and the view construction can use the dialog's context for
* inflation. Maybe this should become a public API. Note sure.
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 0a425ae..249cdb2 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -19,6 +19,8 @@ package android.app;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityManager.RunningServiceInfo;
import android.app.ActivityManager.StackInfo;
+import android.app.assist.AssistContent;
+import android.app.assist.AssistStructure;
import android.content.ComponentName;
import android.content.ContentProviderNative;
import android.content.IContentProvider;
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 978b4bc..55eaf27 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -16,6 +16,8 @@
package android.app.admin;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
@@ -76,7 +78,7 @@ import java.util.List;
* <h3>Developer Guides</h3>
* <p>For more information about managing policies for device administration, read the
* <a href="{@docRoot}guide/topics/admin/device-admin.html">Device Administration</a>
- * developer guide.</p>
+ * developer guide.
* </div>
*/
public class DevicePolicyManager {
@@ -122,15 +124,45 @@ public class DevicePolicyManager {
*
* <p> If provisioning fails, the managedProfile is removed so the device returns to its
* previous state.
- *
- * <p>Input: Nothing.</p>
- * <p>Output: Nothing</p>
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_PROVISION_MANAGED_PROFILE
= "android.app.action.PROVISION_MANAGED_PROFILE";
/**
+ * Activity action: Starts the provisioning flow which sets up a managed device.
+ * Must be started with {@link android.app.Activity#startActivityForResult(Intent, int)}.
+ *
+ * <p> During device owner provisioning a device admin app is set as the owner of the device.
+ * A device owner has full control over the device. The device owner can not be modified by the
+ * user.
+ *
+ * <p> A typical use case would be a device that is owned by a company, but used by either an
+ * employee or client.
+ *
+ * <p> An intent with this action can be sent only on an unprovisioned device.
+ * It is possible to check if the device is provisioned or not by looking at
+ * {@link android.provider.Settings.Global#DEVICE_PROVISIONED}
+ *
+ * The intent contains the following extras:
+ * <ul>
+ * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME}</li>
+ * <li>{@link #EXTRA_PROVISIONING_SKIP_ENCRYPTION}, optional</li>
+ * <li>{@link #EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED}, optional</li>
+ * </ul>
+ *
+ * <p> When device owner provisioning has completed, an intent of the type
+ * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE} is broadcast to the
+ * device owner.
+ *
+ * <p> If provisioning fails, the device is factory reset.
+ *
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_PROVISION_MANAGED_DEVICE
+ = "android.app.action.PROVISION_MANAGED_DEVICE";
+
+ /**
* A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that allows
* a mobile device management application that starts managed profile provisioning to pass data
* to itself on the managed profile when provisioning completes. The mobile device management
@@ -155,7 +187,7 @@ public class DevicePolicyManager {
* message containing an NFC record with MIME type {@link #MIME_TYPE_PROVISIONING_NFC}.
*
* <p> When this extra is set, the application must have exactly one device admin receiver.
- * This receiver will be set as the profile or device owner and active admin.</p>
+ * This receiver will be set as the profile or device owner and active admin.
* @see DeviceAdminReceiver
* @deprecated Use {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME}. This extra is still
@@ -170,11 +202,13 @@ public class DevicePolicyManager {
* application that will be set as the profile owner or device owner and active admin.
*
* <p>If an application starts provisioning directly via an intent with action
- * {@link #ACTION_PROVISION_MANAGED_PROFILE} the package name of this component has to match the
- * package name of the application that started provisioning.
+ * {@link #ACTION_PROVISION_MANAGED_PROFILE} or
+ * {@link #ACTION_PROVISION_MANAGED_DEVICE} the package name of this
+ * component has to match the package name of the application that started provisioning.
*
* <p>This component is set as device owner and active admin when device owner provisioning is
- * started by an NFC message containing an NFC record with MIME type
+ * started by an intent with action {@link #ACTION_PROVISION_MANAGED_DEVICE} or by an NFC
+ * message containing an NFC record with MIME type
* {@link #MIME_TYPE_PROVISIONING_NFC_V2}. For the NFC record, the component name should be
* flattened to a string, via {@link ComponentName#flattenToShortString()}.
*
@@ -212,10 +246,10 @@ public class DevicePolicyManager {
/**
* A Boolean extra that can be used by the mobile device management application to skip the
- * disabling of system apps during provisioning when set to <code>true</code>.
+ * disabling of system apps during provisioning when set to {@code true}.
*
- * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
- * provisioning via an NFC bump.
+ * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} or an intent with action
+ * {@link #ACTION_PROVISION_MANAGED_DEVICE} that starts device owner provisioning.
*/
public static final String EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED =
"android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED";
@@ -415,8 +449,8 @@ public class DevicePolicyManager {
* A boolean extra indicating whether device encryption can be skipped as part of Device Owner
* provisioning.
*
- * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner
- * provisioning via an NFC bump.
+ * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} or an intent with action
+ * {@link #ACTION_PROVISION_MANAGED_DEVICE} that starts device owner provisioning.
*/
public static final String EXTRA_PROVISIONING_SKIP_ENCRYPTION =
"android.app.extra.PROVISIONING_SKIP_ENCRYPTION";
@@ -610,8 +644,7 @@ public class DevicePolicyManager {
*
* <p>During device owner provisioning a device admin app is set as the owner of the device.
* A device owner has full control over the device. The device owner can not be modified by the
- * user and the only way of resetting the device is if the device owner app calls a factory
- * reset.
+ * user.
*
* <p> A typical use case would be a device that is owned by a company, but used by either an
* employee or client.
@@ -644,9 +677,6 @@ public class DevicePolicyManager {
*
* <p>
* If provisioning fails, the device is factory reset.
- *
- * <p>Input: Nothing.</p>
- * <p>Output: Nothing</p>
*/
public static final String MIME_TYPE_PROVISIONING_NFC_V2
= "application/com.android.managedprovisioning.v2";
@@ -847,18 +877,18 @@ public class DevicePolicyManager {
* Return true if the given administrator component is currently
* active (enabled) in the system.
*/
- public boolean isAdminActive(ComponentName who) {
- return isAdminActiveAsUser(who, UserHandle.myUserId());
+ public boolean isAdminActive(@NonNull ComponentName admin) {
+ return isAdminActiveAsUser(admin, UserHandle.myUserId());
}
/**
* @see #isAdminActive(ComponentName)
* @hide
*/
- public boolean isAdminActiveAsUser(ComponentName who, int userId) {
+ public boolean isAdminActiveAsUser(@NonNull ComponentName admin, int userId) {
if (mService != null) {
try {
- return mService.isAdminActive(who, userId);
+ return mService.isAdminActive(admin, userId);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -870,10 +900,10 @@ public class DevicePolicyManager {
* for the user.
* @hide
*/
- public boolean isRemovingAdmin(ComponentName who, int userId) {
+ public boolean isRemovingAdmin(@NonNull ComponentName admin, int userId) {
if (mService != null) {
try {
- return mService.isRemovingAdmin(who, userId);
+ return mService.isRemovingAdmin(admin, userId);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -883,8 +913,8 @@ public class DevicePolicyManager {
/**
- * Return a list of all currently active device administrator's component
- * names. Note that if there are no administrators than null may be
+ * Return a list of all currently active device administrators' component
+ * names. If there are no administrators {@code null} may be
* returned.
*/
public List<ComponentName> getActiveAdmins() {
@@ -928,10 +958,10 @@ public class DevicePolicyManager {
* try to remove someone else's component, a security exception will be
* thrown.
*/
- public void removeActiveAdmin(ComponentName who) {
+ public void removeActiveAdmin(@NonNull ComponentName admin) {
if (mService != null) {
try {
- mService.removeActiveAdmin(who, UserHandle.myUserId());
+ mService.removeActiveAdmin(admin, UserHandle.myUserId());
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -940,14 +970,14 @@ public class DevicePolicyManager {
/**
* Returns true if an administrator has been granted a particular device policy. This can
- * be used to check if the administrator was activated under an earlier set of policies,
+ * be used to check whether the administrator was activated under an earlier set of policies,
* but requires additional policies after an upgrade.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with. Must be
* an active administrator, or an exception will be thrown.
* @param usesPolicy Which uses-policy to check, as defined in {@link DeviceAdminInfo}.
*/
- public boolean hasGrantedPolicy(ComponentName admin, int usesPolicy) {
+ public boolean hasGrantedPolicy(@NonNull ComponentName admin, int usesPolicy) {
if (mService != null) {
try {
return mService.hasGrantedPolicy(admin, usesPolicy, UserHandle.myUserId());
@@ -1048,7 +1078,7 @@ public class DevicePolicyManager {
* {@link #PASSWORD_QUALITY_ALPHABETIC}, {@link #PASSWORD_QUALITY_ALPHANUMERIC}
* or {@link #PASSWORD_QUALITY_COMPLEX}.
*/
- public void setPasswordQuality(ComponentName admin, int quality) {
+ public void setPasswordQuality(@NonNull ComponentName admin, int quality) {
if (mService != null) {
try {
mService.setPasswordQuality(admin, quality);
@@ -1061,15 +1091,15 @@ public class DevicePolicyManager {
/**
* Retrieve the current minimum password quality for all admins of this user
* and its profiles or a particular one.
- * @param admin The name of the admin component to check, or null to aggregate
+ * @param admin The name of the admin component to check, or {@code null} to aggregate
* all admins.
*/
- public int getPasswordQuality(ComponentName admin) {
+ public int getPasswordQuality(@Nullable ComponentName admin) {
return getPasswordQuality(admin, UserHandle.myUserId());
}
/** @hide per-user version */
- public int getPasswordQuality(ComponentName admin, int userHandle) {
+ public int getPasswordQuality(@Nullable ComponentName admin, int userHandle) {
if (mService != null) {
try {
return mService.getPasswordQuality(admin, userHandle);
@@ -1101,7 +1131,7 @@ public class DevicePolicyManager {
* @param length The new desired minimum password length. A value of 0
* means there is no restriction.
*/
- public void setPasswordMinimumLength(ComponentName admin, int length) {
+ public void setPasswordMinimumLength(@NonNull ComponentName admin, int length) {
if (mService != null) {
try {
mService.setPasswordMinimumLength(admin, length);
@@ -1114,15 +1144,15 @@ public class DevicePolicyManager {
/**
* Retrieve the current minimum password length for all admins of this
* user and its profiles or a particular one.
- * @param admin The name of the admin component to check, or null to aggregate
+ * @param admin The name of the admin component to check, or {@code null} to aggregate
* all admins.
*/
- public int getPasswordMinimumLength(ComponentName admin) {
+ public int getPasswordMinimumLength(@Nullable ComponentName admin) {
return getPasswordMinimumLength(admin, UserHandle.myUserId());
}
/** @hide per-user version */
- public int getPasswordMinimumLength(ComponentName admin, int userHandle) {
+ public int getPasswordMinimumLength(@Nullable ComponentName admin, int userHandle) {
if (mService != null) {
try {
return mService.getPasswordMinimumLength(admin, userHandle);
@@ -1155,7 +1185,7 @@ public class DevicePolicyManager {
* required in the password. A value of 0 means there is no
* restriction.
*/
- public void setPasswordMinimumUpperCase(ComponentName admin, int length) {
+ public void setPasswordMinimumUpperCase(@NonNull ComponentName admin, int length) {
if (mService != null) {
try {
mService.setPasswordMinimumUpperCase(admin, length);
@@ -1173,17 +1203,17 @@ public class DevicePolicyManager {
* and only applies when the password quality is
* {@link #PASSWORD_QUALITY_COMPLEX}.
*
- * @param admin The name of the admin component to check, or null to
+ * @param admin The name of the admin component to check, or {@code null} to
* aggregate all admins.
* @return The minimum number of upper case letters required in the
* password.
*/
- public int getPasswordMinimumUpperCase(ComponentName admin) {
+ public int getPasswordMinimumUpperCase(@Nullable ComponentName admin) {
return getPasswordMinimumUpperCase(admin, UserHandle.myUserId());
}
/** @hide per-user version */
- public int getPasswordMinimumUpperCase(ComponentName admin, int userHandle) {
+ public int getPasswordMinimumUpperCase(@Nullable ComponentName admin, int userHandle) {
if (mService != null) {
try {
return mService.getPasswordMinimumUpperCase(admin, userHandle);
@@ -1216,7 +1246,7 @@ public class DevicePolicyManager {
* required in the password. A value of 0 means there is no
* restriction.
*/
- public void setPasswordMinimumLowerCase(ComponentName admin, int length) {
+ public void setPasswordMinimumLowerCase(@NonNull ComponentName admin, int length) {
if (mService != null) {
try {
mService.setPasswordMinimumLowerCase(admin, length);
@@ -1234,17 +1264,17 @@ public class DevicePolicyManager {
* and only applies when the password quality is
* {@link #PASSWORD_QUALITY_COMPLEX}.
*
- * @param admin The name of the admin component to check, or null to
+ * @param admin The name of the admin component to check, or {@code null} to
* aggregate all admins.
* @return The minimum number of lower case letters required in the
* password.
*/
- public int getPasswordMinimumLowerCase(ComponentName admin) {
+ public int getPasswordMinimumLowerCase(@Nullable ComponentName admin) {
return getPasswordMinimumLowerCase(admin, UserHandle.myUserId());
}
/** @hide per-user version */
- public int getPasswordMinimumLowerCase(ComponentName admin, int userHandle) {
+ public int getPasswordMinimumLowerCase(@Nullable ComponentName admin, int userHandle) {
if (mService != null) {
try {
return mService.getPasswordMinimumLowerCase(admin, userHandle);
@@ -1276,7 +1306,7 @@ public class DevicePolicyManager {
* @param length The new desired minimum number of letters required in the
* password. A value of 0 means there is no restriction.
*/
- public void setPasswordMinimumLetters(ComponentName admin, int length) {
+ public void setPasswordMinimumLetters(@NonNull ComponentName admin, int length) {
if (mService != null) {
try {
mService.setPasswordMinimumLetters(admin, length);
@@ -1293,16 +1323,16 @@ public class DevicePolicyManager {
* and only applies when the password quality is
* {@link #PASSWORD_QUALITY_COMPLEX}.
*
- * @param admin The name of the admin component to check, or null to
+ * @param admin The name of the admin component to check, or {@code null} to
* aggregate all admins.
* @return The minimum number of letters required in the password.
*/
- public int getPasswordMinimumLetters(ComponentName admin) {
+ public int getPasswordMinimumLetters(@Nullable ComponentName admin) {
return getPasswordMinimumLetters(admin, UserHandle.myUserId());
}
/** @hide per-user version */
- public int getPasswordMinimumLetters(ComponentName admin, int userHandle) {
+ public int getPasswordMinimumLetters(@Nullable ComponentName admin, int userHandle) {
if (mService != null) {
try {
return mService.getPasswordMinimumLetters(admin, userHandle);
@@ -1334,7 +1364,7 @@ public class DevicePolicyManager {
* @param length The new desired minimum number of numerical digits required
* in the password. A value of 0 means there is no restriction.
*/
- public void setPasswordMinimumNumeric(ComponentName admin, int length) {
+ public void setPasswordMinimumNumeric(@NonNull ComponentName admin, int length) {
if (mService != null) {
try {
mService.setPasswordMinimumNumeric(admin, length);
@@ -1352,16 +1382,16 @@ public class DevicePolicyManager {
* and only applies when the password quality is
* {@link #PASSWORD_QUALITY_COMPLEX}.
*
- * @param admin The name of the admin component to check, or null to
+ * @param admin The name of the admin component to check, or {@code null} to
* aggregate all admins.
* @return The minimum number of numerical digits required in the password.
*/
- public int getPasswordMinimumNumeric(ComponentName admin) {
+ public int getPasswordMinimumNumeric(@Nullable ComponentName admin) {
return getPasswordMinimumNumeric(admin, UserHandle.myUserId());
}
/** @hide per-user version */
- public int getPasswordMinimumNumeric(ComponentName admin, int userHandle) {
+ public int getPasswordMinimumNumeric(@Nullable ComponentName admin, int userHandle) {
if (mService != null) {
try {
return mService.getPasswordMinimumNumeric(admin, userHandle);
@@ -1393,7 +1423,7 @@ public class DevicePolicyManager {
* @param length The new desired minimum number of symbols required in the
* password. A value of 0 means there is no restriction.
*/
- public void setPasswordMinimumSymbols(ComponentName admin, int length) {
+ public void setPasswordMinimumSymbols(@NonNull ComponentName admin, int length) {
if (mService != null) {
try {
mService.setPasswordMinimumSymbols(admin, length);
@@ -1410,16 +1440,16 @@ public class DevicePolicyManager {
* and only applies when the password quality is
* {@link #PASSWORD_QUALITY_COMPLEX}.
*
- * @param admin The name of the admin component to check, or null to
+ * @param admin The name of the admin component to check, or {@code null} to
* aggregate all admins.
* @return The minimum number of symbols required in the password.
*/
- public int getPasswordMinimumSymbols(ComponentName admin) {
+ public int getPasswordMinimumSymbols(@Nullable ComponentName admin) {
return getPasswordMinimumSymbols(admin, UserHandle.myUserId());
}
/** @hide per-user version */
- public int getPasswordMinimumSymbols(ComponentName admin, int userHandle) {
+ public int getPasswordMinimumSymbols(@Nullable ComponentName admin, int userHandle) {
if (mService != null) {
try {
return mService.getPasswordMinimumSymbols(admin, userHandle);
@@ -1451,7 +1481,7 @@ public class DevicePolicyManager {
* @param length The new desired minimum number of letters required in the
* password. A value of 0 means there is no restriction.
*/
- public void setPasswordMinimumNonLetter(ComponentName admin, int length) {
+ public void setPasswordMinimumNonLetter(@NonNull ComponentName admin, int length) {
if (mService != null) {
try {
mService.setPasswordMinimumNonLetter(admin, length);
@@ -1469,16 +1499,16 @@ public class DevicePolicyManager {
* and only applies when the password quality is
* {@link #PASSWORD_QUALITY_COMPLEX}.
*
- * @param admin The name of the admin component to check, or null to
+ * @param admin The name of the admin component to check, or {@code null} to
* aggregate all admins.
* @return The minimum number of letters required in the password.
*/
- public int getPasswordMinimumNonLetter(ComponentName admin) {
+ public int getPasswordMinimumNonLetter(@Nullable ComponentName admin) {
return getPasswordMinimumNonLetter(admin, UserHandle.myUserId());
}
/** @hide per-user version */
- public int getPasswordMinimumNonLetter(ComponentName admin, int userHandle) {
+ public int getPasswordMinimumNonLetter(@Nullable ComponentName admin, int userHandle) {
if (mService != null) {
try {
return mService.getPasswordMinimumNonLetter(admin, userHandle);
@@ -1511,7 +1541,7 @@ public class DevicePolicyManager {
* @param length The new desired length of password history. A value of 0
* means there is no restriction.
*/
- public void setPasswordHistoryLength(ComponentName admin, int length) {
+ public void setPasswordHistoryLength(@NonNull ComponentName admin, int length) {
if (mService != null) {
try {
mService.setPasswordHistoryLength(admin, length);
@@ -1543,7 +1573,7 @@ public class DevicePolicyManager {
* @param timeout The limit (in ms) that a password can remain in effect. A value of 0
* means there is no restriction (unlimited).
*/
- public void setPasswordExpirationTimeout(ComponentName admin, long timeout) {
+ public void setPasswordExpirationTimeout(@NonNull ComponentName admin, long timeout) {
if (mService != null) {
try {
mService.setPasswordExpirationTimeout(admin, timeout);
@@ -1557,12 +1587,12 @@ public class DevicePolicyManager {
* Get the password expiration timeout for the given admin. The expiration timeout is the
* recurring expiration timeout provided in the call to
* {@link #setPasswordExpirationTimeout(ComponentName, long)} for the given admin or the
- * aggregate of all policy administrators if admin is null.
+ * aggregate of all policy administrators if {@code admin} is null.
*
- * @param admin The name of the admin component to check, or null to aggregate all admins.
+ * @param admin The name of the admin component to check, or {@code null} to aggregate all admins.
* @return The timeout for the given admin or the minimum of all timeouts
*/
- public long getPasswordExpirationTimeout(ComponentName admin) {
+ public long getPasswordExpirationTimeout(@Nullable ComponentName admin) {
if (mService != null) {
try {
return mService.getPasswordExpirationTimeout(admin, UserHandle.myUserId());
@@ -1580,10 +1610,10 @@ public class DevicePolicyManager {
* If admin is null, then a composite of all expiration timeouts is returned
* - which will be the minimum of all timeouts.
*
- * @param admin The name of the admin component to check, or null to aggregate all admins.
+ * @param admin The name of the admin component to check, or {@code null} to aggregate all admins.
* @return The password expiration time, in ms.
*/
- public long getPasswordExpiration(ComponentName admin) {
+ public long getPasswordExpiration(@Nullable ComponentName admin) {
if (mService != null) {
try {
return mService.getPasswordExpiration(admin, UserHandle.myUserId());
@@ -1597,16 +1627,16 @@ public class DevicePolicyManager {
/**
* Retrieve the current password history length for all admins of this
* user and its profiles or a particular one.
- * @param admin The name of the admin component to check, or null to aggregate
+ * @param admin The name of the admin component to check, or {@code null} to aggregate
* all admins.
* @return The length of the password history
*/
- public int getPasswordHistoryLength(ComponentName admin) {
+ public int getPasswordHistoryLength(@Nullable ComponentName admin) {
return getPasswordHistoryLength(admin, UserHandle.myUserId());
}
/** @hide per-user version */
- public int getPasswordHistoryLength(ComponentName admin, int userHandle) {
+ public int getPasswordHistoryLength(@Nullable ComponentName admin, int userHandle) {
if (mService != null) {
try {
return mService.getPasswordHistoryLength(admin, userHandle);
@@ -1705,7 +1735,7 @@ public class DevicePolicyManager {
* @param num The number of failed password attempts at which point the
* device will wipe its data.
*/
- public void setMaximumFailedPasswordsForWipe(ComponentName admin, int num) {
+ public void setMaximumFailedPasswordsForWipe(@NonNull ComponentName admin, int num) {
if (mService != null) {
try {
mService.setMaximumFailedPasswordsForWipe(admin, num);
@@ -1719,15 +1749,15 @@ public class DevicePolicyManager {
* Retrieve the current maximum number of login attempts that are allowed
* before the device wipes itself, for all admins of this user and its profiles
* or a particular one.
- * @param admin The name of the admin component to check, or null to aggregate
+ * @param admin The name of the admin component to check, or {@code null} to aggregate
* all admins.
*/
- public int getMaximumFailedPasswordsForWipe(ComponentName admin) {
+ public int getMaximumFailedPasswordsForWipe(@Nullable ComponentName admin) {
return getMaximumFailedPasswordsForWipe(admin, UserHandle.myUserId());
}
/** @hide per-user version */
- public int getMaximumFailedPasswordsForWipe(ComponentName admin, int userHandle) {
+ public int getMaximumFailedPasswordsForWipe(@Nullable ComponentName admin, int userHandle) {
if (mService != null) {
try {
return mService.getMaximumFailedPasswordsForWipe(admin, userHandle);
@@ -1824,7 +1854,7 @@ public class DevicePolicyManager {
* @param timeMs The new desired maximum time to lock in milliseconds.
* A value of 0 means there is no restriction.
*/
- public void setMaximumTimeToLock(ComponentName admin, long timeMs) {
+ public void setMaximumTimeToLock(@NonNull ComponentName admin, long timeMs) {
if (mService != null) {
try {
mService.setMaximumTimeToLock(admin, timeMs);
@@ -1837,17 +1867,17 @@ public class DevicePolicyManager {
/**
* Retrieve the current maximum time to unlock for all admins of this user
* and its profiles or a particular one.
- * @param admin The name of the admin component to check, or null to aggregate
+ * @param admin The name of the admin component to check, or {@code null} to aggregate
* all admins.
* @return time in milliseconds for the given admin or the minimum value (strictest) of
* all admins if admin is null. Returns 0 if there are no restrictions.
*/
- public long getMaximumTimeToLock(ComponentName admin) {
+ public long getMaximumTimeToLock(@Nullable ComponentName admin) {
return getMaximumTimeToLock(admin, UserHandle.myUserId());
}
/** @hide per-user version */
- public long getMaximumTimeToLock(ComponentName admin, int userHandle) {
+ public long getMaximumTimeToLock(@Nullable ComponentName admin, int userHandle) {
if (mService != null) {
try {
return mService.getMaximumTimeToLock(admin, userHandle);
@@ -1922,21 +1952,20 @@ public class DevicePolicyManager {
* this method; if it has not, a security exception will be thrown.
* Only the first device admin can set the proxy. If a second admin attempts
* to set the proxy, the {@link ComponentName} of the admin originally setting the
- * proxy will be returned. If successful in setting the proxy, null will
+ * proxy will be returned. If successful in setting the proxy, {@code null} will
* be returned.
* The method can be called repeatedly by the device admin alrady setting the
* proxy to update the proxy and exclusion list.
*
- * @param admin Which {@link DeviceAdminReceiver} this request is associated
- * with.
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param proxySpec the global proxy desired. Must be an HTTP Proxy.
* Pass Proxy.NO_PROXY to reset the proxy.
* @param exclusionList a list of domains to be excluded from the global proxy.
- * @return returns null if the proxy was successfully set, or a {@link ComponentName}
- * of the device admin that sets thew proxy otherwise.
+ * @return {@code null} if the proxy was successfully set, or otherwise a {@link ComponentName}
+ * of the device admin that sets the proxy.
* @hide
*/
- public ComponentName setGlobalProxy(ComponentName admin, Proxy proxySpec,
+ public ComponentName setGlobalProxy(@NonNull ComponentName admin, Proxy proxySpec,
List<String> exclusionList ) {
if (proxySpec == null) {
throw new NullPointerException();
@@ -2001,7 +2030,8 @@ public class DevicePolicyManager {
* @param proxyInfo The a {@link ProxyInfo} object defining the new global
* HTTP proxy. A {@code null} value will clear the global HTTP proxy.
*/
- public void setRecommendedGlobalProxy(ComponentName admin, ProxyInfo proxyInfo) {
+ public void setRecommendedGlobalProxy(@NonNull ComponentName admin, @Nullable ProxyInfo
+ proxyInfo) {
if (mService != null) {
try {
mService.setRecommendedGlobalProxy(admin, proxyInfo);
@@ -2013,8 +2043,8 @@ public class DevicePolicyManager {
/**
* Returns the component name setting the global proxy.
- * @return ComponentName object of the device admin that set the global proxy, or
- * null if no admin has set the proxy.
+ * @return ComponentName object of the device admin that set the global proxy, or {@code null}
+ * if no admin has set the proxy.
* @hide
*/
public ComponentName getGlobalProxyAdmin() {
@@ -2147,7 +2177,7 @@ public class DevicePolicyManager {
* {@link #ENCRYPTION_STATUS_ACTIVE}. This is the value of the requests; Use
* {@link #getStorageEncryptionStatus()} to query the actual device state.
*/
- public int setStorageEncryption(ComponentName admin, boolean encrypt) {
+ public int setStorageEncryption(@NonNull ComponentName admin, boolean encrypt) {
if (mService != null) {
try {
return mService.setStorageEncryption(admin, encrypt);
@@ -2167,7 +2197,7 @@ public class DevicePolicyManager {
* administrators.
* @return true if the admin(s) are requesting encryption, false if not.
*/
- public boolean getStorageEncryption(ComponentName admin) {
+ public boolean getStorageEncryption(@Nullable ComponentName admin) {
if (mService != null) {
try {
return mService.getStorageEncryption(admin, UserHandle.myUserId());
@@ -2216,14 +2246,14 @@ public class DevicePolicyManager {
/**
* Installs the given certificate as a user CA.
*
- * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Use
- * <code>null</code> if calling from a delegated certificate installer.
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
+ * {@code null} if calling from a delegated certificate installer.
* @param certBuffer encoded form of the certificate to install.
*
* @return false if the certBuffer cannot be parsed or installation is
* interrupted, true otherwise.
*/
- public boolean installCaCert(ComponentName admin, byte[] certBuffer) {
+ public boolean installCaCert(@Nullable ComponentName admin, byte[] certBuffer) {
if (mService != null) {
try {
return mService.installCaCert(admin, certBuffer);
@@ -2237,11 +2267,11 @@ public class DevicePolicyManager {
/**
* Uninstalls the given certificate from trusted user CAs, if present.
*
- * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Use
- * <code>null</code> if calling from a delegated certificate installer.
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
+ * {@code null} if calling from a delegated certificate installer.
* @param certBuffer encoded form of the certificate to remove.
*/
- public void uninstallCaCert(ComponentName admin, byte[] certBuffer) {
+ public void uninstallCaCert(@Nullable ComponentName admin, byte[] certBuffer) {
if (mService != null) {
try {
final String alias = getCaCertAlias(certBuffer);
@@ -2259,11 +2289,11 @@ public class DevicePolicyManager {
* If a user has installed any certificates by other means than device policy these will be
* included too.
*
- * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Use
- * <code>null</code> if calling from a delegated certificate installer.
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
+ * {@code null} if calling from a delegated certificate installer.
* @return a List of byte[] arrays, each encoding one user CA certificate.
*/
- public List<byte[]> getInstalledCaCerts(ComponentName admin) {
+ public List<byte[]> getInstalledCaCerts(@Nullable ComponentName admin) {
List<byte[]> certs = new ArrayList<byte[]>();
if (mService != null) {
try {
@@ -2287,10 +2317,10 @@ public class DevicePolicyManager {
* Uninstalls all custom trusted CA certificates from the profile. Certificates installed by
* means other than device policy will also be removed, except for system CA certificates.
*
- * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Use
- * <code>null</code> if calling from a delegated certificate installer.
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
+ * {@code null} if calling from a delegated certificate installer.
*/
- public void uninstallAllUserCaCerts(ComponentName admin) {
+ public void uninstallAllUserCaCerts(@Nullable ComponentName admin) {
if (mService != null) {
for (String alias : new TrustedCertificateStore().userAliases()) {
try {
@@ -2305,11 +2335,11 @@ public class DevicePolicyManager {
/**
* Returns whether this certificate is installed as a trusted CA.
*
- * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Use
- * <code>null</code> if calling from a delegated certificate installer.
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
+ * {@code null} if calling from a delegated certificate installer.
* @param certBuffer encoded form of the certificate to look up.
*/
- public boolean hasCaCertInstalled(ComponentName admin, byte[] certBuffer) {
+ public boolean hasCaCertInstalled(@Nullable ComponentName admin, byte[] certBuffer) {
if (mService != null) {
try {
mService.enforceCanManageCaCerts(admin);
@@ -2327,21 +2357,21 @@ 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. Use
- * <code>null</code> if calling from a delegated certificate installer.
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
+ * {@code null} 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
* with that alias already exists, it will be overwritten.
* @return {@code true} if the keys were installed, {@code false} otherwise.
*/
- public boolean installKeyPair(ComponentName who, PrivateKey privKey, Certificate cert,
+ public boolean installKeyPair(@Nullable ComponentName admin, PrivateKey privKey, Certificate cert,
String alias) {
try {
final byte[] pemCert = Credentials.convertToPem(cert);
final byte[] pkcs8Key = KeyFactory.getInstance(privKey.getAlgorithm())
.getKeySpec(privKey, PKCS8EncodedKeySpec.class).getEncoded();
- return mService.installKeyPair(who, pkcs8Key, pemCert, alias);
+ return mService.installKeyPair(admin, pkcs8Key, pemCert, alias);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
@@ -2353,7 +2383,7 @@ public class DevicePolicyManager {
}
/**
- * Returns the alias of a given CA certificate in the certificate store, or null if it
+ * @return the alias of a given CA certificate in the certificate store, or {@code null} if it
* doesn't exist.
*/
private static String getCaCertAlias(byte[] certBuffer) throws CertificateException {
@@ -2373,15 +2403,15 @@ public class DevicePolicyManager {
* it is later cleared by calling this method with a null value or uninstallling the certificate
* installer.
*
- * @param who Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param installerPackage The package name of the certificate installer which will be given
- * access. If <code>null</code> is given the current package will be cleared.
+ * access. If {@code null} is given the current package will be cleared.
*/
- public void setCertInstallerPackage(ComponentName who, String installerPackage)
- throws SecurityException {
+ public void setCertInstallerPackage(@NonNull ComponentName admin, @Nullable String
+ installerPackage) throws SecurityException {
if (mService != null) {
try {
- mService.setCertInstallerPackage(who, installerPackage);
+ mService.setCertInstallerPackage(admin, installerPackage);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -2392,14 +2422,14 @@ public class DevicePolicyManager {
* Called by a profile owner or device owner to retrieve the certificate installer for the
* current user. null if none is set.
*
- * @param who Which {@link DeviceAdminReceiver} this request is associated with.
- * @return The package name of the current delegated certificate installer. <code>null</code>
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @return The package name of the current delegated certificate installer, or {@code null}
* if none is set.
*/
- public String getCertInstallerPackage(ComponentName who) throws SecurityException {
+ public String getCertInstallerPackage(@NonNull ComponentName admin) throws SecurityException {
if (mService != null) {
try {
- return mService.getCertInstallerPackage(who);
+ return mService.getCertInstallerPackage(admin);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -2419,7 +2449,7 @@ public class DevicePolicyManager {
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param disabled Whether or not the camera should be disabled.
*/
- public void setCameraDisabled(ComponentName admin, boolean disabled) {
+ public void setCameraDisabled(@NonNull ComponentName admin, boolean disabled) {
if (mService != null) {
try {
mService.setCameraDisabled(admin, disabled);
@@ -2432,15 +2462,15 @@ public class DevicePolicyManager {
/**
* Determine whether or not the device's cameras have been disabled for this user,
* either by the current admin, if specified, or all admins.
- * @param admin The name of the admin component to check, or null to check if any admins
+ * @param admin The name of the admin component to check, or {@code null} to check whether any admins
* have disabled the camera
*/
- public boolean getCameraDisabled(ComponentName admin) {
+ public boolean getCameraDisabled(@Nullable ComponentName admin) {
return getCameraDisabled(admin, UserHandle.myUserId());
}
/** @hide per-user version */
- public boolean getCameraDisabled(ComponentName admin, int userHandle) {
+ public boolean getCameraDisabled(@Nullable ComponentName admin, int userHandle) {
if (mService != null) {
try {
return mService.getCameraDisabled(admin, userHandle);
@@ -2463,7 +2493,7 @@ public class DevicePolicyManager {
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param disabled Whether screen capture is disabled or not.
*/
- public void setScreenCaptureDisabled(ComponentName admin, boolean disabled) {
+ public void setScreenCaptureDisabled(@NonNull ComponentName admin, boolean disabled) {
if (mService != null) {
try {
mService.setScreenCaptureDisabled(admin, disabled);
@@ -2476,15 +2506,15 @@ public class DevicePolicyManager {
/**
* Determine whether or not screen capture has been disabled by the current
* admin, if specified, or all admins.
- * @param admin The name of the admin component to check, or null to check if any admins
+ * @param admin The name of the admin component to check, or {@code null} to check whether any admins
* have disabled screen capture.
*/
- public boolean getScreenCaptureDisabled(ComponentName admin) {
+ public boolean getScreenCaptureDisabled(@Nullable ComponentName admin) {
return getScreenCaptureDisabled(admin, UserHandle.myUserId());
}
/** @hide per-user version */
- public boolean getScreenCaptureDisabled(ComponentName admin, int userHandle) {
+ public boolean getScreenCaptureDisabled(@Nullable ComponentName admin, int userHandle) {
if (mService != null) {
try {
return mService.getScreenCaptureDisabled(admin, userHandle);
@@ -2507,7 +2537,7 @@ public class DevicePolicyManager {
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param required Whether auto time is set required or not.
*/
- public void setAutoTimeRequired(ComponentName admin, boolean required) {
+ public void setAutoTimeRequired(@NonNull ComponentName admin, boolean required) {
if (mService != null) {
try {
mService.setAutoTimeRequired(admin, required);
@@ -2561,7 +2591,7 @@ public class DevicePolicyManager {
* {@link #KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS}, {@link #KEYGUARD_DISABLE_FINGERPRINT},
* {@link #KEYGUARD_DISABLE_FEATURES_ALL}
*/
- public void setKeyguardDisabledFeatures(ComponentName admin, int which) {
+ public void setKeyguardDisabledFeatures(@NonNull ComponentName admin, int which) {
if (mService != null) {
try {
mService.setKeyguardDisabledFeatures(admin, which);
@@ -2574,17 +2604,17 @@ public class DevicePolicyManager {
/**
* Determine whether or not features have been disabled in keyguard either by the current
* admin, if specified, or all admins.
- * @param admin The name of the admin component to check, or null to check if any admins
+ * @param admin The name of the admin component to check, or {@code null} to check whether any admins
* have disabled features in keyguard.
* @return bitfield of flags. See {@link #setKeyguardDisabledFeatures(ComponentName, int)}
* for a list.
*/
- public int getKeyguardDisabledFeatures(ComponentName admin) {
+ public int getKeyguardDisabledFeatures(@Nullable ComponentName admin) {
return getKeyguardDisabledFeatures(admin, UserHandle.myUserId());
}
/** @hide per-user version */
- public int getKeyguardDisabledFeatures(ComponentName admin, int userHandle) {
+ public int getKeyguardDisabledFeatures(@Nullable ComponentName admin, int userHandle) {
if (mService != null) {
try {
return mService.getKeyguardDisabledFeatures(admin, userHandle);
@@ -2598,7 +2628,8 @@ public class DevicePolicyManager {
/**
* @hide
*/
- public void setActiveAdmin(ComponentName policyReceiver, boolean refreshing, int userHandle) {
+ public void setActiveAdmin(@NonNull ComponentName policyReceiver, boolean refreshing,
+ int userHandle) {
if (mService != null) {
try {
mService.setActiveAdmin(policyReceiver, refreshing, userHandle);
@@ -2611,15 +2642,15 @@ public class DevicePolicyManager {
/**
* @hide
*/
- public void setActiveAdmin(ComponentName policyReceiver, boolean refreshing) {
+ public void setActiveAdmin(@NonNull ComponentName policyReceiver, boolean refreshing) {
setActiveAdmin(policyReceiver, refreshing, UserHandle.myUserId());
}
/**
- * Returns the DeviceAdminInfo as defined by the administrator's package info & meta-data
+ * Returns the DeviceAdminInfo as defined by the administrator's package info &amp; meta-data
* @hide
*/
- public DeviceAdminInfo getAdminInfo(ComponentName cn) {
+ public DeviceAdminInfo getAdminInfo(@NonNull ComponentName cn) {
ActivityInfo ai;
try {
ai = mContext.getPackageManager().getReceiverInfo(cn,
@@ -2646,7 +2677,7 @@ public class DevicePolicyManager {
/**
* @hide
*/
- public void getRemoveWarning(ComponentName admin, RemoteCallback result) {
+ public void getRemoveWarning(@Nullable ComponentName admin, RemoteCallback result) {
if (mService != null) {
try {
mService.getRemoveWarning(admin, result, UserHandle.myUserId());
@@ -2740,10 +2771,10 @@ public class DevicePolicyManager {
/**
* Used to determine if a particular package has been registered as a Device Owner app.
* A device owner app is a special device admin that cannot be deactivated by the user, once
- * activated as a device admin. It also cannot be uninstalled. To check if a particular
+ * activated as a device admin. It also cannot be uninstalled. To check whether a particular
* package is currently registered as the device owner app, pass in the package name from
* {@link Context#getPackageName()} to this method.<p/>This is useful for device
- * admin apps that want to check if they are also registered as the device owner app. The
+ * admin apps that want to check whether they are also registered as the device owner app. The
* exact mechanism by which a device admin app is registered as a device owner app is defined by
* the setup process.
* @param packageName the package name of the app, to compare with the registered device owner
@@ -2820,19 +2851,20 @@ public class DevicePolicyManager {
* MANAGE_DEVICE_ADMINS permission before the device is provisioned or by a device owner app. A
* device initializer app is granted device owner privileges during device initialization and
* profile owner privileges during secondary user initialization.
- * @param who Which {@link DeviceAdminReceiver} this request is associated with, or null if not
- * called by the device owner.
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
+ * {@code null} if not called by the device owner.
* @param initializer Which {@link DeviceAdminReceiver} to make device initializer.
* @return whether the component was successfully registered as the device initializer.
* @throws IllegalArgumentException if the componentname is null or invalid
* @throws IllegalStateException if the caller is not device owner or the device has
* already been provisioned or a device initializer already exists.
*/
- public boolean setDeviceInitializer(ComponentName who, ComponentName initializer)
+ public boolean setDeviceInitializer(@Nullable ComponentName admin,
+ @NonNull ComponentName initializer)
throws IllegalArgumentException, IllegalStateException {
if (mService != null) {
try {
- return mService.setDeviceInitializer(who, initializer);
+ return mService.setDeviceInitializer(admin, initializer);
} catch (RemoteException re) {
Log.w(TAG, "Failed to set device initializer");
}
@@ -2863,12 +2895,12 @@ public class DevicePolicyManager {
* subsequently created users. This method can be called by either the device owner or device
* initializer itself. The caller must be an active administrator.
*
- * @param who Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
*/
- public void clearDeviceInitializerApp(ComponentName who) {
+ public void clearDeviceInitializerApp(@NonNull ComponentName admin) {
if (mService != null) {
try {
- mService.clearDeviceInitializer(who);
+ mService.clearDeviceInitializer(admin);
} catch (RemoteException re) {
Log.w(TAG, "Failed to clear device initializer");
}
@@ -2927,7 +2959,7 @@ public class DevicePolicyManager {
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @return whether the user is now enabled.
*/
- public boolean setUserEnabled(ComponentName admin) {
+ public boolean setUserEnabled(@NonNull ComponentName admin) {
if (mService != null) {
try {
return mService.setUserEnabled(admin);
@@ -2955,7 +2987,7 @@ public class DevicePolicyManager {
* the user has already been set up.
*/
@SystemApi
- public boolean setActiveProfileOwner(ComponentName admin, @Deprecated String ownerName)
+ public boolean setActiveProfileOwner(@NonNull ComponentName admin, @Deprecated String ownerName)
throws IllegalArgumentException {
if (mService != null) {
try {
@@ -2980,7 +3012,7 @@ public class DevicePolicyManager {
* @return
*/
@SystemApi
- public void clearProfileOwner(ComponentName admin) {
+ public void clearProfileOwner(@NonNull ComponentName admin) {
if (mService != null) {
try {
mService.clearProfileOwner(admin);
@@ -2992,14 +3024,14 @@ public class DevicePolicyManager {
/**
* @hide
- * Checks if the user was already setup.
+ * Checks whether the user was already setup.
*/
public boolean hasUserSetupCompleted() {
if (mService != null) {
try {
return mService.hasUserSetupCompleted();
} catch (RemoteException re) {
- Log.w(TAG, "Failed to check if user setup has completed");
+ Log.w(TAG, "Failed to check whether user setup has completed");
}
}
return true;
@@ -3021,7 +3053,7 @@ public class DevicePolicyManager {
* @throws IllegalArgumentException if admin is null, the package isn't installed, or the
* preconditions mentioned are not met.
*/
- public boolean setProfileOwner(ComponentName admin, @Deprecated String ownerName,
+ public boolean setProfileOwner(@NonNull ComponentName admin, @Deprecated String ownerName,
int userHandle) throws IllegalArgumentException {
if (admin == null) {
throw new NullPointerException("admin cannot be null");
@@ -3048,7 +3080,7 @@ public class DevicePolicyManager {
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
*/
- public void setProfileEnabled(ComponentName admin) {
+ public void setProfileEnabled(@NonNull ComponentName admin) {
if (mService != null) {
try {
mService.setProfileEnabled(admin);
@@ -3066,12 +3098,13 @@ public class DevicePolicyManager {
* @see #isProfileOwnerApp
* @see #isDeviceOwnerApp
*
+ * @param admin Which {@link DeviceAdminReceiver} this request is associate with.
* @param profileName The name of the profile.
*/
- public void setProfileName(ComponentName who, String profileName) {
+ public void setProfileName(@NonNull ComponentName admin, String profileName) {
if (mService != null) {
try {
- mService.setProfileName(who, profileName);
+ mService.setProfileName(admin, profileName);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -3102,7 +3135,7 @@ public class DevicePolicyManager {
/**
* @hide
- * @return the packageName of the owner of the given user profile or null if no profile
+ * @return the packageName of the owner of the given user profile or {@code null} if no profile
* owner has been set for that user.
* @throws IllegalArgumentException if the userId is invalid.
*/
@@ -3130,8 +3163,8 @@ public class DevicePolicyManager {
/**
* @hide
- * @return the human readable name of the organisation associated with this DPM or null if
- * one is not set.
+ * @return the human readable name of the organisation associated with this DPM or {@code null}
+ * if one is not set.
* @throws IllegalArgumentException if the userId is invalid.
*/
public String getProfileOwnerName() throws IllegalArgumentException {
@@ -3185,8 +3218,8 @@ public class DevicePolicyManager {
* @param filter The IntentFilter for which a default handler is added.
* @param activity The Activity that is added as default intent handler.
*/
- public void addPersistentPreferredActivity(ComponentName admin, IntentFilter filter,
- ComponentName activity) {
+ public void addPersistentPreferredActivity(@NonNull ComponentName admin, IntentFilter filter,
+ @NonNull ComponentName activity) {
if (mService != null) {
try {
mService.addPersistentPreferredActivity(admin, filter, activity);
@@ -3206,7 +3239,7 @@ public class DevicePolicyManager {
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param packageName The name of the package for which preferences are removed.
*/
- public void clearPackagePersistentPreferredActivities(ComponentName admin,
+ public void clearPackagePersistentPreferredActivities(@NonNull ComponentName admin,
String packageName) {
if (mService != null) {
try {
@@ -3241,7 +3274,7 @@ public class DevicePolicyManager {
*
* @see UserManager#KEY_RESTRICTIONS_PENDING
*/
- public void setApplicationRestrictions(ComponentName admin, String packageName,
+ public void setApplicationRestrictions(@NonNull ComponentName admin, String packageName,
Bundle settings) {
if (mService != null) {
try {
@@ -3271,8 +3304,8 @@ public class DevicePolicyManager {
* then it's up to the TrustAgent itself to aggregate the values from all device admins.
* <p>Consult documentation for the specific TrustAgent to determine legal options parameters.
*/
- public void setTrustAgentConfiguration(ComponentName admin, ComponentName target,
- PersistableBundle configuration) {
+ public void setTrustAgentConfiguration(@NonNull ComponentName admin,
+ @NonNull ComponentName target, PersistableBundle configuration) {
if (mService != null) {
try {
mService.setTrustAgentConfiguration(admin, target, configuration);
@@ -3296,14 +3329,14 @@ public class DevicePolicyManager {
* @param agent Which component to get enabled features for.
* @return configuration for the given trust agent.
*/
- public List<PersistableBundle> getTrustAgentConfiguration(ComponentName admin,
- ComponentName agent) {
+ public List<PersistableBundle> getTrustAgentConfiguration(@Nullable ComponentName admin,
+ @NonNull ComponentName agent) {
return getTrustAgentConfiguration(admin, agent, UserHandle.myUserId());
}
/** @hide per-user version */
- public List<PersistableBundle> getTrustAgentConfiguration(ComponentName admin,
- ComponentName agent, int userHandle) {
+ public List<PersistableBundle> getTrustAgentConfiguration(@Nullable ComponentName admin,
+ @NonNull ComponentName agent, int userHandle) {
if (mService != null) {
try {
return mService.getTrustAgentConfiguration(admin, agent, userHandle);
@@ -3321,13 +3354,13 @@ public class DevicePolicyManager {
* <p>The calling device admin must be a profile owner. If it is not, a
* security exception will be thrown.
*
- * @param who Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param disabled If true caller-Id information in the managed profile is not displayed.
*/
- public void setCrossProfileCallerIdDisabled(ComponentName who, boolean disabled) {
+ public void setCrossProfileCallerIdDisabled(@NonNull ComponentName admin, boolean disabled) {
if (mService != null) {
try {
- mService.setCrossProfileCallerIdDisabled(who, disabled);
+ mService.setCrossProfileCallerIdDisabled(admin, disabled);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -3341,12 +3374,12 @@ public class DevicePolicyManager {
* <p>The calling device admin must be a profile owner. If it is not, a
* security exception will be thrown.
*
- * @param who Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
*/
- public boolean getCrossProfileCallerIdDisabled(ComponentName who) {
+ public boolean getCrossProfileCallerIdDisabled(@NonNull ComponentName admin) {
if (mService != null) {
try {
- return mService.getCrossProfileCallerIdDisabled(who);
+ return mService.getCrossProfileCallerIdDisabled(admin);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -3396,15 +3429,15 @@ public class DevicePolicyManager {
* <p>
* This API works on managed profile only.
*
- * @param who Which {@link DeviceAdminReceiver} this request is associated
+ * @param admin 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) {
+ public void setBluetoothContactSharingDisabled(@NonNull ComponentName admin, boolean disabled) {
if (mService != null) {
try {
- mService.setBluetoothContactSharingDisabled(who, disabled);
+ mService.setBluetoothContactSharingDisabled(admin, disabled);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -3420,13 +3453,13 @@ public class DevicePolicyManager {
* <p>
* This API works on managed profile only.
*
- * @param who Which {@link DeviceAdminReceiver} this request is associated
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated
* with.
*/
- public boolean getBluetoothContactSharingDisabled(ComponentName who) {
+ public boolean getBluetoothContactSharingDisabled(@NonNull ComponentName admin) {
if (mService != null) {
try {
- return mService.getBluetoothContactSharingDisabled(who);
+ return mService.getBluetoothContactSharingDisabled(admin);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -3465,7 +3498,7 @@ public class DevicePolicyManager {
* @param flags {@link DevicePolicyManager#FLAG_MANAGED_CAN_ACCESS_PARENT} and
* {@link DevicePolicyManager#FLAG_PARENT_CAN_ACCESS_MANAGED} are supported.
*/
- public void addCrossProfileIntentFilter(ComponentName admin, IntentFilter filter, int flags) {
+ public void addCrossProfileIntentFilter(@NonNull ComponentName admin, IntentFilter filter, int flags) {
if (mService != null) {
try {
mService.addCrossProfileIntentFilter(admin, filter, flags);
@@ -3481,7 +3514,7 @@ public class DevicePolicyManager {
* Only removes those that have been set by the profile owner.
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
*/
- public void clearCrossProfileIntentFilters(ComponentName admin) {
+ public void clearCrossProfileIntentFilters(@NonNull ComponentName admin) {
if (mService != null) {
try {
mService.clearCrossProfileIntentFilters(admin);
@@ -3512,7 +3545,7 @@ public class DevicePolicyManager {
* @return true if setting the restriction succeeded. It fail if there is
* one or more non-system accessibility services enabled, that are not in the list.
*/
- public boolean setPermittedAccessibilityServices(ComponentName admin,
+ public boolean setPermittedAccessibilityServices(@NonNull ComponentName admin,
List<String> packageNames) {
if (mService != null) {
try {
@@ -3533,7 +3566,7 @@ public class DevicePolicyManager {
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @return List of accessiblity service package names.
*/
- public List<String> getPermittedAccessibilityServices(ComponentName admin) {
+ public List<String> getPermittedAccessibilityServices(@NonNull ComponentName admin) {
if (mService != null) {
try {
return mService.getPermittedAccessibilityServices(admin);
@@ -3591,7 +3624,7 @@ public class DevicePolicyManager {
* one or more non-system input methods currently enabled that are not in
* the packageNames list.
*/
- public boolean setPermittedInputMethods(ComponentName admin, List<String> packageNames) {
+ public boolean setPermittedInputMethods(@NonNull ComponentName admin, List<String> packageNames) {
if (mService != null) {
try {
return mService.setPermittedInputMethods(admin, packageNames);
@@ -3612,7 +3645,7 @@ public class DevicePolicyManager {
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @return List of input method package names.
*/
- public List<String> getPermittedInputMethods(ComponentName admin) {
+ public List<String> getPermittedInputMethods(@NonNull ComponentName admin) {
if (mService != null) {
try {
return mService.getPermittedInputMethods(admin);
@@ -3655,9 +3688,10 @@ public class DevicePolicyManager {
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param name the user's name
* @see UserHandle
- * @return the UserHandle object for the created user, or null if the user could not be created.
+ * @return the {@link android.os.UserHandle} object for the created user, or {@code null} if the
+ * user could not be created.
*/
- public UserHandle createUser(ComponentName admin, String name) {
+ public UserHandle createUser(@NonNull ComponentName admin, String name) {
try {
return mService.createUser(admin, name);
} catch (RemoteException re) {
@@ -3688,10 +3722,11 @@ public class DevicePolicyManager {
* @param adminExtras Extras that will be passed to onEnable of the admin receiver
* on the new user.
* @see UserHandle
- * @return the UserHandle object for the created user, or null if the user could not be created.
+ * @return the {@link android.os.UserHandle} object for the created user, or {@code null} if the
+ * user could not be created.
*/
- public UserHandle createAndInitializeUser(ComponentName admin, String name, String ownerName,
- ComponentName profileOwnerComponent, Bundle adminExtras) {
+ public UserHandle createAndInitializeUser(@NonNull ComponentName admin, String name,
+ String ownerName, @NonNull ComponentName profileOwnerComponent, Bundle adminExtras) {
try {
return mService.createAndInitializeUser(admin, name, ownerName, profileOwnerComponent,
adminExtras);
@@ -3709,7 +3744,7 @@ public class DevicePolicyManager {
* @param userHandle the user to remove.
* @return {@code true} if the user was removed, {@code false} otherwise.
*/
- public boolean removeUser(ComponentName admin, UserHandle userHandle) {
+ public boolean removeUser(@NonNull ComponentName admin, UserHandle userHandle) {
try {
return mService.removeUser(admin, userHandle);
} catch (RemoteException re) {
@@ -3727,7 +3762,7 @@ public class DevicePolicyManager {
*
* @see Intent#ACTION_USER_FOREGROUND
*/
- public boolean switchUser(ComponentName admin, UserHandle userHandle) {
+ public boolean switchUser(@NonNull ComponentName admin, @Nullable UserHandle userHandle) {
try {
return mService.switchUser(admin, userHandle);
} catch (RemoteException re) {
@@ -3749,7 +3784,7 @@ public class DevicePolicyManager {
* {@link DevicePolicyManager#setApplicationRestrictions} was called, or an empty {@link Bundle}
* if no restrictions have been set.
*/
- public Bundle getApplicationRestrictions(ComponentName admin, String packageName) {
+ public Bundle getApplicationRestrictions(@NonNull ComponentName admin, String packageName) {
if (mService != null) {
try {
return mService.getApplicationRestrictions(admin, packageName);
@@ -3771,7 +3806,7 @@ public class DevicePolicyManager {
* @param key The key of the restriction. See the constants in
* {@link android.os.UserManager} for the list of keys.
*/
- public void addUserRestriction(ComponentName admin, String key) {
+ public void addUserRestriction(@NonNull ComponentName admin, String key) {
if (mService != null) {
try {
mService.setUserRestriction(admin, key, true);
@@ -3792,7 +3827,7 @@ public class DevicePolicyManager {
* @param key The key of the restriction. See the constants in
* {@link android.os.UserManager} for the list of keys.
*/
- public void clearUserRestriction(ComponentName admin, String key) {
+ public void clearUserRestriction(@NonNull ComponentName admin, String key) {
if (mService != null) {
try {
mService.setUserRestriction(admin, key, false);
@@ -3812,7 +3847,7 @@ public class DevicePolicyManager {
* unhidden.
* @return boolean Whether the hidden setting of the package was successfully updated.
*/
- public boolean setApplicationHidden(ComponentName admin, String packageName,
+ public boolean setApplicationHidden(@NonNull ComponentName admin, String packageName,
boolean hidden) {
if (mService != null) {
try {
@@ -3831,7 +3866,7 @@ public class DevicePolicyManager {
* @param packageName The name of the package to retrieve the hidden status of.
* @return boolean {@code true} if the package is hidden, {@code false} otherwise.
*/
- public boolean isApplicationHidden(ComponentName admin, String packageName) {
+ public boolean isApplicationHidden(@NonNull ComponentName admin, String packageName) {
if (mService != null) {
try {
return mService.isApplicationHidden(admin, packageName);
@@ -3849,7 +3884,7 @@ public class DevicePolicyManager {
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param packageName The package to be re-enabled in the current profile.
*/
- public void enableSystemApp(ComponentName admin, String packageName) {
+ public void enableSystemApp(@NonNull ComponentName admin, String packageName) {
if (mService != null) {
try {
mService.enableSystemApp(admin, packageName);
@@ -3868,7 +3903,7 @@ public class DevicePolicyManager {
* intent will be re-enabled in the current profile.
* @return int The number of activities that matched the intent and were installed.
*/
- public int enableSystemApp(ComponentName admin, Intent intent) {
+ public int enableSystemApp(@NonNull ComponentName admin, Intent intent) {
if (mService != null) {
try {
return mService.enableSystemAppWithIntent(admin, intent);
@@ -3894,7 +3929,7 @@ public class DevicePolicyManager {
* @param disabled The boolean indicating that account management will be disabled (true) or
* enabled (false).
*/
- public void setAccountManagementDisabled(ComponentName admin, String accountType,
+ public void setAccountManagementDisabled(@NonNull ComponentName admin, String accountType,
boolean disabled) {
if (mService != null) {
try {
@@ -3950,7 +3985,7 @@ public class DevicePolicyManager {
* @see DeviceAdminReceiver#onLockTaskModeExiting(Context, Intent)
* @see UserManager#DISALLOW_CREATE_WINDOWS
*/
- public void setLockTaskPackages(ComponentName admin, String[] packages)
+ public void setLockTaskPackages(@NonNull ComponentName admin, String[] packages)
throws SecurityException {
if (mService != null) {
try {
@@ -3967,7 +4002,7 @@ public class DevicePolicyManager {
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @hide
*/
- public String[] getLockTaskPackages(ComponentName admin) {
+ public String[] getLockTaskPackages(@NonNull ComponentName admin) {
if (mService != null) {
try {
return mService.getLockTaskPackages(admin);
@@ -4024,7 +4059,7 @@ public class DevicePolicyManager {
* @param setting The name of the setting to update.
* @param value The value to update the setting to.
*/
- public void setGlobalSetting(ComponentName admin, String setting, String value) {
+ public void setGlobalSetting(@NonNull ComponentName admin, String setting, String value) {
if (mService != null) {
try {
mService.setGlobalSetting(admin, setting, value);
@@ -4052,7 +4087,7 @@ public class DevicePolicyManager {
* @param setting The name of the setting to update.
* @param value The value to update the setting to.
*/
- public void setSecureSetting(ComponentName admin, String setting, String value) {
+ public void setSecureSetting(@NonNull ComponentName admin, String setting, String value) {
if (mService != null) {
try {
mService.setSecureSetting(admin, setting, value);
@@ -4072,7 +4107,8 @@ public class DevicePolicyManager {
* {@link RestrictionsReceiver}. If this param is null,
* it removes the restrictions provider previously assigned.
*/
- public void setRestrictionsProvider(ComponentName admin, ComponentName provider) {
+ public void setRestrictionsProvider(@NonNull ComponentName admin,
+ @Nullable ComponentName provider) {
if (mService != null) {
try {
mService.setRestrictionsProvider(admin, provider);
@@ -4088,7 +4124,7 @@ public class DevicePolicyManager {
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param on {@code true} to mute master volume, {@code false} to turn mute off.
*/
- public void setMasterVolumeMuted(ComponentName admin, boolean on) {
+ public void setMasterVolumeMuted(@NonNull ComponentName admin, boolean on) {
if (mService != null) {
try {
mService.setMasterVolumeMuted(admin, on);
@@ -4104,7 +4140,7 @@ public class DevicePolicyManager {
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @return {@code true} if master volume is muted, {@code false} if it's not.
*/
- public boolean isMasterVolumeMuted(ComponentName admin) {
+ public boolean isMasterVolumeMuted(@NonNull ComponentName admin) {
if (mService != null) {
try {
return mService.isMasterVolumeMuted(admin);
@@ -4123,7 +4159,7 @@ public class DevicePolicyManager {
* @param packageName package to change.
* @param uninstallBlocked true if the user shouldn't be able to uninstall the package.
*/
- public void setUninstallBlocked(ComponentName admin, String packageName,
+ public void setUninstallBlocked(@NonNull ComponentName admin, String packageName,
boolean uninstallBlocked) {
if (mService != null) {
try {
@@ -4139,16 +4175,16 @@ public class DevicePolicyManager {
* Requires the caller to be the profile owner if checking a specific admin's policy.
* <p>
* <strong>Note:</strong> Starting from {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1}, the
- * behavior of this API is changed such that passing <code>null</code> as the <code>admin</code>
+ * behavior of this API is changed such that passing {@code null} as the {@code admin}
* parameter will return if any admin has blocked the uninstallation. Before L MR1, passing
- * <code>null</code> will cause a NullPointerException to be raised.
+ * {@code null} will cause a NullPointerException to be raised.
*
- * @param admin The name of the admin component whose blocking policy will be checked, or null
- * to check if any admin has blocked the uninstallation.
+ * @param admin The name of the admin component whose blocking policy will be checked, or
+ * {@code null} to check whether any admin has blocked the uninstallation.
* @param packageName package to check.
* @return true if uninstallation is blocked.
*/
- public boolean isUninstallBlocked(ComponentName admin, String packageName) {
+ public boolean isUninstallBlocked(@Nullable ComponentName admin, String packageName) {
if (mService != null) {
try {
return mService.isUninstallBlocked(admin, packageName);
@@ -4168,7 +4204,6 @@ public class DevicePolicyManager {
* provides a different widget type.
* <p>
* <strong>Note:</strong> By default no widget provider package is white-listed.
- * </p>
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param packageName The package from which widget providers are white-listed.
@@ -4177,7 +4212,7 @@ public class DevicePolicyManager {
* @see #removeCrossProfileWidgetProvider(android.content.ComponentName, String)
* @see #getCrossProfileWidgetProviders(android.content.ComponentName)
*/
- public boolean addCrossProfileWidgetProvider(ComponentName admin, String packageName) {
+ public boolean addCrossProfileWidgetProvider(@NonNull ComponentName admin, String packageName) {
if (mService != null) {
try {
return mService.addCrossProfileWidgetProvider(admin, packageName);
@@ -4195,7 +4230,6 @@ public class DevicePolicyManager {
* android.content.ComponentName, String)}.
* <p>
* <strong>Note:</strong> By default no widget provider package is white-listed.
- * </p>
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param packageName The package from which widget providers are no longer
@@ -4205,7 +4239,7 @@ public class DevicePolicyManager {
* @see #addCrossProfileWidgetProvider(android.content.ComponentName, String)
* @see #getCrossProfileWidgetProviders(android.content.ComponentName)
*/
- public boolean removeCrossProfileWidgetProvider(ComponentName admin, String packageName) {
+ public boolean removeCrossProfileWidgetProvider(@NonNull ComponentName admin, String packageName) {
if (mService != null) {
try {
return mService.removeCrossProfileWidgetProvider(admin, packageName);
@@ -4226,7 +4260,7 @@ public class DevicePolicyManager {
* @see #addCrossProfileWidgetProvider(android.content.ComponentName, String)
* @see #removeCrossProfileWidgetProvider(android.content.ComponentName, String)
*/
- public List<String> getCrossProfileWidgetProviders(ComponentName admin) {
+ public List<String> getCrossProfileWidgetProviders(@NonNull ComponentName admin) {
if (mService != null) {
try {
List<String> providers = mService.getCrossProfileWidgetProviders(admin);
@@ -4246,7 +4280,7 @@ public class DevicePolicyManager {
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param icon the bitmap to set as the photo.
*/
- public void setUserIcon(ComponentName admin, Bitmap icon) {
+ public void setUserIcon(@NonNull ComponentName admin, Bitmap icon) {
try {
mService.setUserIcon(admin, icon);
} catch (RemoteException re) {
@@ -4273,16 +4307,17 @@ public class DevicePolicyManager {
* Called by device owners to set a local system update policy. When a new policy is set,
* {@link #ACTION_SYSTEM_UPDATE_POLICY_CHANGED} is broadcasted.
*
- * @param who Which {@link DeviceAdminReceiver} this request is associated with. All components
- * in the device owner package can set system update policies and the most recent policy takes
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with. All
+ * components in the device owner package can set system update policies and the
+ * most recent policy takes
* effect.
- * @param policy the new policy, or null to clear the current policy.
+ * @param policy the new policy, or {@code null} to clear the current policy.
* @see SystemUpdatePolicy
*/
- public void setSystemUpdatePolicy(ComponentName who, SystemUpdatePolicy policy) {
+ public void setSystemUpdatePolicy(@NonNull ComponentName admin, SystemUpdatePolicy policy) {
if (mService != null) {
try {
- mService.setSystemUpdatePolicy(who, policy);
+ mService.setSystemUpdatePolicy(admin, policy);
} catch (RemoteException re) {
Log.w(TAG, "Error calling setSystemUpdatePolicy", re);
}
@@ -4292,7 +4327,7 @@ public class DevicePolicyManager {
/**
* Retrieve a local system update policy set previously by {@link #setSystemUpdatePolicy}.
*
- * @return The current policy object, or null if no policy is set.
+ * @return The current policy object, or {@code null} if no policy is set.
*/
public SystemUpdatePolicy getSystemUpdatePolicy() {
if (mService != null) {
@@ -4319,7 +4354,7 @@ public class DevicePolicyManager {
* @return {@code false} if attempting to disable the keyguard while a lock password was in
* place. {@code true} otherwise.
*/
- public boolean setKeyguardDisabled(ComponentName admin, boolean disabled) {
+ public boolean setKeyguardDisabled(@NonNull ComponentName admin, boolean disabled) {
try {
return mService.setKeyguardDisabled(admin, disabled);
} catch (RemoteException re) {
@@ -4339,7 +4374,7 @@ public class DevicePolicyManager {
* @return {@code false} if attempting to disable the status bar failed.
* {@code true} otherwise.
*/
- public boolean setStatusBarDisabled(ComponentName admin, boolean disabled) {
+ public boolean setStatusBarDisabled(@NonNull ComponentName admin, boolean disabled) {
try {
return mService.setStatusBarDisabled(admin, disabled);
} catch (RemoteException re) {
@@ -4377,7 +4412,8 @@ public class DevicePolicyManager {
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param activity The Activity to be started by default during user setup.
*/
- public void setPreferredSetupActivity(ComponentName admin, ComponentName activity) {
+ public void setPreferredSetupActivity(@NonNull ComponentName admin,
+ @NonNull ComponentName activity) {
try {
mService.setPreferredSetupActivity(admin, activity);
} catch (RemoteException re) {
@@ -4395,7 +4431,7 @@ public class DevicePolicyManager {
* @param policy One of the policy constants {@link #PERMISSION_POLICY_PROMPT},
* {@link #PERMISSION_POLICY_AUTO_GRANT} and {@link #PERMISSION_POLICY_AUTO_DENY}.
*/
- public void setPermissionPolicy(ComponentName admin, int policy) {
+ public void setPermissionPolicy(@NonNull ComponentName admin, int policy) {
try {
mService.setPermissionPolicy(admin, policy);
} catch (RemoteException re) {
@@ -4409,7 +4445,7 @@ public class DevicePolicyManager {
* @param admin Which profile or device owner this request is associated with.
* @return the current policy for future permission requests.
*/
- public int getPermissionPolicy(ComponentName admin) {
+ public int getPermissionPolicy(@NonNull ComponentName admin) {
try {
return mService.getPermissionPolicy(admin);
} catch (RemoteException re) {
@@ -4439,7 +4475,7 @@ public class DevicePolicyManager {
* @see #PERMISSION_GRANT_STATE_DEFAULT
* @see #PERMISSION_GRANT_STATE_GRANTED
*/
- public boolean setPermissionGrantState(ComponentName admin, String packageName,
+ public boolean setPermissionGrantState(@NonNull ComponentName admin, String packageName,
String permission, int grantState) {
try {
return mService.setPermissionGrantState(admin, packageName, permission, grantState);
@@ -4466,7 +4502,7 @@ public class DevicePolicyManager {
* @see #setPermissionGrantState(ComponentName, String, String, int)
* @see PackageManager#checkPermission(String, String)
*/
- public int getPermissionGrantState(ComponentName admin, String packageName,
+ public int getPermissionGrantState(@NonNull ComponentName admin, String packageName,
String permission) {
try {
return mService.getPermissionGrantState(admin, packageName, permission);
diff --git a/core/java/android/app/AssistContent.aidl b/core/java/android/app/assist/AssistContent.aidl
index a6321bf..24379bb 100644
--- a/core/java/android/app/AssistContent.aidl
+++ b/core/java/android/app/assist/AssistContent.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.app;
+package android.app.assist;
parcelable AssistContent;
diff --git a/core/java/android/app/assist/AssistContent.java b/core/java/android/app/assist/AssistContent.java
new file mode 100644
index 0000000..c7e7330
--- /dev/null
+++ b/core/java/android/app/assist/AssistContent.java
@@ -0,0 +1,44 @@
+package android.app.assist;
+
+import android.content.Intent;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * New home for AssistContent.
+ */
+public final class AssistContent extends android.app.AssistContent implements Parcelable {
+
+ /** @hide */
+ public AssistContent() {
+ }
+
+ public AssistContent(Parcel in) {
+ super(in);
+ }
+
+ public Intent getIntent() {
+ return super.getIntent();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ writeToParcelInternal(dest, flags);
+ }
+
+ public static final Parcelable.Creator<AssistContent> CREATOR
+ = new Parcelable.Creator<AssistContent>() {
+ public AssistContent createFromParcel(Parcel in) {
+ return new AssistContent(in);
+ }
+
+ public AssistContent[] newArray(int size) {
+ return new AssistContent[size];
+ }
+ };
+}
diff --git a/core/java/android/app/AssistStructure.aidl b/core/java/android/app/assist/AssistStructure.aidl
index 07fb2453..ae0a34c 100644
--- a/core/java/android/app/AssistStructure.aidl
+++ b/core/java/android/app/assist/AssistStructure.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.app;
+package android.app.assist;
parcelable AssistStructure;
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
new file mode 100644
index 0000000..1677e95
--- /dev/null
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -0,0 +1,56 @@
+package android.app.assist;
+
+import android.app.Activity;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * New home for AssistStructure.
+ */
+public final class AssistStructure extends android.app.AssistStructure implements Parcelable {
+
+ public AssistStructure() {
+ }
+
+ /** @hide */
+ public AssistStructure(Activity activity) {
+ super(activity);
+ }
+
+ AssistStructure(Parcel in) {
+ super(in);
+ }
+
+ public WindowNode getWindowNodeAt(int index) {
+ return super.getWindowNodeAt(index);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ if (mHaveData) {
+ // This object holds its data. We want to write a send channel that the
+ // other side can use to retrieve that data.
+ if (mSendChannel == null) {
+ mSendChannel = new SendChannel();
+ }
+ out.writeStrongBinder(mSendChannel);
+ } else {
+ // This object doesn't hold its data, so just propagate along its receive channel.
+ out.writeStrongBinder(mReceiveChannel);
+ }
+ }
+
+ public static final Parcelable.Creator<AssistStructure> CREATOR
+ = new Parcelable.Creator<AssistStructure>() {
+ public AssistStructure createFromParcel(Parcel in) {
+ return new AssistStructure(in);
+ }
+
+ public AssistStructure[] newArray(int size) {
+ return new AssistStructure[size];
+ }
+ };
+}
diff --git a/core/java/android/app/usage/IUsageStatsManager.aidl b/core/java/android/app/usage/IUsageStatsManager.aidl
index 254408a..a9328bc 100644
--- a/core/java/android/app/usage/IUsageStatsManager.aidl
+++ b/core/java/android/app/usage/IUsageStatsManager.aidl
@@ -32,4 +32,5 @@ interface IUsageStatsManager {
UsageEvents queryEvents(long beginTime, long endTime, String callingPackage);
void setAppInactive(String packageName, boolean inactive, int userId);
boolean isAppInactive(String packageName, int userId);
+ void whitelistAppTemporarily(String packageName, long duration, int userId);
}
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 34699d8..c74b0f2 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -16,6 +16,7 @@
package android.app.usage;
+import android.annotation.SystemApi;
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.os.RemoteException;
@@ -245,4 +246,25 @@ public final class UsageStatsManager {
// fall through
}
}
+
+ /**
+ * {@hide}
+ * Temporarily whitelist the specified app for a short duration. This is to allow an app
+ * receiving a high priority message to be able to access the network and acquire wakelocks
+ * even if the device is in power-save mode or the app is currently considered inactive.
+ * The caller must hold the CHANGE_DEVICE_IDLE_TEMP_WHITELIST permission.
+ * @param packageName The package name of the app to whitelist.
+ * @param duration Duration to whitelist the app for, in milliseconds. It is recommended that
+ * this be limited to 10s of seconds. Requested duration will be clamped to a few minutes.
+ * @param user The user for whom the package should be whitelisted. Passing in a user that is
+ * not the same as the caller's process will require the INTERACT_ACROSS_USERS permission.
+ * @see #isAppInactive(String)
+ */
+ @SystemApi
+ public void whitelistAppTemporarily(String packageName, long duration, UserHandle user) {
+ try {
+ mService.whitelistAppTemporarily(packageName, duration, user.getIdentifier());
+ } catch (RemoteException re) {
+ }
+ }
}
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 8107a97..ab3f7bc 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1467,10 +1467,31 @@ public final class BluetoothAdapter {
* @hide
*/
public BluetoothServerSocket listenUsingRfcommOn(int channel) throws IOException {
+ return listenUsingRfcommOn(channel, false);
+ }
+
+ /**
+ * Create a listening, secure RFCOMM Bluetooth socket.
+ * <p>A remote device connecting to this socket will be authenticated and
+ * communication on this socket will be encrypted.
+ * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
+ * connections from a listening {@link BluetoothServerSocket}.
+ * <p>Valid RFCOMM channels are in range 1 to 30.
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
+ * <p>To auto assign a channel without creating a SDP record use
+ * {@link SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as channel number.
+ * @param channel RFCOMM channel to listen on
+ * @param mitm enforce man-in-the-middle protection for authentication.
+ * @return a listening RFCOMM BluetoothServerSocket
+ * @throws IOException on error, for example Bluetooth not available, or
+ * insufficient permissions, or channel in use.
+ * @hide
+ */
+ public BluetoothServerSocket listenUsingRfcommOn(int channel, boolean mitm) throws IOException {
BluetoothServerSocket socket = new BluetoothServerSocket(
- BluetoothSocket.TYPE_RFCOMM, true, true, channel);
+ BluetoothSocket.TYPE_RFCOMM, true, true, channel, mitm);
int errno = socket.mSocket.bindListen();
- if(channel == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
+ if (channel == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
socket.setChannel(socket.mSocket.getPort());
}
if (errno != 0) {
@@ -1669,14 +1690,18 @@ public final class BluetoothAdapter {
/**
* Construct an encrypted, authenticated, L2CAP server socket.
* Call #accept to retrieve connections to this socket.
+ * <p>To auto assign a port without creating a SDP record use
+ * {@link SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
+ * @param port the PSM to listen on
+ * @param mitm enforce man-in-the-middle protection for authentication.
* @return An L2CAP BluetoothServerSocket
* @throws IOException On error, for example Bluetooth not available, or
* insufficient permissions.
* @hide
*/
- public BluetoothServerSocket listenUsingL2capOn(int port) throws IOException {
+ public BluetoothServerSocket listenUsingL2capOn(int port, boolean mitm) throws IOException {
BluetoothServerSocket socket = new BluetoothServerSocket(
- BluetoothSocket.TYPE_L2CAP, true, true, port);
+ BluetoothSocket.TYPE_L2CAP, true, true, port, mitm);
int errno = socket.mSocket.bindListen();
if(port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
socket.setChannel(socket.mSocket.getPort());
@@ -1691,6 +1716,21 @@ public final class BluetoothAdapter {
}
/**
+ * Construct an encrypted, authenticated, L2CAP server socket.
+ * Call #accept to retrieve connections to this socket.
+ * <p>To auto assign a port without creating a SDP record use
+ * {@link SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
+ * @param port the PSM to listen on
+ * @return An L2CAP BluetoothServerSocket
+ * @throws IOException On error, for example Bluetooth not available, or
+ * insufficient permissions.
+ * @hide
+ */
+ public BluetoothServerSocket listenUsingL2capOn(int port) throws IOException {
+ return listenUsingL2capOn(port, false);
+ }
+
+ /**
* Read the local Out of Band Pairing Data
* <p>Requires {@link android.Manifest.permission#BLUETOOTH}
*
diff --git a/core/java/android/bluetooth/BluetoothServerSocket.java b/core/java/android/bluetooth/BluetoothServerSocket.java
index 21024a6..a80f55c 100644
--- a/core/java/android/bluetooth/BluetoothServerSocket.java
+++ b/core/java/android/bluetooth/BluetoothServerSocket.java
@@ -86,6 +86,26 @@ public final class BluetoothServerSocket implements Closeable {
throws IOException {
mChannel = port;
mSocket = new BluetoothSocket(type, -1, auth, encrypt, null, port, null);
+ if (port == BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
+ mSocket.setExcludeSdp(true);
+ }
+ }
+
+ /**
+ * Construct a socket for incoming connections.
+ * @param type type of socket
+ * @param auth require the remote device to be authenticated
+ * @param encrypt require the connection to be encrypted
+ * @param port remote port
+ * @param mitm enforce man-in-the-middle protection for authentication.
+ * @throws IOException On error, for example Bluetooth not available, or
+ * insufficient privileges
+ */
+ /*package*/ BluetoothServerSocket(int type, boolean auth, boolean encrypt, int port,
+ boolean mitm)
+ throws IOException {
+ mChannel = port;
+ mSocket = new BluetoothSocket(type, -1, auth, encrypt, null, port, null, mitm);
if(port == BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
mSocket.setExcludeSdp(true);
}
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index 5cf2300..6ca6976 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -106,6 +106,7 @@ public final class BluetoothSocket implements Closeable {
/*package*/ static final int SEC_FLAG_ENCRYPT = 1;
/*package*/ static final int SEC_FLAG_AUTH = 1 << 1;
/*package*/ static final int BTSOCK_FLAG_NO_SDP = 1 << 2;
+ /*package*/ static final int SEC_FLAG_AUTH_MITM = 1 << 3;
private final int mType; /* one of TYPE_RFCOMM etc */
private BluetoothDevice mDevice; /* remote device */
@@ -115,7 +116,8 @@ public final class BluetoothSocket implements Closeable {
private final BluetoothInputStream mInputStream;
private final BluetoothOutputStream mOutputStream;
private final ParcelUuid mUuid;
- private boolean mExcludeSdp = false;
+ private boolean mExcludeSdp = false; /* when true no SPP SDP record will be created */
+ private boolean mAuthMitm = false; /* when true Man-in-the-middle protection will be enabled*/
private ParcelFileDescriptor mPfd;
private LocalSocket mSocket;
private InputStream mSocketIS;
@@ -158,6 +160,24 @@ public final class BluetoothSocket implements Closeable {
*/
/*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt,
BluetoothDevice device, int port, ParcelUuid uuid) throws IOException {
+ this(type, fd, auth, encrypt, device, port, uuid, false);
+ }
+
+ /**
+ * Construct a BluetoothSocket.
+ * @param type type of socket
+ * @param fd fd to use for connected socket, or -1 for a new socket
+ * @param auth require the remote device to be authenticated
+ * @param encrypt require the connection to be encrypted
+ * @param device remote device that this socket can connect to
+ * @param port remote port
+ * @param uuid SDP uuid
+ * @param mitm enforce man-in-the-middle protection.
+ * @throws IOException On error, for example Bluetooth not available, or
+ * insufficient privileges
+ */
+ /*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt,
+ BluetoothDevice device, int port, ParcelUuid uuid, boolean mitm) throws IOException {
if (VDBG) Log.d(TAG, "Creating new BluetoothSocket of type: " + type);
if (type == BluetoothSocket.TYPE_RFCOMM && uuid == null && fd == -1
&& port != BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
@@ -170,6 +190,7 @@ public final class BluetoothSocket implements Closeable {
else mUuid = new ParcelUuid(new UUID(0, 0));
mType = type;
mAuth = auth;
+ mAuthMitm = mitm;
mEncrypt = encrypt;
mDevice = device;
mPort = port;
@@ -201,6 +222,7 @@ public final class BluetoothSocket implements Closeable {
mServiceName = s.mServiceName;
mExcludeSdp = s.mExcludeSdp;
+ mAuthMitm = s.mAuthMitm;
}
private BluetoothSocket acceptSocket(String RemoteAddr) throws IOException {
BluetoothSocket as = new BluetoothSocket(this);
@@ -232,7 +254,7 @@ public final class BluetoothSocket implements Closeable {
*/
private BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, String address,
int port) throws IOException {
- this(type, fd, auth, encrypt, new BluetoothDevice(address), port, null);
+ this(type, fd, auth, encrypt, new BluetoothDevice(address), port, null, false);
}
/** @hide */
@@ -252,6 +274,8 @@ public final class BluetoothSocket implements Closeable {
flags |= SEC_FLAG_ENCRYPT;
if(mExcludeSdp)
flags |= BTSOCK_FLAG_NO_SDP;
+ if(mAuthMitm)
+ flags |= SEC_FLAG_AUTH_MITM;
return flags;
}
diff --git a/core/java/android/bluetooth/SdpSapsRecord.java b/core/java/android/bluetooth/SdpSapsRecord.java
new file mode 100644
index 0000000..84a29b9
--- /dev/null
+++ b/core/java/android/bluetooth/SdpSapsRecord.java
@@ -0,0 +1,91 @@
+/*
+ * 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.bluetooth;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/** @hide */
+public class SdpSapsRecord implements Parcelable {
+ private final int mRfcommChannelNumber;
+ private final int mProfileVersion;
+ private final String mServiceName;
+
+ public SdpSapsRecord(int rfcomm_channel_number,
+ int profile_version,
+ String service_name) {
+ this.mRfcommChannelNumber = rfcomm_channel_number;
+ this.mProfileVersion = profile_version;
+ this.mServiceName = service_name;
+ }
+
+ public SdpSapsRecord(Parcel in) {
+ this.mRfcommChannelNumber = in.readInt();
+ this.mProfileVersion = in.readInt();
+ this.mServiceName = in.readString();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public int getRfcommCannelNumber() {
+ return mRfcommChannelNumber;
+ }
+
+ public int getProfileVersion() {
+ return mProfileVersion;
+ }
+
+ public String getServiceName() {
+ return mServiceName;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(this.mRfcommChannelNumber);
+ dest.writeInt(this.mProfileVersion);
+ dest.writeString(this.mServiceName);
+
+ }
+
+ @Override
+ public String toString() {
+ String ret = "Bluetooth MAS SDP Record:\n";
+
+ if (mRfcommChannelNumber != -1) {
+ ret += "RFCOMM Chan Number: " + mRfcommChannelNumber + "\n";
+ }
+ if (mServiceName != null) {
+ ret += "Service Name: " + mServiceName + "\n";
+ }
+ if (mProfileVersion != -1) {
+ ret += "Profile version: " + mProfileVersion + "\n";
+ }
+ return ret;
+ }
+
+ public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
+ public SdpSapsRecord createFromParcel(Parcel in) {
+ return new SdpSapsRecord(in);
+ }
+ public SdpRecord[] newArray(int size) {
+ return new SdpRecord[size];
+ }
+ };
+}
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 17a8eb7..96a80e7 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -1552,23 +1552,21 @@ public abstract class ContentResolver {
*
* @param uri The URI to watch for changes. This can be a specific row URI, or a base URI
* for a whole class of content.
- * @param notifyForDescendents If <code>true</code> changes to URIs beginning with <code>uri</code>
- * will also cause notifications to be sent. If <code>false</code> only changes to the exact URI
- * specified by <em>uri</em> will cause notifications to be sent. If <code>true</code>, any URI values
- * at or below the specified URI will also trigger a match.
+ * @param notifyForDescendents When false, the observer will be notified whenever a
+ * change occurs to the exact URI specified by <code>uri</code> or to one of the
+ * URI's ancestors in the path hierarchy. When true, the observer will also be notified
+ * whenever a change occurs to the URI's descendants in the path hierarchy.
* @param observer The object that receives callbacks when changes occur.
* @see #unregisterContentObserver
*/
public final void registerContentObserver(Uri uri, boolean notifyForDescendents,
- ContentObserver observer)
- {
+ ContentObserver observer) {
registerContentObserver(uri, notifyForDescendents, observer, UserHandle.myUserId());
}
/** @hide - designated user version */
public final void registerContentObserver(Uri uri, boolean notifyForDescendents,
- ContentObserver observer, int userHandle)
- {
+ ContentObserver observer, int userHandle) {
try {
getContentService().registerContentObserver(uri, notifyForDescendents,
observer.getContentObserver(), userHandle);
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index ddff782..00b8c71 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -105,6 +105,9 @@ interface IPackageManager {
void updatePermissionFlags(String permissionName, String packageName, int flagMask,
int flagValues, int userId);
+ boolean shouldShowRequestPermissionRationale(String permissionName,
+ String packageName, int userId);
+
boolean isProtectedBroadcast(String actionName);
int checkSignatures(String pkg1, String pkg2);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 2ca0306..45245e4 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2539,6 +2539,19 @@ public abstract class PackageManager {
@NonNull UserHandle user);
/**
+ * Gets whether you should show UI with rationale for requesting a permission.
+ * You should do this only if you do not have the permission and the context in
+ * which the permission is requested does not clearly communicate to the user
+ * what would be the benefit from grating this permission.
+ *
+ * @param permission A permission your app wants to request.
+ * @return Whether you can show permission rationale UI.
+ *
+ * @hide
+ */
+ public abstract boolean shouldShowRequestPermissionRationale(String permission);
+
+ /**
* Returns an {@link android.content.Intent} suitable for passing to
* {@link android.app.Activity#startActivityForResult(android.content.Intent, int)}
* which prompts the user to grant permissions to this application.
diff --git a/core/java/android/hardware/camera2/CameraCaptureSession.java b/core/java/android/hardware/camera2/CameraCaptureSession.java
index c22ee5f..82d40d3 100644
--- a/core/java/android/hardware/camera2/CameraCaptureSession.java
+++ b/core/java/android/hardware/camera2/CameraCaptureSession.java
@@ -471,6 +471,17 @@ public abstract class CameraCaptureSession implements AutoCloseable {
public abstract boolean isReprocessable();
/**
+ * Return if this capture session is constrained high speed session that is created by
+ * {@link CameraDevice#createConstrainedHighSpeedCaptureSession}.
+ *
+ * @return {@code true} if this session is constrained high speed capture session,
+ * {@code false} otherwise.
+ *
+ * @see CameraDevice#createConstrainedHighSpeedCaptureSession
+ */
+ public abstract boolean isConstrainedHighSpeed();
+
+ /**
* Get the input Surface associated with a reprocessable capture session.
*
* <p>Each reprocessable capture session has an input {@link Surface} where the reprocess
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index d5867a9..b69ca88 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -626,35 +626,54 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
new Key<Integer>("android.control.maxRegionsAf", int.class);
/**
- * <p>List of available high speed video size and fps range configurations
- * supported by the camera device, in the format of (width, height, fps_min, fps_max).</p>
- * <p>When HIGH_SPEED_VIDEO is supported in {@link CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES android.control.availableSceneModes}, this metadata
- * will list the supported high speed video size and fps range configurations. All the sizes
- * listed in this configuration will be a subset of the sizes reported by {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputSizes } for processed
- * non-stalling formats.</p>
- * <p>For the high speed video use case, where the application will set
- * {@link CaptureRequest#CONTROL_SCENE_MODE android.control.sceneMode} to HIGH_SPEED_VIDEO in capture requests, the application must
+ * <p>List of available high speed video size, fps range and max batch size configurations
+ * supported by the camera device, in the format of (width, height, fps_min, fps_max, batch_size_max).</p>
+ * <p>When CONSTRAINED_HIGH_SPEED_VIDEO is supported in android.control.availableCapabilities,
+ * this metadata will list the supported high speed video size, fps range and max batch size
+ * configurations. All the sizes listed in this configuration will be a subset of the sizes
+ * reported by {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputSizes }
+ * for processed non-stalling formats.</p>
+ * <p>For the high speed video use case, the application must
* select the video size and fps range from this metadata to configure the recording and
* preview streams and setup the recording requests. For example, if the application intends
* to do high speed recording, it can select the maximum size reported by this metadata to
* configure output streams. Once the size is selected, application can filter this metadata
* by selected size and get the supported fps ranges, and use these fps ranges to setup the
* recording requests. Note that for the use case of multiple output streams, application
- * must select one unique size from this metadata to use. Otherwise a request error might
- * occur.</p>
- * <p>For normal video recording use case, where some application will NOT set
- * {@link CaptureRequest#CONTROL_SCENE_MODE android.control.sceneMode} to HIGH_SPEED_VIDEO in capture requests, the fps ranges
- * reported in this metadata must not be used to setup capture requests, or it will cause
- * request error.</p>
+ * must select one unique size from this metadata to use (e.g., preview and recording streams
+ * must have the same size). Otherwise, the high speed capture session creation will fail.</p>
+ * <p>The min and max fps will be multiple times of 30fps.</p>
+ * <p>High speed video streaming extends significant performance pressue to camera hardware,
+ * to achieve efficient high speed streaming, the camera device may have to aggregate
+ * multiple frames together and send to camera device for processing where the request
+ * controls are same for all the frames in this batch. Max batch size indicates
+ * the max possible number of frames the camera device will group together for this high
+ * speed stream configuration. This max batch size will be used to generate a high speed
+ * recording request list by
+ * {@link android.hardware.camera2.CameraDevice#createConstrainedHighSpeedRequestList }.
+ * The max batch size for each configuration will satisfy below conditions:</p>
+ * <ul>
+ * <li>Each max batch size will be a divisor of its corresponding fps_max / 30. For example,
+ * if max_fps is 300, max batch size will only be 1, 2, 5, or 10.</li>
+ * <li>The camera device may choose smaller internal batch size for each configuration, but
+ * the actual batch size will be a divisor of max batch size. For example, if the max batch
+ * size is 8, the actual batch size used by camera device will only be 1, 2, 4, or 8.</li>
+ * <li>The max batch size in each configuration entry must be no larger than 32.</li>
+ * </ul>
+ * <p>The camera device doesn't have to support batch mode to achieve high speed video recording,
+ * in such case, batch_size_max will be reported as 1 in each configuration entry.</p>
+ * <p>This fps ranges in this configuration list can only be used to create requests
+ * that are submitted to a high speed camera capture session created by
+ * {@link android.hardware.camera2.CameraDevice#createConstrainedHighSpeedCaptureSession }.
+ * The fps ranges reported in this metadata must not be used to setup capture requests for
+ * normal capture session, or it will cause request error.</p>
* <p><b>Range of valid values:</b><br></p>
- * <p>For each configuration, the fps_max &gt;= 60fps.</p>
+ * <p>For each configuration, the fps_max &gt;= 120fps.</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
* <p><b>Limited capability</b> -
* Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the
* {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p>
*
- * @see CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES
- * @see CaptureRequest#CONTROL_SCENE_MODE
* @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
* @hide
*/
@@ -1003,12 +1022,33 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
/**
* <p>Position of the camera optical center.</p>
- * <p>As measured in the device sensor coordinate system, the
- * position of the camera device's optical center, as a
- * three-dimensional vector <code>(x,y,z)</code>.</p>
- * <p>To transform a world position to a camera-device centered
- * coordinate system, the position must be translated by this
- * vector and then rotated by {@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation}.</p>
+ * <p>The position of the camera device's lens optical center,
+ * as a three-dimensional vector <code>(x,y,z)</code>, relative to the
+ * optical center of the largest camera device facing in the
+ * same direction as this camera, in the {@link android.hardware.SensorEvent Android sensor coordinate
+ * axes}. Note that only the axis definitions are shared with
+ * the sensor coordinate system, but not the origin.</p>
+ * <p>If this device is the largest or only camera device with a
+ * given facing, then this position will be <code>(0, 0, 0)</code>; a
+ * camera device with a lens optical center located 3 cm from
+ * the main sensor along the +X axis (to the right from the
+ * user's perspective) will report <code>(0.03, 0, 0)</code>.</p>
+ * <p>To transform a pixel coordinates between two cameras
+ * facing the same direction, first the source camera
+ * android.lens.radialDistortion must be corrected for. Then
+ * the source camera android.lens.intrinsicCalibration needs
+ * to be applied, followed by the {@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation}
+ * of the source camera, the translation of the source camera
+ * relative to the destination camera, the
+ * {@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation} of the destination camera, and
+ * finally the inverse of android.lens.intrinsicCalibration
+ * of the destination camera. This obtains a
+ * radial-distortion-free coordinate in the destination
+ * camera pixel coordinates.</p>
+ * <p>To compare this against a real image from the destination
+ * camera, the destination camera image then needs to be
+ * corrected for radial distortion before comparison or
+ * sampling.</p>
* <p><b>Units</b>: Meters</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
@@ -1308,7 +1348,8 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
* the max pipeline depth.</p>
* <p>A pipeline depth of X stages is equivalent to a pipeline latency of
* X frame intervals.</p>
- * <p>This value will be 8 or less.</p>
+ * <p>This value will normally be 8 or less, however, for high speed capture session,
+ * the max pipeline depth will be up to 8 x size of high speed capture request list.</p>
* <p>This key is available on all devices.</p>
*
* @see CaptureResult#REQUEST_PIPELINE_DEPTH
@@ -1371,6 +1412,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
* <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE BURST_CAPTURE}</li>
* <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING YUV_REPROCESSING}</li>
* <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT DEPTH_OUTPUT}</li>
+ * <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO CONSTRAINED_HIGH_SPEED_VIDEO}</li>
* </ul></p>
* <p>This key is available on all devices.</p>
*
@@ -1384,6 +1426,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
* @see #REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE
* @see #REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING
* @see #REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT
+ * @see #REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO
*/
@PublicKey
public static final Key<int[]> REQUEST_AVAILABLE_CAPABILITIES =
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index d02f349..006030c 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -583,6 +583,147 @@ public abstract class CameraDevice implements AutoCloseable {
throws CameraAccessException;
/**
+ * <p>Create a new constrained high speed capture session.</p>
+ *
+ * <p>The application can use normal capture session (created via {@link #createCaptureSession})
+ * for high speed capture if the desired high speed FPS ranges are advertised by
+ * {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES}, in which case all API
+ * semantics associated with normal capture sessions applies.</p>
+ *
+ * <p>The method creates a specialized capture session that is only targeted at high speed
+ * video recording (>=120fps) use case if the camera device supports high speed video
+ * capability (i.e., {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} contains
+ * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO}).
+ * Therefore, it has special characteristics compared with a normal capture session:</p>
+ *
+ * <ul>
+ *
+ * <li>In addition to the output target Surface requirements specified by the
+ * {@link #createCaptureSession} method, an active high speed capture session will support up
+ * to 2 output Surfaces, though the application might choose to configure just one Surface
+ * (e.g., preview only). All Surfaces must be either video encoder surfaces (acquired by
+ * {@link android.media.MediaRecorder#getSurface} or
+ * {@link android.media.MediaCodec#createInputSurface}) or preview surfaces (obtained from
+ * {@link android.view.SurfaceView}, {@link android.graphics.SurfaceTexture} via
+ * {@link android.view.Surface#Surface(android.graphics.SurfaceTexture)}). The Surface sizes
+ * must be one of the sizes reported by {@link StreamConfigurationMap#getHighSpeedVideoSizes}.
+ * When multiple Surfaces are configured, their size must be same.</li>
+ *
+ * <li>An active high speed capture session only accepts request lists created via
+ * {@link #createConstrainedHighSpeedRequestList}, and the request list can only be submitted
+ * to this session via {@link CameraCaptureSession#captureBurst captureBurst}, or
+ * {@link CameraCaptureSession#setRepeatingBurst setRepeatingBurst}.</li>
+ *
+ * <li>The FPS ranges being requested to this session must be selected from
+ * {@link StreamConfigurationMap#getHighSpeedVideoFpsRangesFor}. The application can still use
+ * {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE} to control the desired FPS range.
+ * Switching to an FPS range that has different
+ * {@link android.util.Range#getUpper() maximum FPS} may trigger some camera device
+ * reconfigurations, which may introduce extra latency. It is recommended that the
+ * application avoids unnecessary maximum target FPS changes as much as possible during high
+ * speed streaming.</li>
+ *
+ * <li>For the request lists submitted to this session, the camera device will override the
+ * {@link CaptureRequest#CONTROL_MODE control mode}, auto-exposure (AE), auto-white balance
+ * (AWB) and auto-focus (AF) to {@link CameraMetadata#CONTROL_MODE_AUTO},
+ * {@link CameraMetadata#CONTROL_AE_MODE_ON}, {@link CameraMetadata#CONTROL_AWB_MODE_AUTO}
+ * and {@link CameraMetadata#CONTROL_AF_MODE_CONTINUOUS_VIDEO}, respectively. All
+ * post-processing block mode controls will be overridden to be FAST. Therefore, no manual
+ * control of capture and post-processing parameters is possible. Beside these, only a subset
+ * of controls will work, see
+ * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO} for
+ * more details.</li>
+ *
+ * </ul>
+ *
+ * @param outputs The new set of Surfaces that should be made available as
+ * targets for captured high speed image data.
+ * @param callback The callback to notify about the status of the new capture session.
+ * @param handler The handler on which the callback should be invoked, or {@code null} to use
+ * the current thread's {@link android.os.Looper looper}.
+ *
+ * @throws IllegalArgumentException if the set of output Surfaces do not meet the requirements,
+ * the callback is null, or the handler is null but the current
+ * thread has no looper, or the camera device doesn't support
+ * high speed video capability.
+ * @throws CameraAccessException if the camera device is no longer connected or has
+ * encountered a fatal error
+ * @throws IllegalStateException if the camera device has been closed
+ *
+ * @see #createCaptureSession
+ * @see CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE
+ * @see StreamConfigurationMap#getHighSpeedVideoSizes
+ * @see StreamConfigurationMap#getHighSpeedVideoFpsRangesFor
+ * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
+ * @see CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO
+ * @see CameraCaptureSession#captureBurst
+ * @see CameraCaptureSession#setRepeatingBurst
+ * @see #createConstrainedHighSpeedRequestList
+ */
+ public abstract void createConstrainedHighSpeedCaptureSession(@NonNull List<Surface> outputs,
+ @NonNull CameraCaptureSession.StateCallback callback,
+ @Nullable Handler handler)
+ throws CameraAccessException;
+
+
+ /**
+ * <p>Create a unmodifiable list of requests that is suitable for constrained high speed capture
+ * session streaming.</p>
+ *
+ * <p>High speed video streaming creates significant performance pressue on the camera device,
+ * so to achieve efficient high speed streaming, the camera device may have to aggregate
+ * multiple frames together. This means requests must be sent in batched groups, with all
+ * requests sharing the same settings. This method takes the list of output target
+ * Surfaces (subject to the output Surface requirements specified by the contrained high speed
+ * session) and a {@link CaptureRequest request}, and generates a request list that has the same
+ * controls for each request. The input {@link CaptureRequest request} must contain the target
+ * output Surfaces and target high speed FPS range that is one of the
+ * {@link StreamConfigurationMap#getHighSpeedVideoFpsRangesFor} for the Surface size.</p>
+ *
+ * <p>If both preview and recording Surfaces are specified in the {@code request}, the
+ * {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE target FPS range} in the input
+ * {@link CaptureRequest request} must be a fixed framerate FPS range, where the
+ * {@link android.util.Range#getLower minimal FPS} ==
+ * {@link android.util.Range#getUpper() maximum FPS}. The created request list will contain
+ * a interleaved request pattern such that the preview output FPS is at least 30fps, the
+ * recording output FPS is {@link android.util.Range#getUpper() maximum FPS} of the requested
+ * FPS range. The application can submit this request list directly to an active high speed
+ * capture session to achieve high speed video recording. When only preview or recording
+ * Surface is specified, this method will return a list of request that have the same controls
+ * and output targets for all requests.</p>
+ *
+ * <p>Submitting a request list created by this method to a normal capture session will result
+ * in an {@link IllegalArgumentException} if the high speed
+ * {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE FPS range} is not supported by
+ * {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES}.</p>
+ *
+ * @param request The high speed capture request that will be used to generate the high speed
+ * request list.
+ * @return A unmodifiable CaptureRequest list that is suitable for constrained high speed
+ * capture.
+ *
+ * @throws IllegalArgumentException if the set of output Surfaces in the request do not meet the
+ * high speed video capability requirements, or the camera
+ * device doesn't support high speed video capability, or the
+ * request doesn't meet the high speed video capability
+ * requirements, or the request doesn't contain the required
+ * controls for high speed capture.
+ * @throws CameraAccessException if the camera device is no longer connected or has
+ * encountered a fatal error
+ * @throws IllegalStateException if the camera device has been closed
+ *
+ * @see #createConstrainedHighSpeedCaptureSession
+ * @see CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE
+ * @see StreamConfigurationMap#getHighSpeedVideoSizes
+ * @see StreamConfigurationMap#getHighSpeedVideoFpsRangesFor
+ * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
+ * @see CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO
+ */
+ @NonNull
+ public abstract List<CaptureRequest> createConstrainedHighSpeedRequestList(
+ @NonNull CaptureRequest request)throws CameraAccessException;
+
+ /**
* <p>Create a {@link CaptureRequest.Builder} for new capture requests,
* initialized with template for a target use case. The settings are chosen
* to be the best options for the specific camera device, so it is not
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 0f002a9..0fb6889 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -802,12 +802,9 @@ public final class CameraManager {
*/
public ICameraService getCameraService() {
synchronized(mLock) {
+ connectCameraServiceLocked();
if (mCameraService == null) {
- Log.i(TAG, "getCameraService: Reconnecting to camera service");
- connectCameraServiceLocked();
- if (mCameraService == null) {
- Log.e(TAG, "Camera service is unavailable");
- }
+ Log.e(TAG, "Camera service is unavailable");
}
return mCameraService;
}
@@ -815,11 +812,16 @@ public final class CameraManager {
/**
* Connect to the camera service if it's available, and set up listeners.
+ * If the service is already connected, do nothing.
*
* <p>Sets mCameraService to a valid pointer or null if the connection does not succeed.</p>
*/
private void connectCameraServiceLocked() {
- mCameraService = null;
+ // Only reconnect if necessary
+ if (mCameraService != null) return;
+
+ Log.i(TAG, "Connecting to camera service");
+
IBinder cameraServiceBinder = ServiceManager.getService(CAMERA_SERVICE_BINDER_NAME);
if (cameraServiceBinder == null) {
// Camera service is now down, leave mCameraService as null
@@ -1098,6 +1100,8 @@ public final class CameraManager {
*/
public void registerAvailabilityCallback(AvailabilityCallback callback, Handler handler) {
synchronized (mLock) {
+ connectCameraServiceLocked();
+
Handler oldHandler = mCallbackMap.put(callback, handler);
// For new callbacks, provide initial availability information
if (oldHandler == null) {
@@ -1120,6 +1124,8 @@ public final class CameraManager {
public void registerTorchCallback(TorchCallback callback, Handler handler) {
synchronized(mLock) {
+ connectCameraServiceLocked();
+
Handler oldHandler = mTorchCallbackMap.put(callback, handler);
// For new callbacks, provide initial torch information
if (oldHandler == null) {
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index ac29f80..f8db6d9 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -648,6 +648,100 @@ public abstract class CameraMetadata<TKey> {
*/
public static final int REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT = 8;
+ /**
+ * <p>The device supports constrained high speed video recording (frame rate &gt;=120fps)
+ * use case. The camera device will support high speed capture session created by
+ * {@link android.hardware.camera2.CameraDevice#createConstrainedHighSpeedCaptureSession }, which
+ * only accepts high speed request list created by
+ * {@link android.hardware.camera2.CameraDevice#createConstrainedHighSpeedRequestList }.</p>
+ * <p>A camera device can still support high speed video streaming by advertising the high speed
+ * FPS ranges in {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES android.control.aeAvailableTargetFpsRanges}. For this case, all normal
+ * capture request per frame control and synchronization requirements will apply to
+ * the high speed fps ranges, the same as all other fps ranges. This capability describes
+ * the capability of a specialized operating mode with many limitations (see below), which
+ * is only targeted at high speed video recording.</p>
+ * <p>The supported high speed video sizes and fps ranges are specified in
+ * {@link android.hardware.camera2.params.StreamConfigurationMap#getHighSpeedVideoFpsRanges }.
+ * To get desired output frame rates, the application is only allowed to select video size
+ * and FPS range combinations provided by
+ * {@link android.hardware.camera2.params.StreamConfigurationMap#getHighSpeedVideoSizes }.
+ * The fps range can be controlled via {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE android.control.aeTargetFpsRange}.</p>
+ * <p>In this capability, the camera device will override aeMode, awbMode, and afMode to
+ * ON, ON, and CONTINUOUS_VIDEO, respectively. All post-processing block mode
+ * controls will be overridden to be FAST. Therefore, no manual control of capture
+ * and post-processing parameters is possible. All other controls operate the
+ * same as when {@link CaptureRequest#CONTROL_MODE android.control.mode} == AUTO. This means that all other
+ * android.control.* fields continue to work, such as</p>
+ * <ul>
+ * <li>{@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE android.control.aeTargetFpsRange}</li>
+ * <li>{@link CaptureRequest#CONTROL_AE_EXPOSURE_COMPENSATION android.control.aeExposureCompensation}</li>
+ * <li>{@link CaptureRequest#CONTROL_AE_LOCK android.control.aeLock}</li>
+ * <li>{@link CaptureRequest#CONTROL_AWB_LOCK android.control.awbLock}</li>
+ * <li>{@link CaptureRequest#CONTROL_EFFECT_MODE android.control.effectMode}</li>
+ * <li>{@link CaptureRequest#CONTROL_AE_REGIONS android.control.aeRegions}</li>
+ * <li>{@link CaptureRequest#CONTROL_AF_REGIONS android.control.afRegions}</li>
+ * <li>{@link CaptureRequest#CONTROL_AWB_REGIONS android.control.awbRegions}</li>
+ * <li>{@link CaptureRequest#CONTROL_AF_TRIGGER android.control.afTrigger}</li>
+ * <li>{@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger}</li>
+ * </ul>
+ * <p>Outside of android.control.*, the following controls will work:</p>
+ * <ul>
+ * <li>{@link CaptureRequest#FLASH_MODE android.flash.mode} (TORCH mode only, automatic flash for still capture will not
+ * work since aeMode is ON)</li>
+ * <li>{@link CaptureRequest#LENS_OPTICAL_STABILIZATION_MODE android.lens.opticalStabilizationMode} (if it is supported)</li>
+ * <li>{@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}</li>
+ * <li>{@link CaptureRequest#STATISTICS_FACE_DETECT_MODE android.statistics.faceDetectMode} (if it is supported)</li>
+ * </ul>
+ * <p>For high speed recording use case, the actual maximum supported frame rate may
+ * be lower than what camera can output, depending on the destination Surfaces for
+ * the image data. For example, if the destination surface is from video encoder,
+ * the application need check if the video encoder is capable of supporting the
+ * high frame rate for a given video size, or it will end up with lower recording
+ * frame rate. If the destination surface is from preview window, the actual preview frame
+ * rate will be bounded by the screen refresh rate.</p>
+ * <p>The camera device will only support up to 2 high speed simultaneous output surfaces
+ * (preview and recording surfaces)
+ * in this mode. Above controls will be effective only if all of below conditions are true:</p>
+ * <ul>
+ * <li>The application creates a camera capture session with no more than 2 surfaces via
+ * {@link android.hardware.camera2.CameraDevice#createConstrainedHighSpeedCaptureSession }. The
+ * targeted surfaces must be preview surface (either from
+ * {@link android.view.SurfaceView } or {@link android.graphics.SurfaceTexture }) or
+ * recording surface(either from {@link android.media.MediaRecorder#getSurface } or
+ * {@link android.media.MediaCodec#createInputSurface }).</li>
+ * <li>The stream sizes are selected from the sizes reported by
+ * {@link android.hardware.camera2.params.StreamConfigurationMap#getHighSpeedVideoSizes }.</li>
+ * <li>The FPS ranges are selected from
+ * {@link android.hardware.camera2.params.StreamConfigurationMap#getHighSpeedVideoFpsRanges }.</li>
+ * </ul>
+ * <p>When above conditions are NOT satistied, the
+ * {@link android.hardware.camera2.CameraDevice#createConstrainedHighSpeedCaptureSession }
+ * and {@link android.hardware.camera2.CameraDevice#createConstrainedHighSpeedRequestList } will fail.</p>
+ * <p>Switching to a FPS range that has different maximum FPS may trigger some camera device
+ * reconfigurations, which may introduce extra latency. It is recommended that
+ * the application avoids unnecessary maximum target FPS changes as much as possible
+ * during high speed streaming.</p>
+ *
+ * @see CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES
+ * @see CaptureRequest#CONTROL_AE_EXPOSURE_COMPENSATION
+ * @see CaptureRequest#CONTROL_AE_LOCK
+ * @see CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER
+ * @see CaptureRequest#CONTROL_AE_REGIONS
+ * @see CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE
+ * @see CaptureRequest#CONTROL_AF_REGIONS
+ * @see CaptureRequest#CONTROL_AF_TRIGGER
+ * @see CaptureRequest#CONTROL_AWB_LOCK
+ * @see CaptureRequest#CONTROL_AWB_REGIONS
+ * @see CaptureRequest#CONTROL_EFFECT_MODE
+ * @see CaptureRequest#CONTROL_MODE
+ * @see CaptureRequest#FLASH_MODE
+ * @see CaptureRequest#LENS_OPTICAL_STABILIZATION_MODE
+ * @see CaptureRequest#SCALER_CROP_REGION
+ * @see CaptureRequest#STATISTICS_FACE_DETECT_MODE
+ * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
+ */
+ public static final int REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO = 9;
+
//
// Enumeration values for CameraCharacteristics#SCALER_CROPPING_TYPE
//
@@ -1725,6 +1819,10 @@ public abstract class CameraMetadata<TKey> {
public static final int CONTROL_SCENE_MODE_BARCODE = 16;
/**
+ * <p>This is deprecated, please use
+ * {@link android.hardware.camera2.CameraDevice#createConstrainedHighSpeedCaptureSession }
+ * and {@link android.hardware.camera2.CameraDevice#createConstrainedHighSpeedRequestList }
+ * for high speed video recording.</p>
* <p>Optimized for high speed video recording (frame rate &gt;=60fps) use case.</p>
* <p>The supported high speed video sizes and fps ranges are specified in
* android.control.availableHighSpeedVideoConfigurations. To get desired
@@ -1799,6 +1897,7 @@ public abstract class CameraMetadata<TKey> {
* @see CaptureRequest#SCALER_CROP_REGION
* @see CaptureRequest#STATISTICS_FACE_DETECT_MODE
* @see CaptureRequest#CONTROL_SCENE_MODE
+ * @deprecated Please refer to this API documentation to find the alternatives
*/
public static final int CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO = 17;
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index df6c986..3bb2fdb 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -2584,12 +2584,33 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> {
/**
* <p>Position of the camera optical center.</p>
- * <p>As measured in the device sensor coordinate system, the
- * position of the camera device's optical center, as a
- * three-dimensional vector <code>(x,y,z)</code>.</p>
- * <p>To transform a world position to a camera-device centered
- * coordinate system, the position must be translated by this
- * vector and then rotated by {@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation}.</p>
+ * <p>The position of the camera device's lens optical center,
+ * as a three-dimensional vector <code>(x,y,z)</code>, relative to the
+ * optical center of the largest camera device facing in the
+ * same direction as this camera, in the {@link android.hardware.SensorEvent Android sensor coordinate
+ * axes}. Note that only the axis definitions are shared with
+ * the sensor coordinate system, but not the origin.</p>
+ * <p>If this device is the largest or only camera device with a
+ * given facing, then this position will be <code>(0, 0, 0)</code>; a
+ * camera device with a lens optical center located 3 cm from
+ * the main sensor along the +X axis (to the right from the
+ * user's perspective) will report <code>(0.03, 0, 0)</code>.</p>
+ * <p>To transform a pixel coordinates between two cameras
+ * facing the same direction, first the source camera
+ * android.lens.radialDistortion must be corrected for. Then
+ * the source camera android.lens.intrinsicCalibration needs
+ * to be applied, followed by the {@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation}
+ * of the source camera, the translation of the source camera
+ * relative to the destination camera, the
+ * {@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation} of the destination camera, and
+ * finally the inverse of android.lens.intrinsicCalibration
+ * of the destination camera. This obtains a
+ * radial-distortion-free coordinate in the destination
+ * camera pixel coordinates.</p>
+ * <p>To compare this against a real image from the destination
+ * camera, the destination camera image then needs to be
+ * corrected for radial distortion before comparison or
+ * sampling.</p>
* <p><b>Units</b>: Meters</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
index 7a39dd5..ab0f607 100644
--- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
@@ -721,4 +721,10 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession {
}
}
+ @Override
+ public boolean isConstrainedHighSpeed() {
+ // TODO: to be implemented
+ return false;
+ }
+
}
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index e60e266..ad0cd0f 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -906,7 +906,6 @@ public class CameraDeviceImpl extends CameraDevice {
}
mRemoteDevice = null;
- mInError = false;
}
}
@@ -1889,13 +1888,13 @@ public class CameraDeviceImpl extends CameraDevice {
}
private void checkIfCameraClosedOrInError() throws CameraAccessException {
+ if (mRemoteDevice == null) {
+ throw new IllegalStateException("CameraDevice was already closed");
+ }
if (mInError) {
throw new CameraAccessException(CameraAccessException.CAMERA_ERROR,
"The camera device has encountered a serious error");
}
- if (mRemoteDevice == null) {
- throw new IllegalStateException("CameraDevice was already closed");
- }
}
/** Whether the camera device has started to close (may not yet have finished) */
@@ -1906,4 +1905,18 @@ public class CameraDeviceImpl extends CameraDevice {
private CameraCharacteristics getCharacteristics() {
return mCharacteristics;
}
+
+ @Override
+ public void createConstrainedHighSpeedCaptureSession(List<Surface> outputs,
+ android.hardware.camera2.CameraCaptureSession.StateCallback callback, Handler handler)
+ throws CameraAccessException {
+ // TODO: to be implemented
+ throw new UnsupportedOperationException("To be implemented!!!!");
+ }
+
+ @Override
+ public List<CaptureRequest> createConstrainedHighSpeedRequestList(CaptureRequest request)
+ throws CameraAccessException {
+ throw new UnsupportedOperationException("To be implemented!!!!");
+ }
}
diff --git a/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableHighSpeedVideoConfiguration.java b/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableHighSpeedVideoConfiguration.java
index c03144b..2449abe 100644
--- a/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableHighSpeedVideoConfiguration.java
+++ b/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableHighSpeedVideoConfiguration.java
@@ -33,7 +33,7 @@ import java.nio.ByteBuffer;
*/
public class MarshalQueryableHighSpeedVideoConfiguration
implements MarshalQueryable<HighSpeedVideoConfiguration> {
- private static final int SIZE = SIZEOF_INT32 * 4;
+ private static final int SIZE = SIZEOF_INT32 * 5;
private class MarshalerHighSpeedVideoConfiguration
extends Marshaler<HighSpeedVideoConfiguration> {
@@ -49,6 +49,7 @@ public class MarshalQueryableHighSpeedVideoConfiguration
buffer.putInt(value.getHeight());
buffer.putInt(value.getFpsMin());
buffer.putInt(value.getFpsMax());
+ buffer.putInt(value.getBatchSizeMax());
}
@Override
@@ -57,8 +58,9 @@ public class MarshalQueryableHighSpeedVideoConfiguration
int height = buffer.getInt();
int fpsMin = buffer.getInt();
int fpsMax = buffer.getInt();
+ int batchSizeMax = buffer.getInt();
- return new HighSpeedVideoConfiguration(width, height, fpsMin, fpsMax);
+ return new HighSpeedVideoConfiguration(width, height, fpsMin, fpsMax, batchSizeMax);
}
@Override
diff --git a/core/java/android/hardware/camera2/params/HighSpeedVideoConfiguration.java b/core/java/android/hardware/camera2/params/HighSpeedVideoConfiguration.java
index 088049f..b469126 100644
--- a/core/java/android/hardware/camera2/params/HighSpeedVideoConfiguration.java
+++ b/core/java/android/hardware/camera2/params/HighSpeedVideoConfiguration.java
@@ -33,6 +33,7 @@ import android.util.Size;
* @hide
*/
public final class HighSpeedVideoConfiguration {
+ static final private int HIGH_SPEED_MAX_MINIMAL_FPS = 120;
/**
* Create a new {@link HighSpeedVideoConfiguration}.
@@ -48,15 +49,18 @@ public final class HighSpeedVideoConfiguration {
* @hide
*/
public HighSpeedVideoConfiguration(
- final int width, final int height, final int fpsMin, final int fpsMax) {
- if (fpsMax < 60) {
- throw new IllegalArgumentException("fpsMax must be at least 60");
+ final int width, final int height, final int fpsMin, final int fpsMax,
+ final int batchSizeMax) {
+ if (fpsMax < HIGH_SPEED_MAX_MINIMAL_FPS) {
+ throw new IllegalArgumentException("fpsMax must be at least " +
+ HIGH_SPEED_MAX_MINIMAL_FPS);
}
mFpsMax = fpsMax;
mWidth = checkArgumentPositive(width, "width must be positive");
mHeight = checkArgumentPositive(height, "height must be positive");
mFpsMin = checkArgumentPositive(fpsMin, "fpsMin must be positive");
mSize = new Size(mWidth, mHeight);
+ mBatchSizeMax = checkArgumentPositive(batchSizeMax, "batchSizeMax must be positive");
mFpsRange = new Range<Integer>(mFpsMin, mFpsMax);
}
@@ -106,9 +110,18 @@ public final class HighSpeedVideoConfiguration {
}
/**
+ * Convenience method to return the max batch size of this high speed video configuration.
+ *
+ * @return the maximal batch size for this high speed video configuration
+ */
+ public int getBatchSizeMax() {
+ return mBatchSizeMax;
+ }
+
+ /**
* Convenience method to return the FPS range of this high speed video configuration.
*
- * @return a Range with high bound >= 60
+ * @return a Range with high bound >= {@value #HIGH_SPEED_MAX_MINIMAL_FPS}
*/
public Range<Integer> getFpsRange() {
return mFpsRange;
@@ -135,7 +148,8 @@ public final class HighSpeedVideoConfiguration {
return mWidth == other.mWidth &&
mHeight == other.mHeight &&
mFpsMin == other.mFpsMin &&
- mFpsMax == other.mFpsMax;
+ mFpsMax == other.mFpsMax &&
+ mBatchSizeMax == other.mBatchSizeMax;
}
return false;
}
@@ -152,6 +166,7 @@ public final class HighSpeedVideoConfiguration {
private final int mHeight;
private final int mFpsMin;
private final int mFpsMax;
+ private final int mBatchSizeMax;
private final Size mSize;
private final Range<Integer> mFpsRange;
}
diff --git a/core/java/android/net/IpReachabilityMonitor.java b/core/java/android/net/IpReachabilityMonitor.java
index 3cfd8b2..88fb014 100644
--- a/core/java/android/net/IpReachabilityMonitor.java
+++ b/core/java/android/net/IpReachabilityMonitor.java
@@ -99,16 +99,10 @@ public class IpReachabilityMonitor {
public static boolean probeNeighbor(int ifIndex, InetAddress ip) {
final long IO_TIMEOUT = 300L;
final String msgSnippet = "probing ip=" + ip.getHostAddress() + "%" + ifIndex;
- // This currently does not cause neighbor probing if the target |ip|
- // has been confirmed reachable within the past "delay_probe_time"
- // seconds, i.e. within the past 5 seconds.
- //
- // TODO: replace with a transition directly to NUD_PROBE state once
- // kernels are updated to do so correctly.
if (DBG) { Log.d(TAG, msgSnippet); }
final byte[] msg = RtNetlinkNeighborMessage.newNewNeighborMessage(
- 1, ip, StructNdMsg.NUD_DELAY, ifIndex, null);
+ 1, ip, StructNdMsg.NUD_PROBE, ifIndex, null);
boolean returnValue = false;
try (NetlinkSocket nlSocket = new NetlinkSocket(OsConstants.NETLINK_ROUTE)) {
diff --git a/core/java/android/os/IDeviceIdleController.aidl b/core/java/android/os/IDeviceIdleController.aidl
index 602bfea..268295d 100644
--- a/core/java/android/os/IDeviceIdleController.aidl
+++ b/core/java/android/os/IDeviceIdleController.aidl
@@ -16,6 +16,8 @@
package android.os;
+import android.os.UserHandle;
+
/** @hide */
interface IDeviceIdleController {
void addPowerSaveWhitelistApp(String name);
@@ -23,5 +25,7 @@ interface IDeviceIdleController {
String[] getSystemPowerWhitelist();
String[] getFullPowerWhitelist();
int[] getAppIdWhitelist();
+ int[] getAppIdTempWhitelist();
boolean isPowerSaveWhitelistApp(String name);
+ void addPowerSaveTempWhitelistApp(String name, long duration, int userId);
}
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 1d9d7d2..8b18f32 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -928,6 +928,14 @@ public final class PowerManager {
= "android.os.action.POWER_SAVE_WHITELIST_CHANGED";
/**
+ * @hide Intent that is broadcast when the set of temporarily whitelisted apps has changed.
+ * This broadcast is only sent to registered receivers.
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED
+ = "android.os.action.POWER_SAVE_TEMP_WHITELIST_CHANGED";
+
+ /**
* Intent that is broadcast when the state of {@link #isPowerSaveMode()} is about to change.
* This broadcast is only sent to registered receivers.
*
diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java
index e523285..e742f98 100644
--- a/core/java/android/os/PowerManagerInternal.java
+++ b/core/java/android/os/PowerManagerInternal.java
@@ -137,6 +137,8 @@ public abstract class PowerManagerInternal {
public abstract void setDeviceIdleWhitelist(int[] appids);
+ public abstract void setDeviceIdleTempWhitelist(int[] appids);
+
public abstract void updateUidProcState(int uid, int procState);
public abstract void uidGone(int uid);
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 76a5f967..df2e5f9 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -7930,8 +7930,6 @@ public final class ContactsContract {
/**
* API for inquiring about the general status of the provider.
- *
- * @hide
*/
public static final class ProviderStatus {
@@ -7965,21 +7963,16 @@ public final class ContactsContract {
public static final int STATUS_NORMAL = 0;
/**
- * The status used when the provider is in the process of upgrading. Contacts
- * are temporarily unaccessible.
- */
- public static final int STATUS_UPGRADING = 1;
-
- /**
- * The status used during a locale change.
+ * The provider won't respond to queries. It is in the middle of a long running task, such
+ * as a database upgrade or locale change.
*/
- public static final int STATUS_CHANGING_LOCALE = 3;
+ public static final int STATUS_BUSY = 1;
/**
* The status that indicates that there are no accounts and no contacts
* on the device.
*/
- public static final int STATUS_NO_ACCOUNTS_NO_CONTACTS = 4;
+ public static final int STATUS_EMPTY = 2;
}
/**
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 7565654b..51dbdee 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -22,6 +22,7 @@ import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
+import android.content.Intent;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteException;
@@ -33,6 +34,7 @@ import android.media.ThumbnailUtils;
import android.net.Uri;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
+import android.service.media.CameraPrewarmService;
import android.util.Log;
import java.io.FileInputStream;
@@ -226,33 +228,24 @@ public final class MediaStore {
public static final String INTENT_ACTION_STILL_IMAGE_CAMERA = "android.media.action.STILL_IMAGE_CAMERA";
/**
- * The name of the Intent action used to indicate that a camera launch might be imminent. This
- * broadcast should be targeted to the package that is receiving
- * {@link #INTENT_ACTION_STILL_IMAGE_CAMERA} or
- * {@link #INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE}, depending on the context. If such
- * intent would launch the resolver activity, this broadcast should not be sent at all.
+ * Name under which an activity handling {@link #INTENT_ACTION_STILL_IMAGE_CAMERA} or
+ * {@link #INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE} publishes the service name for its prewarm
+ * service.
* <p>
- * A receiver of this broadcast should do the absolute minimum amount of work to initialize the
- * camera in order to reduce startup time in likely case that shortly after an actual camera
- * launch intent would be sent.
+ * This meta-data should reference the fully qualified class name of the prewarm service
+ * extending {@link CameraPrewarmService}.
* <p>
- * In case the actual intent will not be fired, the target package will receive
- * {@link #ACTION_STILL_IMAGE_CAMERA_COOLDOWN}. However, it is recommended that the receiver
- * also implements a timeout to close the camera after receiving this intent, as there is no
- * guarantee that {@link #ACTION_STILL_IMAGE_CAMERA_COOLDOWN} will be delivered.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_STILL_IMAGE_CAMERA_PREWARM = "android.media.action.STILL_IMAGE_CAMERA_PREWARM";
-
- /**
- * The name of the Intent action used to indicate that an imminent camera launch has been
- * cancelled by the user. This broadcast should be targeted to the package that has received
- * {@link #ACTION_STILL_IMAGE_CAMERA_PREWARM}.
+ * The prewarm service will get bound and receive a prewarm signal
+ * {@link CameraPrewarmService#onPrewarm()} when a camera launch intent fire might be imminent.
+ * An application implementing a prewarm service should do the absolute minimum amount of work
+ * to initialize the camera in order to reduce startup time in likely case that shortly after a
+ * camera launch intent would be sent.
* <p>
- * A receiver of this broadcast should close the camera immediately.
+ * If the camera launch intent gets fired shortly after, the service will be unbound
+ * asynchronously, without receiving
*/
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_STILL_IMAGE_CAMERA_COOLDOWN = "android.media.action.STILL_IMAGE_CAMERA_COOLDOWN";
+ public static final String META_DATA_STILL_IMAGE_CAMERA_PREWARM_SERVICE =
+ "android.media.still_image_camera_preview_service";
/**
* The name of the Intent action used to launch a camera in still image mode
@@ -2268,5 +2261,4 @@ public final class MediaStore {
}
return null;
}
-
}
diff --git a/core/java/android/security/IKeystoreService.aidl b/core/java/android/security/IKeystoreService.aidl
index 30ea8e7..409542d 100644
--- a/core/java/android/security/IKeystoreService.aidl
+++ b/core/java/android/security/IKeystoreService.aidl
@@ -65,9 +65,10 @@ interface IKeystoreService {
ExportResult exportKey(String alias, int format, in KeymasterBlob clientId,
in KeymasterBlob appId);
OperationResult begin(IBinder appToken, String alias, int purpose, boolean pruneable,
- in KeymasterArguments params, in byte[] entropy, out KeymasterArguments operationParams);
+ in KeymasterArguments params, in byte[] entropy);
OperationResult update(IBinder token, in KeymasterArguments params, in byte[] input);
- OperationResult finish(IBinder token, in KeymasterArguments params, in byte[] signature);
+ OperationResult finish(IBinder token, in KeymasterArguments params, in byte[] signature,
+ in byte[] entropy);
int abort(IBinder handle);
boolean isOperationAuthorized(IBinder token);
int addAuthToken(in byte[] authToken);
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index 0e2b8ba..6e40c6c 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -50,8 +50,7 @@ public final class KeymasterDefs {
public static final int KM_TAG_BLOCK_MODE = KM_ENUM_REP | 4;
public static final int KM_TAG_DIGEST = KM_ENUM_REP | 5;
public static final int KM_TAG_PADDING = KM_ENUM_REP | 6;
- public static final int KM_TAG_RETURN_UNAUTHED = KM_BOOL | 7;
- public static final int KM_TAG_CALLER_NONCE = KM_BOOL | 8;
+ public static final int KM_TAG_CALLER_NONCE = KM_BOOL | 7;
public static final int KM_TAG_RESCOPING_ADD = KM_ENUM_REP | 101;
public static final int KM_TAG_RESCOPING_DEL = KM_ENUM_REP | 102;
@@ -82,7 +81,7 @@ public final class KeymasterDefs {
public static final int KM_TAG_ASSOCIATED_DATA = KM_BYTES | 1000;
public static final int KM_TAG_NONCE = KM_BYTES | 1001;
- public static final int KM_TAG_CHUNK_LENGTH = KM_INT | 1002;
+ public static final int KM_TAG_AEAD_TAG = KM_BYTES | 1002;
public static final int KM_TAG_AUTH_TOKEN = KM_BYTES | 1003;
public static final int KM_TAG_MAC_LENGTH = KM_INT | 1004;
@@ -93,12 +92,10 @@ public final class KeymasterDefs {
public static final int KM_ALGORITHM_HMAC = 128;
// Block modes.
- public static final int KM_MODE_FIRST_UNAUTHENTICATED = 1;
- public static final int KM_MODE_ECB = KM_MODE_FIRST_UNAUTHENTICATED;
+ public static final int KM_MODE_ECB = 1;
public static final int KM_MODE_CBC = 2;
- public static final int KM_MODE_CTR = 4;
- public static final int KM_MODE_FIRST_AUTHENTICATED = 32;
- public static final int KM_MODE_GCM = KM_MODE_FIRST_AUTHENTICATED;
+ public static final int KM_MODE_CTR = 3;
+ public static final int KM_MODE_GCM = 32;
// Padding modes.
public static final int KM_PAD_NONE = 1;
@@ -194,7 +191,7 @@ public final class KeymasterDefs {
public static final int KM_ERROR_UNSUPPORTED_EC_FIELD = -50;
public static final int KM_ERROR_MISSING_NONCE = -51;
public static final int KM_ERROR_INVALID_NONCE = -52;
- public static final int KM_ERROR_UNSUPPORTED_CHUNK_LENGTH = -53;
+ public static final int KM_ERROR_MISSING_MAC_LENGTH = -53;
public static final int KM_ERROR_RESCOPABLE_KEY_NOT_USABLE = -54;
public static final int KM_ERROR_CALLER_NONCE_PROHIBITED = -55;
public static final int KM_ERROR_UNIMPLEMENTED = -100;
diff --git a/core/java/android/security/keymaster/OperationResult.java b/core/java/android/security/keymaster/OperationResult.java
index 9b46ad3..911a05a 100644
--- a/core/java/android/security/keymaster/OperationResult.java
+++ b/core/java/android/security/keymaster/OperationResult.java
@@ -31,6 +31,7 @@ public class OperationResult implements Parcelable {
public final long operationHandle;
public final int inputConsumed;
public final byte[] output;
+ public final KeymasterArguments outParams;
public static final Parcelable.Creator<OperationResult> CREATOR = new
Parcelable.Creator<OperationResult>() {
@@ -49,6 +50,7 @@ public class OperationResult implements Parcelable {
operationHandle = in.readLong();
inputConsumed = in.readInt();
output = in.createByteArray();
+ outParams = KeymasterArguments.CREATOR.createFromParcel(in);
}
@Override
@@ -63,5 +65,6 @@ public class OperationResult implements Parcelable {
out.writeLong(operationHandle);
out.writeInt(inputConsumed);
out.writeByteArray(output);
+ outParams.writeToParcel(out, flags);
}
}
diff --git a/core/java/android/service/carrier/CarrierService.java b/core/java/android/service/carrier/CarrierService.java
index 15ccc25..4a4a375 100644
--- a/core/java/android/service/carrier/CarrierService.java
+++ b/core/java/android/service/carrier/CarrierService.java
@@ -86,11 +86,13 @@ public abstract class CarrierService extends Service {
/** @hide */
@Override
public final IBinder onBind(Intent intent) {
- if (!CONFIG_SERVICE_INTERFACE.equals(intent.getAction())
- || !BIND_SERVICE_INTERFACE.equals(intent.getAction())) {
- return null;
+ switch (intent.getAction()) {
+ case CONFIG_SERVICE_INTERFACE:
+ case BIND_SERVICE_INTERFACE:
+ return mStubWrapper;
+ default:
+ return null;
}
- return mStubWrapper;
}
/**
diff --git a/core/java/android/service/media/CameraPrewarmService.java b/core/java/android/service/media/CameraPrewarmService.java
new file mode 100644
index 0000000..335b00a
--- /dev/null
+++ b/core/java/android/service/media/CameraPrewarmService.java
@@ -0,0 +1,96 @@
+/*
+ * 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.service.media;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
+
+/**
+ * Extend this class to implement a camera prewarm service. See
+ * {@link android.provider.MediaStore#META_DATA_STILL_IMAGE_CAMERA_PREWARM_SERVICE}.
+ */
+public abstract class CameraPrewarmService extends Service {
+
+ /**
+ * Intent action to bind the service as a prewarm service.
+ * @hide
+ */
+ public static final String ACTION_PREWARM =
+ "android.service.media.CameraPrewarmService.ACTION_PREWARM";
+
+ /**
+ * Message sent by the client indicating that the camera intent has been fired.
+ * @hide
+ */
+ public static final int MSG_CAMERA_FIRED = 1;
+
+ private final Handler mHandler = new Handler() {
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_CAMERA_FIRED:
+ mCameraIntentFired = true;
+ break;
+ default:
+ super.handleMessage(msg);
+ }
+ }
+ };
+ private boolean mCameraIntentFired;
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ if (ACTION_PREWARM.equals(intent.getAction())) {
+ onPrewarm();
+ return new Messenger(mHandler).getBinder();
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public boolean onUnbind(Intent intent) {
+ if (ACTION_PREWARM.equals(intent.getAction())) {
+ onCooldown(mCameraIntentFired);
+ }
+ return false;
+ }
+
+ /**
+ * Called when the camera should be prewarmed.
+ */
+ public abstract void onPrewarm();
+
+ /**
+ * Called when prewarm phase is done, either because the camera launch intent has been fired
+ * at this point or prewarm is no longer needed. A client should close the camera
+ * immediately in the latter case.
+ * <p>
+ * In case the camera launch intent has been fired, there is no guarantee about the ordering
+ * of these two events. Cooldown might happen either before or after the activity has been
+ * created that handles the camera intent.
+ *
+ * @param cameraIntentFired Indicates whether the intent to launch the camera has been
+ * fired.
+ */
+ public abstract void onCooldown(boolean cameraIntentFired);
+}
diff --git a/core/java/android/service/voice/IVoiceInteractionSession.aidl b/core/java/android/service/voice/IVoiceInteractionSession.aidl
index 894edac..8fe84e1 100644
--- a/core/java/android/service/voice/IVoiceInteractionSession.aidl
+++ b/core/java/android/service/voice/IVoiceInteractionSession.aidl
@@ -16,8 +16,8 @@
package android.service.voice;
-import android.app.AssistContent;
-import android.app.AssistStructure;
+import android.app.assist.AssistContent;
+import android.app.assist.AssistStructure;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index 48ad5a8..33fef62 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -16,11 +16,11 @@
package android.service.voice;
-import android.app.AssistContent;
-import android.app.AssistStructure;
import android.app.Dialog;
import android.app.Instrumentation;
import android.app.VoiceInteractor;
+import android.app.assist.AssistContent;
+import android.app.assist.AssistStructure;
import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.Intent;
@@ -386,7 +386,7 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
}
/**
- * ASk the app to cancel this current request.
+ * ASk the app to cancelLocked this current request.
*/
public void cancel() {
try {
@@ -878,14 +878,34 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
show(null, 0);
}
- public void show(Bundle args, int showFlags) {
+ /**
+ * Show the UI for this session. This asks the system to go through the process of showing
+ * your UI, which will eventually culminate in {@link #onShow}. This is similar to calling
+ * {@link VoiceInteractionService#showSession VoiceInteractionService.showSession}.
+ * @param args Arbitrary arguments that will be propagated {@link #onShow}.
+ * @param flags Indicates additional optional behavior that should be performed. May
+ * be {@link VoiceInteractionSession#SHOW_WITH_ASSIST VoiceInteractionSession.SHOW_WITH_ASSIST}
+ * to request that the system generate and deliver assist data on the current foreground
+ * app as part of showing the session UI.
+ */
+ public void show(Bundle args, int flags) {
+ if (mToken == null) {
+ throw new IllegalStateException("Can't call before onCreate()");
+ }
try {
- mSystemService.showSessionFromSession(mToken, null, 0);
+ mSystemService.showSessionFromSession(mToken, args, flags);
} catch (RemoteException e) {
}
}
+ /**
+ * Hide the session's UI, if currently shown. Call this when you are done with your
+ * user interaction.
+ */
public void hide() {
+ if (mToken == null) {
+ throw new IllegalStateException("Can't call before onCreate()");
+ }
try {
mSystemService.hideSessionFromSession(mToken);
} catch (RemoteException e) {
@@ -964,6 +984,9 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
* {@link #startVoiceActivity}.</p>
*/
public void setKeepAwake(boolean keepAwake) {
+ if (mToken == null) {
+ throw new IllegalStateException("Can't call before onCreate()");
+ }
try {
mSystemService.setKeepAwake(mToken, keepAwake);
} catch (RemoteException e) {
@@ -985,7 +1008,9 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
}
/**
- * Finish the session.
+ * Finish the session. This completely destroys the session -- the next time it is shown,
+ * an entirely new one will be created. You do not normally call this function; instead,
+ * use {@link #hide} and allow the system to destroy your session if it needs its RAM.
*/
public void finish() {
if (mToken == null) {
@@ -1114,7 +1139,7 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
* Called when the user presses the back button while focus is in the session UI. Note
* that this will only happen if the session UI has requested input focus in its window;
* otherwise, the back key will go to whatever window has focus and do whatever behavior
- * it normally has there.
+ * it normally has there. The default implementation simply calls {@link #hide}.
*/
public void onBackPressed() {
hide();
@@ -1123,7 +1148,7 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
/**
* Sessions automatically watch for requests that all system UI be closed (such as when
* the user presses HOME), which will appear here. The default implementation always
- * calls {@link #finish}.
+ * calls {@link #hide}.
*/
public void onCloseSystemDialogs() {
hide();
@@ -1287,7 +1312,7 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
}
/**
- * Called when the {@link android.app.VoiceInteractor} has asked to cancel a {@link Request}
+ * Called when the {@link android.app.VoiceInteractor} has asked to cancelLocked a {@link Request}
* that was previously delivered to {@link #onRequestConfirmation},
* {@link #onRequestPickOption}, {@link #onRequestCompleteVoice}, {@link #onRequestAbortVoice},
* or {@link #onRequestCommand}.
diff --git a/core/java/android/text/Annotation.java b/core/java/android/text/Annotation.java
index dbc290b..bb5d3ea 100644
--- a/core/java/android/text/Annotation.java
+++ b/core/java/android/text/Annotation.java
@@ -38,6 +38,11 @@ public class Annotation implements ParcelableSpan {
}
public int getSpanTypeId() {
+ return getSpanTypeIdInternal();
+ }
+
+ /** @hide */
+ public int getSpanTypeIdInternal() {
return TextUtils.ANNOTATION;
}
@@ -46,6 +51,11 @@ public class Annotation implements ParcelableSpan {
}
public void writeToParcel(Parcel dest, int flags) {
+ writeToParcelInternal(dest, flags);
+ }
+
+ /** @hide */
+ public void writeToParcelInternal(Parcel dest, int flags) {
dest.writeString(mKey);
dest.writeString(mValue);
}
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
index e99a960..5b5cdd2 100644
--- a/core/java/android/text/DynamicLayout.java
+++ b/core/java/android/text/DynamicLayout.java
@@ -291,7 +291,7 @@ public class DynamicLayout extends Layout
b.setText(text, where, where + after)
.setPaint(getPaint())
.setWidth(getWidth())
- .setTextDir(getTextDirectionHeuristic())
+ .setTextDirection(getTextDirectionHeuristic())
.setLineSpacing(getSpacingAdd(), getSpacingMultiplier())
.setEllipsizedWidth(mEllipsizedWidth)
.setEllipsize(mEllipsizeAt)
diff --git a/core/java/android/text/Hyphenator.java b/core/java/android/text/Hyphenator.java
index a99bdf5..67c36e3 100644
--- a/core/java/android/text/Hyphenator.java
+++ b/core/java/android/text/Hyphenator.java
@@ -16,6 +16,9 @@
package android.text;
+import com.android.internal.annotations.GuardedBy;
+
+import android.annotation.Nullable;
import android.util.Log;
import java.io.File;
@@ -36,6 +39,9 @@ public class Hyphenator {
private static String TAG = "Hyphenator";
+ private final static Object sLock = new Object();
+
+ @GuardedBy("sLock")
static HashMap<Locale, Hyphenator> sMap = new HashMap<Locale, Hyphenator>();
private long mNativePtr;
@@ -44,35 +50,94 @@ public class Hyphenator {
mNativePtr = nativePtr;
}
- public static long get(Locale locale) {
- Hyphenator result = sMap.get(locale);
- return result == null ? 0 : result.mNativePtr;
- }
+ public static long get(@Nullable Locale locale) {
+ synchronized (sLock) {
+ if (sMap.containsKey(locale)) {
+ Hyphenator result = sMap.get(locale);
+ return (result == null) ? 0 : result.mNativePtr;
+ }
+
+ // TODO: Convert this a proper locale-fallback system
- private static Hyphenator loadHyphenator(Locale locale) {
- // TODO: find pattern dictionary (from system location) that best matches locale
- if (Locale.US.equals(locale)) {
- File f = new File(getSystemHyphenatorLocation(), "hyph-en-us.pat.txt");
- try {
- RandomAccessFile rf = new RandomAccessFile(f, "r");
- byte[] buf = new byte[(int)rf.length()];
- rf.read(buf);
- rf.close();
- String patternData = new String(buf);
- long nativePtr = StaticLayout.nLoadHyphenator(patternData);
- return new Hyphenator(nativePtr);
- } catch (IOException e) {
- Log.e(TAG, "error loading hyphenation " + f, e);
+ // Fall back to language-only, if available
+ Locale languageOnlyLocale = new Locale(locale.getLanguage());
+ if (sMap.containsKey(languageOnlyLocale)) {
+ Hyphenator result = sMap.get(languageOnlyLocale);
+ sMap.put(locale, result);
+ return (result == null) ? 0 : result.mNativePtr;
}
+
+ // Fall back to script-only, if available
+ String script = locale.getScript();
+ if (!script.equals("")) {
+ Locale scriptOnlyLocale = new Locale.Builder()
+ .setLanguage("und")
+ .setScript(script)
+ .build();
+ if (sMap.containsKey(scriptOnlyLocale)) {
+ Hyphenator result = sMap.get(scriptOnlyLocale);
+ sMap.put(locale, result);
+ return (result == null) ? 0 : result.mNativePtr;
+ }
+ }
+
+ sMap.put(locale, null); // To remember we found nothing.
+ }
+ return 0;
+ }
+
+ private static Hyphenator loadHyphenator(String languageTag) {
+ String patternFilename = "hyph-"+languageTag.toLowerCase(Locale.US)+".pat.txt";
+ File patternFile = new File(getSystemHyphenatorLocation(), patternFilename);
+ try {
+ RandomAccessFile rf = new RandomAccessFile(patternFile, "r");
+ byte[] buf = new byte[(int)rf.length()];
+ rf.read(buf);
+ rf.close();
+ String patternData = new String(buf);
+ long nativePtr = StaticLayout.nLoadHyphenator(patternData);
+ return new Hyphenator(nativePtr);
+ } catch (IOException e) {
+ Log.e(TAG, "error loading hyphenation " + patternFile, e);
}
return null;
}
private static File getSystemHyphenatorLocation() {
- // TODO: move to a sensible location under system
return new File("/system/usr/hyphen-data");
}
+ // This array holds pairs of language tags that are used to prefill the map from locale to
+ // hyphenation data: The hyphenation data for the first field will be prefilled from the
+ // hyphenation data for the second field.
+ //
+ // The aliases that are computable by the get() method above are not included.
+ private static final String[][] LOCALE_FALLBACK_DATA = {
+ // English locales that fall back to en-US. The data is
+ // from CLDR. It's all English locales, minus the locales whose
+ // parent is en-001 (from supplementalData.xml, under <parentLocales>).
+ // TODO: Figure out how to get this from ICU.
+ {"en-AS", "en-US"}, // English (American Samoa)
+ {"en-GU", "en-US"}, // English (Guam)
+ {"en-MH", "en-US"}, // English (Marshall Islands)
+ {"en-MP", "en-US"}, // English (Northern Mariana Islands)
+ {"en-PR", "en-US"}, // English (Puerto Rico)
+ {"en-UM", "en-US"}, // English (United States Minor Outlying Islands)
+ {"en-VI", "en-US"}, // English (Virgin Islands)
+
+ // Norwegian is very probably Norwegian Bokmål.
+ {"no", "nb"},
+
+ // Fall back to Ethiopic script for languages likely to be written in Ethiopic.
+ // Data is from CLDR's likelySubtags.xml.
+ // TODO: Convert this to a mechanism using ICU4J's ULocale#addLikelySubtags().
+ {"am", "und-Ethi"}, // Amharic
+ {"byn", "und-Ethi"}, // Blin
+ {"gez", "und-Ethi"}, // Geʻez
+ {"ti", "und-Ethi"}, // Tigrinya
+ {"wal", "und-Ethi"}, // Wolaytta
+ };
+
/**
* Load hyphenation patterns at initialization time. We want to have patterns
* for all locales loaded and ready to use so we don't have to do any file IO
@@ -81,7 +146,22 @@ public class Hyphenator {
* @hide
*/
public static void init() {
- Locale l = Locale.US;
- sMap.put(l, loadHyphenator(l));
+ sMap.put(null, null);
+
+ // TODO: replace this with a discovery-based method that looks into /system/usr/hyphen-data
+ String[] availableLanguages = {"en-US", "eu", "hu", "hy", "nb", "nn", "sa", "und-Ethi"};
+ for (int i = 0; i < availableLanguages.length; i++) {
+ String languageTag = availableLanguages[i];
+ Hyphenator h = loadHyphenator(languageTag);
+ if (h != null) {
+ sMap.put(Locale.forLanguageTag(languageTag), h);
+ }
+ }
+
+ for (int i = 0; i < LOCALE_FALLBACK_DATA.length; i++) {
+ String language = LOCALE_FALLBACK_DATA[i][0];
+ String fallback = LOCALE_FALLBACK_DATA[i][1];
+ sMap.put(Locale.forLanguageTag(language), sMap.get(Locale.forLanguageTag(fallback)));
+ }
}
}
diff --git a/core/java/android/text/ParcelableSpan.java b/core/java/android/text/ParcelableSpan.java
index 224511a..d7c1a4b 100644
--- a/core/java/android/text/ParcelableSpan.java
+++ b/core/java/android/text/ParcelableSpan.java
@@ -16,6 +16,7 @@
package android.text;
+import android.os.Parcel;
import android.os.Parcelable;
/**
@@ -27,5 +28,21 @@ public interface ParcelableSpan extends Parcelable {
/**
* Return a special type identifier for this span class.
*/
- public abstract int getSpanTypeId();
+ int getSpanTypeId();
+
+ /**
+ * Internal implementation of {@link #getSpanTypeId()} that is not meant to
+ * be overridden outside of the framework.
+ *
+ * @hide
+ */
+ int getSpanTypeIdInternal();
+
+ /**
+ * Internal implementation of {@link Parcelable#writeToParcel(Parcel, int)}
+ * that is not meant to be overridden outside of the framework.
+ *
+ * @hide
+ */
+ void writeToParcelInternal(Parcel dest, int flags);
}
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index d6d046b..464710b 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -184,7 +184,7 @@ public class StaticLayout extends Layout {
* @param textDir text direction heuristic for resolving BiDi behavior.
* @return this builder, useful for chaining
*/
- public Builder setTextDir(TextDirectionHeuristic textDir) {
+ public Builder setTextDirection(TextDirectionHeuristic textDir) {
mTextDir = textDir;
return this;
}
@@ -473,7 +473,7 @@ public class StaticLayout extends Layout {
Builder b = Builder.obtain(source, bufstart, bufend, paint, outerwidth)
.setAlignment(align)
- .setTextDir(textDir)
+ .setTextDirection(textDir)
.setLineSpacing(spacingadd, spacingmult)
.setIncludePad(includepad)
.setEllipsizedWidth(ellipsizedWidth)
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 676986d..6c4d8fd 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -622,8 +622,7 @@ public class TextUtils {
* Flatten a CharSequence and whatever styles can be copied across processes
* into the parcel.
*/
- public static void writeToParcel(CharSequence cs, Parcel p,
- int parcelableFlags) {
+ public static void writeToParcel(CharSequence cs, Parcel p, int parcelableFlags) {
if (cs instanceof Spanned) {
p.writeInt(0);
p.writeString(cs.toString());
@@ -645,15 +644,15 @@ public class TextUtils {
}
if (prop instanceof ParcelableSpan) {
- ParcelableSpan ps = (ParcelableSpan)prop;
- int spanTypeId = ps.getSpanTypeId();
+ final ParcelableSpan ps = (ParcelableSpan) prop;
+ final int spanTypeId = ps.getSpanTypeIdInternal();
if (spanTypeId < FIRST_SPAN || spanTypeId > LAST_SPAN) {
- Log.e(TAG, "external class \"" + ps.getClass().getSimpleName()
+ Log.e(TAG, "External class \"" + ps.getClass().getSimpleName()
+ "\" is attempting to use the frameworks-only ParcelableSpan"
+ " interface");
} else {
p.writeInt(spanTypeId);
- ps.writeToParcel(p, parcelableFlags);
+ ps.writeToParcelInternal(p, parcelableFlags);
writeWhere(p, sp, o);
}
}
diff --git a/core/java/android/text/style/AbsoluteSizeSpan.java b/core/java/android/text/style/AbsoluteSizeSpan.java
index 1214040..908ef55 100644
--- a/core/java/android/text/style/AbsoluteSizeSpan.java
+++ b/core/java/android/text/style/AbsoluteSizeSpan.java
@@ -49,6 +49,11 @@ public class AbsoluteSizeSpan extends MetricAffectingSpan implements ParcelableS
}
public int getSpanTypeId() {
+ return getSpanTypeIdInternal();
+ }
+
+ /** @hide */
+ public int getSpanTypeIdInternal() {
return TextUtils.ABSOLUTE_SIZE_SPAN;
}
@@ -57,6 +62,11 @@ public class AbsoluteSizeSpan extends MetricAffectingSpan implements ParcelableS
}
public void writeToParcel(Parcel dest, int flags) {
+ writeToParcelInternal(dest, flags);
+ }
+
+ /** @hide */
+ public void writeToParcelInternal(Parcel dest, int flags) {
dest.writeInt(mSize);
dest.writeInt(mDip ? 1 : 0);
}
diff --git a/core/java/android/text/style/AlignmentSpan.java b/core/java/android/text/style/AlignmentSpan.java
index b8a37da..6158309 100644
--- a/core/java/android/text/style/AlignmentSpan.java
+++ b/core/java/android/text/style/AlignmentSpan.java
@@ -22,10 +22,9 @@ import android.text.ParcelableSpan;
import android.text.TextUtils;
public interface AlignmentSpan extends ParagraphStyle {
- public Layout.Alignment getAlignment();
+ Layout.Alignment getAlignment();
- public static class Standard
- implements AlignmentSpan, ParcelableSpan {
+ class Standard implements AlignmentSpan, ParcelableSpan {
public Standard(Layout.Alignment align) {
mAlignment = align;
}
@@ -35,6 +34,11 @@ public interface AlignmentSpan extends ParagraphStyle {
}
public int getSpanTypeId() {
+ return getSpanTypeIdInternal();
+ }
+
+ /** @hide */
+ public int getSpanTypeIdInternal() {
return TextUtils.ALIGNMENT_SPAN;
}
@@ -43,6 +47,11 @@ public interface AlignmentSpan extends ParagraphStyle {
}
public void writeToParcel(Parcel dest, int flags) {
+ writeToParcelInternal(dest, flags);
+ }
+
+ /** @hide */
+ public void writeToParcelInternal(Parcel dest, int flags) {
dest.writeString(mAlignment.name());
}
diff --git a/core/java/android/text/style/BackgroundColorSpan.java b/core/java/android/text/style/BackgroundColorSpan.java
index cda8015..de05f50 100644
--- a/core/java/android/text/style/BackgroundColorSpan.java
+++ b/core/java/android/text/style/BackgroundColorSpan.java
@@ -35,6 +35,11 @@ public class BackgroundColorSpan extends CharacterStyle
}
public int getSpanTypeId() {
+ return getSpanTypeIdInternal();
+ }
+
+ /** @hide */
+ public int getSpanTypeIdInternal() {
return TextUtils.BACKGROUND_COLOR_SPAN;
}
@@ -43,6 +48,11 @@ public class BackgroundColorSpan extends CharacterStyle
}
public void writeToParcel(Parcel dest, int flags) {
+ writeToParcelInternal(dest, flags);
+ }
+
+ /** @hide */
+ public void writeToParcelInternal(Parcel dest, int flags) {
dest.writeInt(mColor);
}
diff --git a/core/java/android/text/style/BulletSpan.java b/core/java/android/text/style/BulletSpan.java
index 3f86b08..7408415 100644
--- a/core/java/android/text/style/BulletSpan.java
+++ b/core/java/android/text/style/BulletSpan.java
@@ -60,6 +60,11 @@ public class BulletSpan implements LeadingMarginSpan, ParcelableSpan {
}
public int getSpanTypeId() {
+ return getSpanTypeIdInternal();
+ }
+
+ /** @hide */
+ public int getSpanTypeIdInternal() {
return TextUtils.BULLET_SPAN;
}
@@ -68,6 +73,11 @@ public class BulletSpan implements LeadingMarginSpan, ParcelableSpan {
}
public void writeToParcel(Parcel dest, int flags) {
+ writeToParcelInternal(dest, flags);
+ }
+
+ /** @hide */
+ public void writeToParcelInternal(Parcel dest, int flags) {
dest.writeInt(mGapWidth);
dest.writeInt(mWantColor ? 1 : 0);
dest.writeInt(mColor);
diff --git a/core/java/android/text/style/EasyEditSpan.java b/core/java/android/text/style/EasyEditSpan.java
index 03b4f60..7af1c2c 100644
--- a/core/java/android/text/style/EasyEditSpan.java
+++ b/core/java/android/text/style/EasyEditSpan.java
@@ -91,12 +91,22 @@ public class EasyEditSpan implements ParcelableSpan {
@Override
public void writeToParcel(Parcel dest, int flags) {
+ writeToParcelInternal(dest, flags);
+ }
+
+ /** @hide */
+ public void writeToParcelInternal(Parcel dest, int flags) {
dest.writeParcelable(mPendingIntent, 0);
dest.writeByte((byte) (mDeleteEnabled ? 1 : 0));
}
@Override
public int getSpanTypeId() {
+ return getSpanTypeIdInternal();
+ }
+
+ /** @hide */
+ public int getSpanTypeIdInternal() {
return TextUtils.EASY_EDIT_SPAN;
}
diff --git a/core/java/android/text/style/ForegroundColorSpan.java b/core/java/android/text/style/ForegroundColorSpan.java
index f167aab..2bc6d54 100644
--- a/core/java/android/text/style/ForegroundColorSpan.java
+++ b/core/java/android/text/style/ForegroundColorSpan.java
@@ -36,14 +36,24 @@ public class ForegroundColorSpan extends CharacterStyle
}
public int getSpanTypeId() {
+ return getSpanTypeIdInternal();
+ }
+
+ /** @hide */
+ public int getSpanTypeIdInternal() {
return TextUtils.FOREGROUND_COLOR_SPAN;
}
-
+
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
+ writeToParcelInternal(dest, flags);
+ }
+
+ /** @hide */
+ public void writeToParcelInternal(Parcel dest, int flags) {
dest.writeInt(mColor);
}
diff --git a/core/java/android/text/style/LeadingMarginSpan.java b/core/java/android/text/style/LeadingMarginSpan.java
index 96a7cd9..339d885 100644
--- a/core/java/android/text/style/LeadingMarginSpan.java
+++ b/core/java/android/text/style/LeadingMarginSpan.java
@@ -125,6 +125,11 @@ extends ParagraphStyle
}
public int getSpanTypeId() {
+ return getSpanTypeIdInternal();
+ }
+
+ /** @hide */
+ public int getSpanTypeIdInternal() {
return TextUtils.LEADING_MARGIN_SPAN;
}
@@ -133,6 +138,11 @@ extends ParagraphStyle
}
public void writeToParcel(Parcel dest, int flags) {
+ writeToParcelInternal(dest, flags);
+ }
+
+ /** @hide */
+ public void writeToParcelInternal(Parcel dest, int flags) {
dest.writeInt(mFirst);
dest.writeInt(mRest);
}
diff --git a/core/java/android/text/style/LocaleSpan.java b/core/java/android/text/style/LocaleSpan.java
index a12c42f..d286231 100644
--- a/core/java/android/text/style/LocaleSpan.java
+++ b/core/java/android/text/style/LocaleSpan.java
@@ -44,6 +44,11 @@ public class LocaleSpan extends MetricAffectingSpan implements ParcelableSpan {
@Override
public int getSpanTypeId() {
+ return getSpanTypeIdInternal();
+ }
+
+ /** @hide */
+ public int getSpanTypeIdInternal() {
return TextUtils.LOCALE_SPAN;
}
@@ -54,6 +59,11 @@ public class LocaleSpan extends MetricAffectingSpan implements ParcelableSpan {
@Override
public void writeToParcel(Parcel dest, int flags) {
+ writeToParcelInternal(dest, flags);
+ }
+
+ /** @hide */
+ public void writeToParcelInternal(Parcel dest, int flags) {
dest.writeString(mLocale.getLanguage());
dest.writeString(mLocale.getCountry());
dest.writeString(mLocale.getVariant());
diff --git a/core/java/android/text/style/QuoteSpan.java b/core/java/android/text/style/QuoteSpan.java
index 17748ca..0b0a82c 100644
--- a/core/java/android/text/style/QuoteSpan.java
+++ b/core/java/android/text/style/QuoteSpan.java
@@ -45,6 +45,11 @@ public class QuoteSpan implements LeadingMarginSpan, ParcelableSpan {
}
public int getSpanTypeId() {
+ return getSpanTypeIdInternal();
+ }
+
+ /** @hide */
+ public int getSpanTypeIdInternal() {
return TextUtils.QUOTE_SPAN;
}
@@ -53,6 +58,11 @@ public class QuoteSpan implements LeadingMarginSpan, ParcelableSpan {
}
public void writeToParcel(Parcel dest, int flags) {
+ writeToParcelInternal(dest, flags);
+ }
+
+ /** @hide */
+ public void writeToParcelInternal(Parcel dest, int flags) {
dest.writeInt(mColor);
}
diff --git a/core/java/android/text/style/RelativeSizeSpan.java b/core/java/android/text/style/RelativeSizeSpan.java
index 632dbd4..95f048a 100644
--- a/core/java/android/text/style/RelativeSizeSpan.java
+++ b/core/java/android/text/style/RelativeSizeSpan.java
@@ -34,6 +34,11 @@ public class RelativeSizeSpan extends MetricAffectingSpan implements ParcelableS
}
public int getSpanTypeId() {
+ return getSpanTypeIdInternal();
+ }
+
+ /** @hide */
+ public int getSpanTypeIdInternal() {
return TextUtils.RELATIVE_SIZE_SPAN;
}
@@ -42,6 +47,11 @@ public class RelativeSizeSpan extends MetricAffectingSpan implements ParcelableS
}
public void writeToParcel(Parcel dest, int flags) {
+ writeToParcelInternal(dest, flags);
+ }
+
+ /** @hide */
+ public void writeToParcelInternal(Parcel dest, int flags) {
dest.writeFloat(mProportion);
}
diff --git a/core/java/android/text/style/ScaleXSpan.java b/core/java/android/text/style/ScaleXSpan.java
index a22a5a1..d085018 100644
--- a/core/java/android/text/style/ScaleXSpan.java
+++ b/core/java/android/text/style/ScaleXSpan.java
@@ -34,6 +34,11 @@ public class ScaleXSpan extends MetricAffectingSpan implements ParcelableSpan {
}
public int getSpanTypeId() {
+ return getSpanTypeIdInternal();
+ }
+
+ /** @hide */
+ public int getSpanTypeIdInternal() {
return TextUtils.SCALE_X_SPAN;
}
@@ -42,6 +47,11 @@ public class ScaleXSpan extends MetricAffectingSpan implements ParcelableSpan {
}
public void writeToParcel(Parcel dest, int flags) {
+ writeToParcelInternal(dest, flags);
+ }
+
+ /** @hide */
+ public void writeToParcelInternal(Parcel dest, int flags) {
dest.writeFloat(mProportion);
}
diff --git a/core/java/android/text/style/SpellCheckSpan.java b/core/java/android/text/style/SpellCheckSpan.java
index 0d8a103..10275c2 100644
--- a/core/java/android/text/style/SpellCheckSpan.java
+++ b/core/java/android/text/style/SpellCheckSpan.java
@@ -54,11 +54,21 @@ public class SpellCheckSpan implements ParcelableSpan {
@Override
public void writeToParcel(Parcel dest, int flags) {
+ writeToParcelInternal(dest, flags);
+ }
+
+ /** @hide */
+ public void writeToParcelInternal(Parcel dest, int flags) {
dest.writeInt(mSpellCheckInProgress ? 1 : 0);
}
@Override
public int getSpanTypeId() {
+ return getSpanTypeIdInternal();
+ }
+
+ /** @hide */
+ public int getSpanTypeIdInternal() {
return TextUtils.SPELL_CHECK_SPAN;
}
}
diff --git a/core/java/android/text/style/StrikethroughSpan.java b/core/java/android/text/style/StrikethroughSpan.java
index 303e415..1389704 100644
--- a/core/java/android/text/style/StrikethroughSpan.java
+++ b/core/java/android/text/style/StrikethroughSpan.java
@@ -30,6 +30,11 @@ public class StrikethroughSpan extends CharacterStyle
}
public int getSpanTypeId() {
+ return getSpanTypeIdInternal();
+ }
+
+ /** @hide */
+ public int getSpanTypeIdInternal() {
return TextUtils.STRIKETHROUGH_SPAN;
}
@@ -38,6 +43,11 @@ public class StrikethroughSpan extends CharacterStyle
}
public void writeToParcel(Parcel dest, int flags) {
+ writeToParcelInternal(dest, flags);
+ }
+
+ /** @hide */
+ public void writeToParcelInternal(Parcel dest, int flags) {
}
@Override
diff --git a/core/java/android/text/style/StyleSpan.java b/core/java/android/text/style/StyleSpan.java
index b08f70e..f900db5 100644
--- a/core/java/android/text/style/StyleSpan.java
+++ b/core/java/android/text/style/StyleSpan.java
@@ -50,6 +50,11 @@ public class StyleSpan extends MetricAffectingSpan implements ParcelableSpan {
}
public int getSpanTypeId() {
+ return getSpanTypeIdInternal();
+ }
+
+ /** @hide */
+ public int getSpanTypeIdInternal() {
return TextUtils.STYLE_SPAN;
}
@@ -58,6 +63,11 @@ public class StyleSpan extends MetricAffectingSpan implements ParcelableSpan {
}
public void writeToParcel(Parcel dest, int flags) {
+ writeToParcelInternal(dest, flags);
+ }
+
+ /** @hide */
+ public void writeToParcelInternal(Parcel dest, int flags) {
dest.writeInt(mStyle);
}
diff --git a/core/java/android/text/style/SubscriptSpan.java b/core/java/android/text/style/SubscriptSpan.java
index de1d8b2..f1b0d38 100644
--- a/core/java/android/text/style/SubscriptSpan.java
+++ b/core/java/android/text/style/SubscriptSpan.java
@@ -29,6 +29,11 @@ public class SubscriptSpan extends MetricAffectingSpan implements ParcelableSpan
}
public int getSpanTypeId() {
+ return getSpanTypeIdInternal();
+ }
+
+ /** @hide */
+ public int getSpanTypeIdInternal() {
return TextUtils.SUBSCRIPT_SPAN;
}
@@ -37,6 +42,11 @@ public class SubscriptSpan extends MetricAffectingSpan implements ParcelableSpan
}
public void writeToParcel(Parcel dest, int flags) {
+ writeToParcelInternal(dest, flags);
+ }
+
+ /** @hide */
+ public void writeToParcelInternal(Parcel dest, int flags) {
}
@Override
diff --git a/core/java/android/text/style/SuggestionRangeSpan.java b/core/java/android/text/style/SuggestionRangeSpan.java
index 2dbfc72..c1943d5 100644
--- a/core/java/android/text/style/SuggestionRangeSpan.java
+++ b/core/java/android/text/style/SuggestionRangeSpan.java
@@ -46,11 +46,21 @@ public class SuggestionRangeSpan extends CharacterStyle implements ParcelableSpa
@Override
public void writeToParcel(Parcel dest, int flags) {
+ writeToParcelInternal(dest, flags);
+ }
+
+ /** @hide */
+ public void writeToParcelInternal(Parcel dest, int flags) {
dest.writeInt(mBackgroundColor);
}
@Override
public int getSpanTypeId() {
+ return getSpanTypeIdInternal();
+ }
+
+ /** @hide */
+ public int getSpanTypeIdInternal() {
return TextUtils.SUGGESTION_RANGE_SPAN;
}
diff --git a/core/java/android/text/style/SuggestionSpan.java b/core/java/android/text/style/SuggestionSpan.java
index 8b40953..6b449f9 100644
--- a/core/java/android/text/style/SuggestionSpan.java
+++ b/core/java/android/text/style/SuggestionSpan.java
@@ -248,6 +248,11 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
@Override
public void writeToParcel(Parcel dest, int flags) {
+ writeToParcelInternal(dest, flags);
+ }
+
+ /** @hide */
+ public void writeToParcelInternal(Parcel dest, int flags) {
dest.writeStringArray(mSuggestions);
dest.writeInt(mFlags);
dest.writeString(mLocaleString);
@@ -264,6 +269,11 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
@Override
public int getSpanTypeId() {
+ return getSpanTypeIdInternal();
+ }
+
+ /** @hide */
+ public int getSpanTypeIdInternal() {
return TextUtils.SUGGESTION_SPAN;
}
diff --git a/core/java/android/text/style/SuperscriptSpan.java b/core/java/android/text/style/SuperscriptSpan.java
index 285fe84..abcf688 100644
--- a/core/java/android/text/style/SuperscriptSpan.java
+++ b/core/java/android/text/style/SuperscriptSpan.java
@@ -29,6 +29,11 @@ public class SuperscriptSpan extends MetricAffectingSpan implements ParcelableSp
}
public int getSpanTypeId() {
+ return getSpanTypeIdInternal();
+ }
+
+ /** @hide */
+ public int getSpanTypeIdInternal() {
return TextUtils.SUPERSCRIPT_SPAN;
}
@@ -37,6 +42,11 @@ public class SuperscriptSpan extends MetricAffectingSpan implements ParcelableSp
}
public void writeToParcel(Parcel dest, int flags) {
+ writeToParcelInternal(dest, flags);
+ }
+
+ /** @hide */
+ public void writeToParcelInternal(Parcel dest, int flags) {
}
@Override
diff --git a/core/java/android/text/style/TextAppearanceSpan.java b/core/java/android/text/style/TextAppearanceSpan.java
index ecbf4bc..abbd793 100644
--- a/core/java/android/text/style/TextAppearanceSpan.java
+++ b/core/java/android/text/style/TextAppearanceSpan.java
@@ -136,6 +136,11 @@ public class TextAppearanceSpan extends MetricAffectingSpan implements Parcelabl
}
public int getSpanTypeId() {
+ return getSpanTypeIdInternal();
+ }
+
+ /** @hide */
+ public int getSpanTypeIdInternal() {
return TextUtils.TEXT_APPEARANCE_SPAN;
}
@@ -144,6 +149,11 @@ public class TextAppearanceSpan extends MetricAffectingSpan implements Parcelabl
}
public void writeToParcel(Parcel dest, int flags) {
+ writeToParcelInternal(dest, flags);
+ }
+
+ /** @hide */
+ public void writeToParcelInternal(Parcel dest, int flags) {
dest.writeString(mTypeface);
dest.writeInt(mStyle);
dest.writeInt(mTextSize);
diff --git a/core/java/android/text/style/TtsSpan.java b/core/java/android/text/style/TtsSpan.java
index 342a183..c40f11f 100644
--- a/core/java/android/text/style/TtsSpan.java
+++ b/core/java/android/text/style/TtsSpan.java
@@ -495,12 +495,22 @@ public class TtsSpan implements ParcelableSpan {
@Override
public void writeToParcel(Parcel dest, int flags) {
+ writeToParcelInternal(dest, flags);
+ }
+
+ /** @hide */
+ public void writeToParcelInternal(Parcel dest, int flags) {
dest.writeString(mType);
dest.writePersistableBundle(mArgs);
}
@Override
public int getSpanTypeId() {
+ return getSpanTypeIdInternal();
+ }
+
+ /** @hide */
+ public int getSpanTypeIdInternal() {
return TextUtils.TTS_SPAN;
}
diff --git a/core/java/android/text/style/TypefaceSpan.java b/core/java/android/text/style/TypefaceSpan.java
index f194060..aa622d8 100644
--- a/core/java/android/text/style/TypefaceSpan.java
+++ b/core/java/android/text/style/TypefaceSpan.java
@@ -42,6 +42,11 @@ public class TypefaceSpan extends MetricAffectingSpan implements ParcelableSpan
}
public int getSpanTypeId() {
+ return getSpanTypeIdInternal();
+ }
+
+ /** @hide */
+ public int getSpanTypeIdInternal() {
return TextUtils.TYPEFACE_SPAN;
}
@@ -50,6 +55,11 @@ public class TypefaceSpan extends MetricAffectingSpan implements ParcelableSpan
}
public void writeToParcel(Parcel dest, int flags) {
+ writeToParcelInternal(dest, flags);
+ }
+
+ /** @hide */
+ public void writeToParcelInternal(Parcel dest, int flags) {
dest.writeString(mFamily);
}
diff --git a/core/java/android/text/style/URLSpan.java b/core/java/android/text/style/URLSpan.java
index 0669b6f..58239ef 100644
--- a/core/java/android/text/style/URLSpan.java
+++ b/core/java/android/text/style/URLSpan.java
@@ -40,6 +40,11 @@ public class URLSpan extends ClickableSpan implements ParcelableSpan {
}
public int getSpanTypeId() {
+ return getSpanTypeIdInternal();
+ }
+
+ /** @hide */
+ public int getSpanTypeIdInternal() {
return TextUtils.URL_SPAN;
}
@@ -48,6 +53,11 @@ public class URLSpan extends ClickableSpan implements ParcelableSpan {
}
public void writeToParcel(Parcel dest, int flags) {
+ writeToParcelInternal(dest, flags);
+ }
+
+ /** @hide */
+ public void writeToParcelInternal(Parcel dest, int flags) {
dest.writeString(mURL);
}
diff --git a/core/java/android/text/style/UnderlineSpan.java b/core/java/android/text/style/UnderlineSpan.java
index 80b2427..9024dcd 100644
--- a/core/java/android/text/style/UnderlineSpan.java
+++ b/core/java/android/text/style/UnderlineSpan.java
@@ -30,6 +30,11 @@ public class UnderlineSpan extends CharacterStyle
}
public int getSpanTypeId() {
+ return getSpanTypeIdInternal();
+ }
+
+ /** @hide */
+ public int getSpanTypeIdInternal() {
return TextUtils.UNDERLINE_SPAN;
}
@@ -38,6 +43,11 @@ public class UnderlineSpan extends CharacterStyle
}
public void writeToParcel(Parcel dest, int flags) {
+ writeToParcelInternal(dest, flags);
+ }
+
+ /** @hide */
+ public void writeToParcelInternal(Parcel dest, int flags) {
}
@Override
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index d0e5b9e..a36e66c 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -79,6 +79,14 @@ public class DisplayMetrics {
* This is not a density that applications should target, instead relying
* on the system to scale their {@link #DENSITY_XXHIGH} assets for them.
*/
+ public static final int DENSITY_360 = 360;
+
+ /**
+ * Intermediate density for screens that sit somewhere between
+ * {@link #DENSITY_XHIGH} (320 dpi) and {@link #DENSITY_XXHIGH} (480 dpi).
+ * This is not a density that applications should target, instead relying
+ * on the system to scale their {@link #DENSITY_XXHIGH} assets for them.
+ */
public static final int DENSITY_400 = 400;
/**
diff --git a/core/java/android/util/StateSet.java b/core/java/android/util/StateSet.java
index 83dfc47..c2a6a7a 100644
--- a/core/java/android/util/StateSet.java
+++ b/core/java/android/util/StateSet.java
@@ -119,7 +119,14 @@ public class StateSet {
/** @hide */
public StateSet() {}
+ /**
+ * A state specification that will be matched by all StateSets.
+ */
public static final int[] WILD_CARD = new int[0];
+
+ /**
+ * A state set that does not contain any valid states.
+ */
public static final int[] NOTHING = new int[] { 0 };
/**
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 6e2d110..664c02a 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -19,6 +19,7 @@ package android.view;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
+import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@@ -158,7 +159,9 @@ final class AccessibilityInteractionController {
try {
mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
applyAppScaleAndMagnificationSpecIfNeeded(infos, spec);
- if (spec != null) {
+ // Recycle if called from another process. Specs are cached in the
+ // system process and obtained from a pool when read from parcel.
+ if (spec != null && android.os.Process.myPid() != Binder.getCallingPid()) {
spec.recycle();
}
adjustIsVisibleToUserIfNeeded(infos, interactiveRegion);
@@ -167,6 +170,12 @@ final class AccessibilityInteractionController {
} catch (RemoteException re) {
/* ignore - the other side will time out */
}
+
+ // Recycle if called from the same process. Regions are obtained in
+ // the system process and instantiated when read from parcel.
+ if (interactiveRegion != null && android.os.Process.myPid() == Binder.getCallingPid()) {
+ interactiveRegion.recycle();
+ }
}
}
@@ -244,7 +253,9 @@ final class AccessibilityInteractionController {
try {
mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
applyAppScaleAndMagnificationSpecIfNeeded(infos, spec);
- if (spec != null) {
+ // Recycle if called from another process. Specs are cached in the
+ // system process and obtained from a pool when read from parcel.
+ if (spec != null && android.os.Process.myPid() != Binder.getCallingPid()) {
spec.recycle();
}
adjustIsVisibleToUserIfNeeded(infos, interactiveRegion);
@@ -252,6 +263,12 @@ final class AccessibilityInteractionController {
} catch (RemoteException re) {
/* ignore - the other side will time out */
}
+
+ // Recycle if called from the same process. Regions are obtained in
+ // the system process and instantiated when read from parcel.
+ if (interactiveRegion != null && android.os.Process.myPid() == Binder.getCallingPid()) {
+ interactiveRegion.recycle();
+ }
}
}
@@ -354,7 +371,9 @@ final class AccessibilityInteractionController {
try {
mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
applyAppScaleAndMagnificationSpecIfNeeded(infos, spec);
- if (spec != null) {
+ // Recycle if called from another process. Specs are cached in the
+ // system process and obtained from a pool when read from parcel.
+ if (spec != null && android.os.Process.myPid() != Binder.getCallingPid()) {
spec.recycle();
}
adjustIsVisibleToUserIfNeeded(infos, interactiveRegion);
@@ -362,6 +381,12 @@ final class AccessibilityInteractionController {
} catch (RemoteException re) {
/* ignore - the other side will time out */
}
+
+ // Recycle if called from the same process. Regions are obtained in
+ // the system process and instantiated when read from parcel.
+ if (interactiveRegion != null && android.os.Process.myPid() == Binder.getCallingPid()) {
+ interactiveRegion.recycle();
+ }
}
}
@@ -468,7 +493,9 @@ final class AccessibilityInteractionController {
try {
mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
applyAppScaleAndMagnificationSpecIfNeeded(focused, spec);
- if (spec != null) {
+ // Recycle if called from another process. Specs are cached in the
+ // system process and obtained from a pool when read from parcel.
+ if (spec != null && android.os.Process.myPid() != Binder.getCallingPid()) {
spec.recycle();
}
adjustIsVisibleToUserIfNeeded(focused, interactiveRegion);
@@ -476,6 +503,12 @@ final class AccessibilityInteractionController {
} catch (RemoteException re) {
/* ignore - the other side will time out */
}
+
+ // Recycle if called from the same process. Regions are obtained in
+ // the system process and instantiated when read from parcel.
+ if (interactiveRegion != null && android.os.Process.myPid() == Binder.getCallingPid()) {
+ interactiveRegion.recycle();
+ }
}
}
@@ -545,7 +578,9 @@ final class AccessibilityInteractionController {
try {
mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
applyAppScaleAndMagnificationSpecIfNeeded(next, spec);
- if (spec != null) {
+ // Recycle if called from another process. Specs are cached in the
+ // system process and obtained from a pool when read from parcel.
+ if (spec != null && android.os.Process.myPid() != Binder.getCallingPid()) {
spec.recycle();
}
adjustIsVisibleToUserIfNeeded(next, interactiveRegion);
@@ -553,6 +588,12 @@ final class AccessibilityInteractionController {
} catch (RemoteException re) {
/* ignore - the other side will time out */
}
+
+ // Recycle if called from the same process. Regions are obtained in
+ // the system process and instantiated when read from parcel.
+ if (interactiveRegion != null && android.os.Process.myPid() == Binder.getCallingPid()) {
+ interactiveRegion.recycle();
+ }
}
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index cfd504d..126540f 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1661,8 +1661,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
/** {@hide} */
static final int PFLAG_SKIP_DRAW = 0x00000080;
/** {@hide} */
- static final int PFLAG_ONLY_DRAWS_BACKGROUND = 0x00000100;
- /** {@hide} */
static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
/** {@hide} */
static final int PFLAG_DRAWABLE_STATE_DIRTY = 0x00000400;
@@ -7368,7 +7366,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @hide
*/
public void getOutsets(Rect outOutsetRect) {
- outOutsetRect.set(mAttachInfo.mOutsets);
+ if (mAttachInfo != null) {
+ outOutsetRect.set(mAttachInfo.mOutsets);
+ } else {
+ outOutsetRect.setEmpty();
+ }
}
/**
@@ -10619,9 +10621,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if ((changed & DRAW_MASK) != 0) {
if ((mViewFlags & WILL_NOT_DRAW) != 0) {
- if (mBackground != null) {
+ if (mBackground != null
+ || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
mPrivateFlags &= ~PFLAG_SKIP_DRAW;
- mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
} else {
mPrivateFlags |= PFLAG_SKIP_DRAW;
}
@@ -17113,6 +17115,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
* attached to this view.
*/
+ @CallSuper
public void jumpDrawablesToCurrentState() {
if (mBackground != null) {
mBackground.jumpToCurrentState();
@@ -17260,20 +17263,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
mPrivateFlags &= ~PFLAG_SKIP_DRAW;
- mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
requestLayout = true;
}
} else {
/* Remove the background */
mBackground = null;
-
- if ((mPrivateFlags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0) {
- /*
- * This view ONLY drew the background before and we're removing
- * the background, so now it won't draw anything
- * (hence we SKIP_DRAW)
- */
- mPrivateFlags &= ~PFLAG_ONLY_DRAWS_BACKGROUND;
+ if ((mViewFlags & WILL_NOT_DRAW) != 0
+ && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
mPrivateFlags |= PFLAG_SKIP_DRAW;
}
@@ -17447,13 +17443,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mForegroundInfo.mDrawable = foreground;
mForegroundInfo.mBoundsChanged = true;
if (foreground != null) {
- setWillNotDraw(false);
+ if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
+ mPrivateFlags &= ~PFLAG_SKIP_DRAW;
+ }
foreground.setCallback(this);
foreground.setLayoutDirection(getLayoutDirection());
if (foreground.isStateful()) {
foreground.setState(getDrawableState());
}
applyForegroundTint();
+ } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
+ mPrivateFlags |= PFLAG_SKIP_DRAW;
}
requestLayout();
invalidate();
@@ -17565,13 +17565,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @see Drawable#setTintMode(PorterDuff.Mode)
*/
public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
- if (mBackgroundTint == null) {
- mBackgroundTint = new TintInfo();
+ if (mForegroundInfo == null) {
+ mForegroundInfo = new ForegroundInfo();
}
- mBackgroundTint.mTintMode = tintMode;
- mBackgroundTint.mHasTintMode = true;
+ if (mForegroundInfo.mTintInfo == null) {
+ mForegroundInfo.mTintInfo = new TintInfo();
+ }
+ mForegroundInfo.mTintInfo.mTintMode = tintMode;
+ mForegroundInfo.mTintInfo.mHasTintMode = true;
- applyBackgroundTint();
+ applyForegroundTint();
}
/**
@@ -17581,7 +17584,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return the blending mode used to apply the tint to the foreground
* drawable
* @attr ref android.R.styleable#View_foregroundTintMode
- * @see #setBackgroundTintMode(PorterDuff.Mode)
+ * @see #setForegroundTintMode(PorterDuff.Mode)
*/
@Nullable
public PorterDuff.Mode getForegroundTintMode() {
@@ -18291,7 +18294,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (accessibilityId < 0) {
return null;
}
- return findViewByAccessibilityIdTraversal(accessibilityId);
+ View view = findViewByAccessibilityIdTraversal(accessibilityId);
+ if (view != null) {
+ return view.includeForAccessibility() ? view : null;
+ }
+ return null;
}
/**
@@ -19181,16 +19188,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
getLocationInWindow(location);
region.op(location[0], location[1], location[0] + mRight - mLeft,
location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
- } else if ((pflags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0 && mBackground != null &&
- mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
- // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
- // exists, so we remove the background drawable's non-transparent
- // parts from this transparent region.
- applyDrawableToTransparentRegion(mBackground, region);
- }
- final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
- if (foreground != null) {
- applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
+ } else {
+ if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
+ // The SKIP_DRAW flag IS set and the background drawable exists, we remove
+ // the background drawable's non-transparent parts from this transparent region.
+ applyDrawableToTransparentRegion(mBackground, region);
+ }
+ if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
+ && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
+ // Similarly, we remove the foreground drawable's non-transparent parts.
+ applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
+ }
}
}
return true;
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index e015c04..dd32f85 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1173,6 +1173,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
if (foundView != null) {
return foundView;
}
+
+ if (getAccessibilityNodeProvider() != null) {
+ return null;
+ }
+
final int childrenCount = mChildrenCount;
final View[] children = mChildren;
for (int i = 0; i < childrenCount; i++) {
@@ -1182,6 +1187,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
return foundView;
}
}
+
return null;
}
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index 886547a..e525474 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -18,7 +18,6 @@ package android.view;
import android.graphics.Rect;
import android.os.Bundle;
-import android.text.TextPaint;
/**
* Container for storing additional per-view data generated by {@link View#onProvideStructure
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index 9e0719d..997e7e8 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -251,7 +251,7 @@ public final class WindowInsets {
* @return true if any inset values are nonzero
*/
public boolean hasInsets() {
- return hasSystemWindowInsets() || hasWindowDecorInsets();
+ return hasSystemWindowInsets() || hasWindowDecorInsets() || hasStableInsets();
}
/**
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index f0c86e5..45bc1df 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -309,6 +309,7 @@ public interface WindowManager extends ViewManager {
* Window type: a above sub-panel on top of an application window and it's
* sub-panel windows. These windows are displayed on top of their attached window
* and any {@link #TYPE_APPLICATION_SUB_PANEL} panels.
+ * @hide
*/
public static final int TYPE_APPLICATION_ABOVE_SUB_PANEL = FIRST_SUB_WINDOW + 5;
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index f7b6405..ca5f5ad 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -1058,6 +1058,13 @@ public interface WindowManagerPolicy {
public boolean isKeyguardSecure();
/**
+ * Return whether the keyguard is on.
+ *
+ * @return true if in keyguard is on.
+ */
+ public boolean isKeyguardShowingOrOccluded();
+
+ /**
* inKeyguardRestrictedKeyInputMode
*
* if keyguard screen is showing or in restricted key input mode (i.e. in
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 5537b3e..053b35c 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -24,6 +24,7 @@ import com.android.internal.view.IInputMethodManager;
import com.android.internal.view.IInputMethodSession;
import com.android.internal.view.InputBindResult;
+import android.annotation.RequiresPermission;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.Rect;
@@ -60,6 +61,8 @@ import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
+
/**
* Central system API to the overall input method framework (IMF) architecture,
* which arbitrates interaction between applications and the current input method.
@@ -1976,6 +1979,7 @@ public final class InputMethodManager {
* @return true if the current subtype was successfully switched. When the specified subtype is
* null, this method returns false.
*/
+ @RequiresPermission(WRITE_SECURE_SETTINGS)
public boolean setCurrentInputMethodSubtype(InputMethodSubtype subtype) {
synchronized (mH) {
try {
diff --git a/core/java/android/view/inputmethod/InputMethodSubtype.java b/core/java/android/view/inputmethod/InputMethodSubtype.java
index c2f3777..4ee155c 100644
--- a/core/java/android/view/inputmethod/InputMethodSubtype.java
+++ b/core/java/android/view/inputmethod/InputMethodSubtype.java
@@ -16,6 +16,7 @@
package android.view.inputmethod;
+import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.os.Parcel;
@@ -323,6 +324,19 @@ public final class InputMethodSubtype implements Parcelable {
}
/**
+ * @return The normalized {@link Locale} object of the subtype. The returned locale may or may
+ * not equal to "locale" string parameter passed to the constructor.
+ *
+ * <p>TODO: Consider to make this a public API.</p>
+ * @hide
+ */
+ @Nullable
+ public Locale getLocaleObject() {
+ // TODO: Move the following method from InputMethodUtils to InputMethodSubtype.
+ return InputMethodUtils.constructLocaleFromString(mSubtypeLocale);
+ }
+
+ /**
* @return The mode of the subtype.
*/
public String getMode() {
@@ -381,7 +395,7 @@ public final class InputMethodSubtype implements Parcelable {
*/
public CharSequence getDisplayName(
Context context, String packageName, ApplicationInfo appInfo) {
- final Locale locale = InputMethodUtils.constructLocaleFromString(mSubtypeLocale);
+ final Locale locale = getLocaleObject();
final String localeStr = locale != null ? locale.getDisplayName() : mSubtypeLocale;
if (mSubtypeNameResId == 0) {
return localeStr;
diff --git a/core/java/android/view/textservice/SpellCheckerSession.java b/core/java/android/view/textservice/SpellCheckerSession.java
index 84f395a..195a335 100644
--- a/core/java/android/view/textservice/SpellCheckerSession.java
+++ b/core/java/android/view/textservice/SpellCheckerSession.java
@@ -98,11 +98,11 @@ public class SpellCheckerSession {
private final InternalListener mInternalListener;
private final ITextServicesManager mTextServicesManager;
private final SpellCheckerInfo mSpellCheckerInfo;
+ private final SpellCheckerSessionListener mSpellCheckerSessionListener;
private final SpellCheckerSessionListenerImpl mSpellCheckerSessionListenerImpl;
private final SpellCheckerSubtype mSubtype;
private boolean mIsUsed;
- private SpellCheckerSessionListener mSpellCheckerSessionListener;
/** Handler that will execute the main tasks */
private final Handler mHandler = new Handler() {
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index a3332fa..a0d1930 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -2345,8 +2345,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
}
- // Scrap view implies temporary detachment.
isScrap[0] = true;
+
+ // Finish the temporary detach started in addScrapView().
+ transientView.dispatchFinishTemporaryDetach();
return transientView;
}
@@ -2359,6 +2361,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
} else {
isScrap[0] = true;
+ // Finish the temporary detach started in addScrapView().
child.dispatchFinishTemporaryDetach();
}
}
diff --git a/core/java/android/widget/ArrayAdapter.java b/core/java/android/widget/ArrayAdapter.java
index ae94a10..027f6d6 100644
--- a/core/java/android/widget/ArrayAdapter.java
+++ b/core/java/android/widget/ArrayAdapter.java
@@ -50,14 +50,7 @@ import java.util.List;
* or to have some of data besides toString() results fill the views,
* override {@link #getView(int, View, ViewGroup)} to return the type of view you want.
*/
-public class ArrayAdapter<T> extends BaseAdapter implements Filterable,
- Spinner.ThemedSpinnerAdapter {
- /**
- * Contains the list of objects that represent the data of this ArrayAdapter.
- * The content of this list is referred to as "the array" in the documentation.
- */
- private List<T> mObjects;
-
+public class ArrayAdapter<T> extends BaseAdapter implements Filterable, ThemedSpinnerAdapter {
/**
* Lock used to modify the content of {@link #mObjects}. Any write operation
* performed on the array should be synchronized on this lock. This lock is also
@@ -66,6 +59,14 @@ public class ArrayAdapter<T> extends BaseAdapter implements Filterable,
*/
private final Object mLock = new Object();
+ private final LayoutInflater mInflater;
+
+ /**
+ * Contains the list of objects that represent the data of this ArrayAdapter.
+ * The content of this list is referred to as "the array" in the documentation.
+ */
+ private List<T> mObjects;
+
/**
* The resource indicating what views to inflate to display the content of this
* array adapter.
@@ -98,8 +99,6 @@ public class ArrayAdapter<T> extends BaseAdapter implements Filterable,
private ArrayList<T> mOriginalValues;
private ArrayFilter mFilter;
- private LayoutInflater mInflater;
-
/** Layout inflater used for {@link #getDropDownView(int, View, ViewGroup)}. */
private LayoutInflater mDropDownInflater;
@@ -443,9 +442,6 @@ public class ArrayAdapter<T> extends BaseAdapter implements Filterable,
return mDropDownInflater == null ? null : mDropDownInflater.getContext().getTheme();
}
- /**
- * {@inheritDoc}
- */
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
final LayoutInflater inflater = mDropDownInflater == null ? mInflater : mDropDownInflater;
diff --git a/core/java/android/widget/CursorAdapter.java b/core/java/android/widget/CursorAdapter.java
index d8ce60c..9fb98db 100644
--- a/core/java/android/widget/CursorAdapter.java
+++ b/core/java/android/widget/CursorAdapter.java
@@ -38,7 +38,7 @@ import android.view.ViewGroup;
* columns.
*/
public abstract class CursorAdapter extends BaseAdapter implements Filterable,
- CursorFilter.CursorFilterClient, Spinner.ThemedSpinnerAdapter {
+ CursorFilter.CursorFilterClient, ThemedSpinnerAdapter {
/**
* This field should be made private, so it is hidden from the SDK.
* {@hide}
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index d38a225..7e542c9 100755
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -115,7 +115,8 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate {
R.styleable.DatePicker_internalLayout, R.layout.date_picker_material);
// Set up and attach container.
- mContainer = (ViewGroup) inflater.inflate(layoutResourceId, mDelegator);
+ mContainer = (ViewGroup) inflater.inflate(layoutResourceId, mDelegator, false);
+ mDelegator.addView(mContainer);
// Set up header views.
final ViewGroup header = (ViewGroup) mContainer.findViewById(R.id.date_picker_header);
@@ -471,7 +472,11 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate {
@Override
public void setEnabled(boolean enabled) {
- mContainer.setEnabled(false);
+ mContainer.setEnabled(enabled);
+ mDayPickerView.setEnabled(enabled);
+ mYearPickerView.setEnabled(enabled);
+ mHeaderYear.setEnabled(enabled);
+ mHeaderMonthDay.setEnabled(enabled);
}
@Override
@@ -481,8 +486,7 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate {
@Override
public CalendarView getCalendarView() {
- throw new UnsupportedOperationException(
- "CalendarView does not exists for the new DatePicker");
+ throw new UnsupportedOperationException("Not supported by calendar-mode DatePicker");
}
@Override
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 0cac529..56f9b5c 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -1004,14 +1004,14 @@ public class Editor {
stopSelectionActionMode();
} else {
stopSelectionActionMode();
- startSelectionActionModeWithSelectionAndStartDrag();
+ selectCurrentWordAndStartDrag();
}
handled = true;
}
// Start a new selection
if (!handled) {
- handled = startSelectionActionModeWithSelectionAndStartDrag();
+ handled = selectCurrentWordAndStartDrag();
}
return handled;
@@ -1724,22 +1724,9 @@ public class Editor {
}
/**
- * Starts a Selection Action Mode with the current selection and enters drag mode. This should
- * be used whenever the mode is started from a touch event.
- *
- * @return true if the selection mode was actually started.
- */
- private boolean startSelectionActionModeWithSelectionAndStartDrag() {
- boolean selectionStarted = startSelectionActionModeWithSelectionInternal();
- if (selectionStarted) {
- getSelectionController().enterDrag();
- }
- return selectionStarted;
- }
-
- /**
* Starts a Selection Action Mode with the current selection and ensures the selection handles
- * are shown. This should be used when the mode is started from a non-touch event.
+ * are shown if there is a selection, otherwise the insertion handle is shown. This should be
+ * used when the mode is started from a non-touch event.
*
* @return true if the selection mode was actually started.
*/
@@ -1747,38 +1734,65 @@ public class Editor {
boolean selectionStarted = startSelectionActionModeWithSelectionInternal();
if (selectionStarted) {
getSelectionController().show();
+ } else if (getInsertionController() != null) {
+ getInsertionController().show();
}
return selectionStarted;
}
- private boolean startSelectionActionModeWithSelectionInternal() {
+ /**
+ * If the TextView allows text selection, selects the current word when no existing selection
+ * was available and starts a drag.
+ *
+ * @return true if the drag was started.
+ */
+ private boolean selectCurrentWordAndStartDrag() {
if (extractedTextModeWillBeStarted()) {
// Cancel the single tap delayed runnable.
if (mSelectionModeWithoutSelectionRunnable != null) {
mTextView.removeCallbacks(mSelectionModeWithoutSelectionRunnable);
}
-
return false;
}
-
if (mSelectionActionMode != null) {
- // Selection action mode is already started
- mSelectionActionMode.invalidate();
+ mSelectionActionMode.finish();
+ }
+ if (!checkFieldAndSelectCurrentWord()) {
return false;
}
+ getSelectionController().enterDrag();
+ return true;
+ }
+ /**
+ * Checks whether a selection can be performed on the current TextView and if so selects
+ * the current word.
+ *
+ * @return true if there already was a selection or if the current word was selected.
+ */
+ private boolean checkFieldAndSelectCurrentWord() {
if (!mTextView.canSelectText() || !mTextView.requestFocus()) {
Log.w(TextView.LOG_TAG,
- "TextView does not support text selection. Action mode cancelled.");
+ "TextView does not support text selection. Selection cancelled.");
return false;
}
if (!mTextView.hasSelection()) {
// There may already be a selection on device rotation
- if (!selectCurrentWord()) {
- // No word found under cursor or text selection not permitted.
- return false;
- }
+ return selectCurrentWord();
+ }
+ return true;
+ }
+
+ private boolean startSelectionActionModeWithSelectionInternal() {
+ if (mSelectionActionMode != null) {
+ // Selection action mode is already started
+ mSelectionActionMode.invalidate();
+ return false;
+ }
+
+ if (!checkFieldAndSelectCurrentWord()) {
+ return false;
}
boolean willExtract = extractedTextModeWillBeStarted();
@@ -1829,12 +1843,18 @@ public class Editor {
}
if (selectionStart == selectionEnd) {
// Spans overlap the cursor.
- return true;
+ for (int i = 0; i < suggestionSpans.length; i++) {
+ if (suggestionSpans[i].getSuggestions().length > 0) {
+ return true;
+ }
+ }
+ return false;
}
int minSpanStart = mTextView.getText().length();
int maxSpanEnd = 0;
int unionOfSpansCoveringSelectionStartStart = mTextView.getText().length();
int unionOfSpansCoveringSelectionStartEnd = 0;
+ boolean hasValidSuggestions = false;
for (int i = 0; i < suggestionSpans.length; i++) {
final int spanStart = spannable.getSpanStart(suggestionSpans[i]);
final int spanEnd = spannable.getSpanEnd(suggestionSpans[i]);
@@ -1844,11 +1864,16 @@ public class Editor {
// The span doesn't cover the current selection start point.
continue;
}
+ hasValidSuggestions =
+ hasValidSuggestions || suggestionSpans[i].getSuggestions().length > 0;
unionOfSpansCoveringSelectionStartStart =
Math.min(unionOfSpansCoveringSelectionStartStart, spanStart);
unionOfSpansCoveringSelectionStartEnd =
Math.max(unionOfSpansCoveringSelectionStartEnd, spanEnd);
}
+ if (!hasValidSuggestions) {
+ return false;
+ }
if (unionOfSpansCoveringSelectionStartStart >= unionOfSpansCoveringSelectionStartEnd) {
// No spans cover the selection start point.
return false;
@@ -4071,12 +4096,17 @@ public class Editor {
offset = getNextCursorOffset(selectionEnd, false);
mTouchWordDelta = 0.0f;
}
- mInWord = !getWordIteratorWithText().isBoundary(offset);
positionAtCursorOffset(offset, false);
}
}
@Override
+ protected void positionAtCursorOffset(int offset, boolean parentScrolled) {
+ super.positionAtCursorOffset(offset, parentScrolled);
+ mInWord = !getWordIteratorWithText().isBoundary(offset);
+ }
+
+ @Override
public boolean onTouchEvent(MotionEvent event) {
boolean superResult = super.onTouchEvent(event);
if (event.getActionMasked() == MotionEvent.ACTION_UP) {
@@ -4193,12 +4223,17 @@ public class Editor {
offset = getNextCursorOffset(selectionStart, true);
mTouchWordDelta = 0.0f;
}
- mInWord = !getWordIteratorWithText().isBoundary(offset);
positionAtCursorOffset(offset, false);
}
}
@Override
+ protected void positionAtCursorOffset(int offset, boolean parentScrolled) {
+ super.positionAtCursorOffset(offset, parentScrolled);
+ mInWord = !getWordIteratorWithText().isBoundary(offset);
+ }
+
+ @Override
public boolean onTouchEvent(MotionEvent event) {
boolean superResult = super.onTouchEvent(event);
if (event.getActionMasked() == MotionEvent.ACTION_UP) {
@@ -4377,7 +4412,7 @@ public class Editor {
boolean stayedInArea = distanceSquared < doubleTapSlop * doubleTapSlop;
if (stayedInArea && isPositionOnText(eventX, eventY)) {
- startSelectionActionModeWithSelectionAndStartDrag();
+ selectCurrentWordAndStartDrag();
mDiscardNextActionUp = true;
}
}
@@ -4480,6 +4515,7 @@ public class Editor {
mEndHandle.showAtLocation(endOffset);
// No longer the first dragging motion, reset.
+ startSelectionActionModeWithSelection();
mDragAcceleratorActive = false;
mStartOffset = -1;
}
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index cf67905..ebc7eb3 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -1505,11 +1505,9 @@ public class HorizontalScrollView extends FrameLayout {
final int scrollRange = Math.max(0,
childWidth - (r - l - mPaddingLeft - mPaddingRight));
if (mSavedState != null) {
- if (isLayoutRtl() == mSavedState.isLayoutRtl) {
- mScrollX = mSavedState.scrollPosition;
- } else {
- mScrollX = scrollRange - mSavedState.scrollPosition;
- }
+ mScrollX = isLayoutRtl()
+ ? scrollRange - mSavedState.scrollOffsetFromStart
+ : mSavedState.scrollOffsetFromStart;
mSavedState = null;
} else {
if (isLayoutRtl()) {
@@ -1692,8 +1690,7 @@ public class HorizontalScrollView extends FrameLayout {
}
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
- ss.scrollPosition = mScrollX;
- ss.isLayoutRtl = isLayoutRtl();
+ ss.scrollOffsetFromStart = isLayoutRtl() ? -mScrollX : mScrollX;
return ss;
}
@@ -1705,8 +1702,7 @@ public class HorizontalScrollView extends FrameLayout {
}
static class SavedState extends BaseSavedState {
- public int scrollPosition;
- public boolean isLayoutRtl;
+ public int scrollOffsetFromStart;
SavedState(Parcelable superState) {
super(superState);
@@ -1714,23 +1710,21 @@ public class HorizontalScrollView extends FrameLayout {
public SavedState(Parcel source) {
super(source);
- scrollPosition = source.readInt();
- isLayoutRtl = (source.readInt() == 0) ? true : false;
+ scrollOffsetFromStart = source.readInt();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
- dest.writeInt(scrollPosition);
- dest.writeInt(isLayoutRtl ? 1 : 0);
+ dest.writeInt(scrollOffsetFromStart);
}
@Override
public String toString() {
return "HorizontalScrollView.SavedState{"
+ Integer.toHexString(System.identityHashCode(this))
- + " scrollPosition=" + scrollPosition
- + " isLayoutRtl=" + isLayoutRtl + "}";
+ + " scrollPosition=" + scrollOffsetFromStart
+ + "}";
}
public static final Parcelable.Creator<SavedState> CREATOR
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 16dc26d..e7d9226 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -16,6 +16,7 @@
package android.widget;
+import android.annotation.CallSuper;
import android.annotation.IntDef;
import android.annotation.Widget;
import android.content.Context;
@@ -608,7 +609,16 @@ public class NumberPicker extends LinearLayout {
mSolidColor = attributesArray.getColor(R.styleable.NumberPicker_solidColor, 0);
- mSelectionDivider = attributesArray.getDrawable(R.styleable.NumberPicker_selectionDivider);
+ final Drawable selectionDivider = attributesArray.getDrawable(
+ R.styleable.NumberPicker_selectionDivider);
+ if (selectionDivider != null) {
+ selectionDivider.setCallback(this);
+ selectionDivider.setLayoutDirection(getLayoutDirection());
+ if (selectionDivider.isStateful()) {
+ selectionDivider.setState(getDrawableState());
+ }
+ }
+ mSelectionDivider = selectionDivider;
final int defSelectionDividerHeight = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, UNSCALED_DEFAULT_SELECTION_DIVIDER_HEIGHT,
@@ -1499,6 +1509,38 @@ public class NumberPicker extends LinearLayout {
removeAllCallbacks();
}
+ @CallSuper
+ @Override
+ protected void drawableStateChanged() {
+ super.drawableStateChanged();
+
+ final int[] state = getDrawableState();
+
+ if (mSelectionDivider != null && mSelectionDivider.isStateful()) {
+ mSelectionDivider.setState(state);
+ }
+ }
+
+ @CallSuper
+ @Override
+ public void jumpDrawablesToCurrentState() {
+ super.jumpDrawablesToCurrentState();
+
+ if (mSelectionDivider != null) {
+ mSelectionDivider.jumpToCurrentState();
+ }
+ }
+
+ /** @hide */
+ @Override
+ public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
+ super.onResolveDrawables(layoutDirection);
+
+ if (mSelectionDivider != null) {
+ mSelectionDivider.setLayoutDirection(layoutDirection);
+ }
+ }
+
@Override
protected void onDraw(Canvas canvas) {
if (!mHasSelectorWheel) {
diff --git a/core/java/android/widget/SimpleAdapter.java b/core/java/android/widget/SimpleAdapter.java
index 2008ba8..3bf9485 100644
--- a/core/java/android/widget/SimpleAdapter.java
+++ b/core/java/android/widget/SimpleAdapter.java
@@ -51,7 +51,9 @@ import java.util.Map;
* </ul>
* If no appropriate binding can be found, an {@link IllegalStateException} is thrown.
*/
-public class SimpleAdapter extends BaseAdapter implements Filterable, Spinner.ThemedSpinnerAdapter {
+public class SimpleAdapter extends BaseAdapter implements Filterable, ThemedSpinnerAdapter {
+ private final LayoutInflater mInflater;
+
private int[] mTo;
private String[] mFrom;
private ViewBinder mViewBinder;
@@ -60,7 +62,6 @@ public class SimpleAdapter extends BaseAdapter implements Filterable, Spinner.Th
private int mResource;
private int mDropDownResource;
- private LayoutInflater mInflater;
/** Layout inflater used for {@link #getDropDownView(int, View, ViewGroup)}. */
private LayoutInflater mDropDownInflater;
@@ -174,8 +175,8 @@ public class SimpleAdapter extends BaseAdapter implements Filterable, Spinner.Th
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
- return createViewFromResource(
- mDropDownInflater, position, convertView, parent, mDropDownResource);
+ final LayoutInflater inflater = mDropDownInflater == null ? mInflater : mDropDownInflater;
+ return createViewFromResource(inflater, position, convertView, parent, mDropDownResource);
}
private void bindView(int position, View view) {
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index 095cc44..6fe34dd 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -26,6 +26,7 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.res.Resources;
+import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
import android.database.DataSetObserver;
import android.graphics.Rect;
@@ -217,24 +218,24 @@ public class Spinner extends AbsSpinner implements OnClickListener {
* Can be 0 to not look for defaults.
* @param mode Constant describing how the user will select choices from
* the spinner.
- * @param popupContext The context against which the dialog or dropdown
- * popup will be inflated. Can be null to use the view
- * context. If set, this will override any value
- * specified by
- * {@link android.R.styleable#Spinner_popupTheme}.
+ * @param popupTheme The theme against which the dialog or dropdown popup
+ * should be inflated. May be {@code null} to use the
+ * view theme. If set, this will override any value
+ * specified by
+ * {@link android.R.styleable#Spinner_popupTheme}.
*
* @see #MODE_DIALOG
* @see #MODE_DROPDOWN
*/
public Spinner(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes, int mode,
- Context popupContext) {
+ Theme popupTheme) {
super(context, attrs, defStyleAttr, defStyleRes);
final TypedArray a = context.obtainStyledAttributes(
attrs, R.styleable.Spinner, defStyleAttr, defStyleRes);
- if (popupContext != null) {
- mPopupContext = popupContext;
+ if (popupTheme != null) {
+ mPopupContext = new ContextThemeWrapper(context, popupTheme);
} else {
final int popupThemeResId = a.getResourceId(R.styleable.Spinner_popupTheme, 0);
if (popupThemeResId != 0) {
@@ -932,9 +933,8 @@ public class Spinner extends AbsSpinner implements OnClickListener {
mListAdapter = (ListAdapter) adapter;
}
- if (dropDownTheme != null && adapter instanceof Spinner.ThemedSpinnerAdapter) {
- final Spinner.ThemedSpinnerAdapter themedAdapter =
- (Spinner.ThemedSpinnerAdapter) adapter;
+ if (dropDownTheme != null && adapter instanceof ThemedSpinnerAdapter) {
+ final ThemedSpinnerAdapter themedAdapter = (ThemedSpinnerAdapter) adapter;
if (themedAdapter.getDropDownViewTheme() == null) {
themedAdapter.setDropDownViewTheme(dropDownTheme);
}
@@ -1263,20 +1263,4 @@ public class Spinner extends AbsSpinner implements OnClickListener {
}
}
- public interface ThemedSpinnerAdapter {
- /**
- * Sets the {@link Resources.Theme} against which drop-down views are
- * inflated.
- *
- * @param theme the context against which to inflate drop-down views
- * @see SpinnerAdapter#getDropDownView(int, View, ViewGroup)
- */
- public void setDropDownViewTheme(Resources.Theme theme);
-
- /**
- * @return The {@link Resources.Theme} against which drop-down views are
- * inflated.
- */
- public Resources.Theme getDropDownViewTheme();
- }
}
diff --git a/core/java/android/widget/TabHost.java b/core/java/android/widget/TabHost.java
index c521f72..27fa3b9 100644
--- a/core/java/android/widget/TabHost.java
+++ b/core/java/android/widget/TabHost.java
@@ -188,32 +188,9 @@ mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1");
mLocalActivityManager = activityGroup;
}
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- final ViewTreeObserver treeObserver = getViewTreeObserver();
- treeObserver.addOnTouchModeChangeListener(this);
- }
-
@Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- final ViewTreeObserver treeObserver = getViewTreeObserver();
- treeObserver.removeOnTouchModeChangeListener(this);
- }
-
- /**
- * {@inheritDoc}
- */
public void onTouchModeChanged(boolean isInTouchMode) {
- if (!isInTouchMode) {
- // leaving touch mode.. if nothing has focus, let's give it to
- // the indicator of the current tab
- if (mCurrentView != null && (!mCurrentView.hasFocus() || mCurrentView.isFocused())) {
- mTabWidget.getChildTabViewAt(mCurrentTab).requestFocus();
- }
- }
+ // No longer used, but kept to maintain API compatibility.
}
/**
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index e14e39c..3a85476 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -6680,7 +6680,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
StaticLayout.Builder builder = StaticLayout.Builder.obtain(mHint, 0,
mHint.length(), mTextPaint, hintWidth)
.setAlignment(alignment)
- .setTextDir(mTextDir)
+ .setTextDirection(mTextDir)
.setLineSpacing(mSpacingAdd, mSpacingMult)
.setIncludePad(mIncludePad)
.setBreakStrategy(mBreakStrategy)
@@ -6771,7 +6771,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
StaticLayout.Builder builder = StaticLayout.Builder.obtain(mTransformed,
0, mTransformed.length(), mTextPaint, wantWidth)
.setAlignment(alignment)
- .setTextDir(mTextDir)
+ .setTextDirection(mTextDir)
.setLineSpacing(mSpacingAdd, mSpacingMult)
.setIncludePad(mIncludePad)
.setBreakStrategy(mBreakStrategy)
diff --git a/core/java/android/widget/ThemedSpinnerAdapter.java b/core/java/android/widget/ThemedSpinnerAdapter.java
new file mode 100644
index 0000000..6d92620
--- /dev/null
+++ b/core/java/android/widget/ThemedSpinnerAdapter.java
@@ -0,0 +1,53 @@
+/*
+ * 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.widget;
+
+import android.annotation.Nullable;
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * An extension of SpinnerAdapter that is capable of inflating drop-down views
+ * against a different theme than normal views.
+ * <p>
+ * Classes that implement this interface should use the theme provided to
+ * {@link #setDropDownViewTheme(Theme)} when creating views in
+ * {@link SpinnerAdapter#getDropDownView(int, View, ViewGroup)}.
+ */
+public interface ThemedSpinnerAdapter extends SpinnerAdapter {
+ /**
+ * Sets the {@link Resources.Theme} against which drop-down views are
+ * inflated.
+ *
+ * @param theme the context against which to inflate drop-down views, or
+ * {@code null} to use the default theme
+ * @see SpinnerAdapter#getDropDownView(int, View, ViewGroup)
+ */
+ void setDropDownViewTheme(@Nullable Resources.Theme theme);
+
+ /**
+ * Returns the value previously set by a call to
+ * {@link #setDropDownViewTheme(Theme)}.
+ *
+ * @return the {@link Resources.Theme} against which drop-down views are
+ * inflated, or {@code null} if one has not been explicitly set
+ */
+ @Nullable
+ Resources.Theme getDropDownViewTheme();
+}
diff --git a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
index ce94727..e607a3f 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
@@ -20,6 +20,7 @@ import android.content.Context;
import android.content.pm.PackageManager;
import android.text.TextUtils;
import android.util.Log;
+import android.util.Printer;
import android.util.Slog;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype;
@@ -314,6 +315,15 @@ public class InputMethodSubtypeSwitchingController {
}
return null;
}
+
+ protected void dump(final Printer pw, final String prefix) {
+ final int N = mImeSubtypeList.size();
+ for (int i = 0; i < N; ++i) {
+ final int rank = i;
+ final ImeSubtypeListItem item = mImeSubtypeList.get(i);
+ pw.println(prefix + "rank=" + rank + " item=" + item);
+ }
+ }
}
private static class DynamicRotationList {
@@ -388,6 +398,14 @@ public class InputMethodSubtypeSwitchingController {
}
return null;
}
+
+ protected void dump(final Printer pw, final String prefix) {
+ for (int i = 0; i < mUsageHistoryOfSubtypeListItemIndex.length; ++i) {
+ final int rank = mUsageHistoryOfSubtypeListItemIndex[i];
+ final ImeSubtypeListItem item = mImeSubtypeList.get(i);
+ pw.println(prefix + "rank=" + rank + " item=" + item);
+ }
+ }
}
@VisibleForTesting
@@ -478,6 +496,13 @@ public class InputMethodSubtypeSwitchingController {
}
return result;
}
+
+ protected void dump(final Printer pw) {
+ pw.println(" mSwitchingAwareRotationList:");
+ mSwitchingAwareRotationList.dump(pw, " ");
+ pw.println(" mSwitchingUnawareRotationList:");
+ mSwitchingUnawareRotationList.dump(pw, " ");
+ }
}
private final InputMethodSettings mSettings;
@@ -526,4 +551,12 @@ public class InputMethodSubtypeSwitchingController {
return mSubtypeList.getSortedInputMethodAndSubtypeList(
showSubtypes, includingAuxiliarySubtypes, isScreenLocked);
}
+
+ public void dump(final Printer pw) {
+ if (mController != null) {
+ mController.dump(pw);
+ } else {
+ pw.println(" mController=null");
+ }
+ }
}
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index 06bdb24..042db71 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -379,6 +379,14 @@ public class InputMethodUtils {
// The length of localeStr is guaranteed to always return a 1 <= value <= 3
// because localeStr is not empty.
if (localeParams.length == 1) {
+ if (localeParams.length >= 1 && "tl".equals(localeParams[0])) {
+ // Convert a locale whose language is "tl" to one whose language is "fil".
+ // For example, "tl_PH" will get converted to "fil_PH".
+ // Versions of Android earlier than Lollipop did not support three letter language
+ // codes, and used "tl" (Tagalog) as the language string for "fil" (Filipino).
+ // On Lollipop and above, the current three letter version must be used.
+ localeParams[0] = "fil";
+ }
return new Locale(localeParams[0]);
} else if (localeParams.length == 2) {
return new Locale(localeParams[0], localeParams[1]);
@@ -397,7 +405,7 @@ public class InputMethodUtils {
for (int i = 0; i < N; ++i) {
final InputMethodSubtype subtype = imi.getSubtypeAt(i);
if (checkCountry) {
- final Locale subtypeLocale = constructLocaleFromString(subtype.getLocale());
+ final Locale subtypeLocale = subtype.getLocaleObject();
if (subtypeLocale == null ||
!TextUtils.equals(subtypeLocale.getLanguage(), locale.getLanguage()) ||
!TextUtils.equals(subtypeLocale.getCountry(), locale.getCountry())) {
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 22c0680..14065b1 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -289,6 +289,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
private Rect mTempRect;
private Rect mOutsets = new Rect();
+ private boolean mIsStartingWindow;
+
static class WindowManagerHolder {
static final IWindowManager sWindowManager = IWindowManager.Stub.asInterface(
ServiceManager.getService("window"));
@@ -3891,7 +3893,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
// A pending invalidation will typically be resolved before the posted message
// would run normally in order to satisfy instance state restoration.
PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
- if (!isDestroyed() && (st == null || st.menu == null)) {
+ if (!isDestroyed() && (st == null || st.menu == null) && !mIsStartingWindow) {
invalidatePanelMenu(FEATURE_ACTION_BAR);
}
} else {
@@ -4966,4 +4968,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
mDecor.updateColorViews(null, false /* animate */);
}
}
+
+ public void setIsStartingWindow(boolean isStartingWindow) {
+ mIsStartingWindow = isStartingWindow;
+ }
}
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index 1fc0ac3..c77d614 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -37,6 +37,7 @@ import android.view.View.MeasureSpec;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.Window;
+import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
@@ -83,7 +84,7 @@ public final class FloatingToolbar {
private final Rect mContentRect = new Rect();
private Menu mMenu;
- private List<CharSequence> mShowingTitles = new ArrayList<CharSequence>();
+ private List<Object> mShowingMenuItems = new ArrayList<Object>();
private MenuItem.OnMenuItemClickListener mMenuItemClickListener = NO_OP_MENUITEM_CLICK_LISTENER;
private int mSuggestedWidth;
@@ -155,7 +156,7 @@ public final class FloatingToolbar {
if (!isCurrentlyShowing(menuItems) || mWidthChanged) {
mPopup.dismiss();
mPopup.layoutMenuItems(menuItems, mMenuItemClickListener, mSuggestedWidth);
- mShowingTitles = getMenuItemTitles(menuItems);
+ mShowingMenuItems = getShowingMenuItemsReferences(menuItems);
}
mPopup.updateCoordinates(mContentRect);
if (!mPopup.isShowing()) {
@@ -210,7 +211,7 @@ public final class FloatingToolbar {
* Returns true if this floating toolbar is currently showing the specified menu items.
*/
private boolean isCurrentlyShowing(List<MenuItem> menuItems) {
- return mShowingTitles.equals(getMenuItemTitles(menuItems));
+ return mShowingMenuItems.equals(getShowingMenuItemsReferences(menuItems));
}
/**
@@ -233,12 +234,16 @@ public final class FloatingToolbar {
return menuItems;
}
- private List<CharSequence> getMenuItemTitles(List<MenuItem> menuItems) {
- List<CharSequence> titles = new ArrayList<CharSequence>();
+ private List<Object> getShowingMenuItemsReferences(List<MenuItem> menuItems) {
+ List<Object> references = new ArrayList<Object>();
for (MenuItem menuItem : menuItems) {
- titles.add(menuItem.getTitle());
+ if (isIconOnlyMenuItem(menuItem)) {
+ references.add(menuItem.getIcon());
+ } else {
+ references.add(menuItem.getTitle());
+ }
}
- return titles;
+ return references;
}
@@ -289,7 +294,6 @@ public final class FloatingToolbar {
public void onAnimationRepeat(Animation animation) {
}
};
- private final AnimatorSet mShowAnimation;
private final AnimatorSet mDismissAnimation;
private final AnimatorSet mHideAnimation;
private final AnimationSet mOpenOverflowAnimation = new AnimationSet(true) {
@@ -324,6 +328,7 @@ public final class FloatingToolbar {
}
};
+ private final Rect mViewPort = new Rect();
private final Point mCoords = new Point();
private final Region mTouchableRegion = new Region();
@@ -353,14 +358,9 @@ public final class FloatingToolbar {
* from.
*/
public FloatingToolbarPopup(View parent) {
- mMarginHorizontal = parent.getResources()
- .getDimensionPixelSize(R.dimen.floating_toolbar_horizontal_margin);
- mMarginVertical = parent.getResources()
- .getDimensionPixelSize(R.dimen.floating_toolbar_vertical_margin);
mParent = Preconditions.checkNotNull(parent);
mContentContainer = createContentContainer(parent.getContext());
mPopupWindow = createPopupWindow(mContentContainer);
- mShowAnimation = createGrowFadeInFromBottom(mContentContainer, mMarginHorizontal);
mDismissAnimation = createShrinkFadeOutFromBottomAnimation(
mContentContainer,
150, // startDelay
@@ -380,6 +380,10 @@ public final class FloatingToolbar {
mPopupWindow.dismiss();
}
});
+ mMarginHorizontal = parent.getResources()
+ .getDimensionPixelSize(R.dimen.floating_toolbar_horizontal_margin);
+ mMarginVertical = parent.getResources()
+ .getDimensionPixelSize(R.dimen.floating_toolbar_vertical_margin);
}
/**
@@ -396,7 +400,7 @@ public final class FloatingToolbar {
mMainPanel = new FloatingToolbarMainPanel(mParent.getContext(), mOpenOverflow);
}
List<MenuItem> overflowMenuItems =
- mMainPanel.layoutMenuItems(menuItems, suggestedWidth);
+ mMainPanel.layoutMenuItems(menuItems, getToolbarWidth(suggestedWidth));
mMainPanel.setOnMenuItemClickListener(menuItemClickListener);
if (!overflowMenuItems.isEmpty()) {
if (mOverflowPanel == null) {
@@ -432,7 +436,8 @@ public final class FloatingToolbar {
// The "show" animation will make this visible.
mContentContainer.setAlpha(0);
}
- updateOverflowHeight(contentRect.top - (mMarginVertical * 2));
+ refreshViewPort();
+ updateOverflowHeight(contentRect.top - (mMarginVertical * 2) - mViewPort.top);
refreshCoordinatesAndOverflowDirection(contentRect);
preparePopupContent();
mPopupWindow.showAtLocation(mParent, Gravity.NO_GRAVITY, mCoords.x, mCoords.y);
@@ -496,6 +501,7 @@ public final class FloatingToolbar {
}
cancelOverflowAnimations();
+ refreshViewPort();
refreshCoordinatesAndOverflowDirection(contentRect);
preparePopupContent();
mPopupWindow.update(mCoords.x, mCoords.y, getWidth(), getHeight());
@@ -523,18 +529,24 @@ public final class FloatingToolbar {
}
private void refreshCoordinatesAndOverflowDirection(Rect contentRect) {
+ // NOTE: Ensure that mViewPort has been refreshed before this.
+
int x = contentRect.centerX() - getWidth() / 2;
int y;
- if (contentRect.top > getHeight()) {
+ if (contentRect.top - getHeight() > mViewPort.top) {
y = contentRect.top - getHeight();
mOverflowDirection = FloatingToolbarPopup.OVERFLOW_DIRECTION_UP;
- } else if (contentRect.top > getToolbarHeightWithVerticalMargin()) {
+ } else if (contentRect.top - getToolbarHeightWithVerticalMargin() > mViewPort.top) {
y = contentRect.top - getToolbarHeightWithVerticalMargin();
mOverflowDirection = FloatingToolbarPopup.OVERFLOW_DIRECTION_DOWN;
} else {
y = contentRect.bottom;
mOverflowDirection = FloatingToolbarPopup.OVERFLOW_DIRECTION_DOWN;
}
+
+ // Update x so that the toolbar isn't rendered behind the nav bar in landscape.
+ x = Math.max(0, Math.min(x, mViewPort.right - getWidth()));
+
mCoords.set(x, y);
if (mOverflowPanel != null) {
mOverflowPanel.setOverflowDirection(mOverflowDirection);
@@ -549,7 +561,7 @@ public final class FloatingToolbar {
* Performs the "show" animation on the floating popup.
*/
private void runShowAnimation() {
- mShowAnimation.start();
+ createGrowFadeInFromBottom(mContentContainer).start();
}
/**
@@ -597,7 +609,6 @@ public final class FloatingToolbar {
final float startY = mContentContainer.getY();
final float left = mContentContainer.getX();
final float right = left + mContentContainer.getWidth();
- final boolean rtl = mContentContainer.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
Animation widthAnimation = new Animation() {
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
@@ -605,7 +616,7 @@ public final class FloatingToolbar {
int deltaWidth = (int) (interpolatedTime * (targetWidth - startWidth));
params.width = startWidth + deltaWidth;
mContentContainer.setLayoutParams(params);
- if (rtl) {
+ if (isRTL()) {
mContentContainer.setX(left);
} else {
mContentContainer.setX(right - mContentContainer.getWidth());
@@ -656,7 +667,6 @@ public final class FloatingToolbar {
final boolean morphedUpwards = (mOverflowDirection == OVERFLOW_DIRECTION_UP);
final float left = mContentContainer.getX();
final float right = left + mContentContainer.getWidth();
- final boolean rtl = mContentContainer.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
Animation widthAnimation = new Animation() {
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
@@ -664,7 +674,7 @@ public final class FloatingToolbar {
int deltaWidth = (int) (interpolatedTime * (targetWidth - startWidth));
params.width = startWidth + deltaWidth;
mContentContainer.setLayoutParams(params);
- if (rtl) {
+ if (isRTL()) {
mContentContainer.setX(left);
} else {
mContentContainer.setX(right - mContentContainer.getWidth());
@@ -777,8 +787,13 @@ public final class FloatingToolbar {
*/
private void positionOverflowPanel() {
Preconditions.checkNotNull(mOverflowPanel);
- float x = mPopupWindow.getWidth()
+ float x;
+ if (isRTL()) {
+ x = mMarginHorizontal;
+ } else {
+ x = mPopupWindow.getWidth()
- (mOverflowPanel.getView().getMeasuredWidth() + mMarginHorizontal);
+ }
mContentContainer.setX(x);
mContentContainer.setY(mMarginVertical);
setContentAreaAsTouchableSurface();
@@ -820,6 +835,29 @@ public final class FloatingToolbar {
mPopupWindow.setHeight(height + mMarginVertical * 2);
}
+
+ private void refreshViewPort() {
+ mParent.getGlobalVisibleRect(mViewPort);
+ WindowInsets windowInsets = mParent.getRootWindowInsets();
+ mViewPort.set(
+ mViewPort.left + windowInsets.getStableInsetLeft(),
+ mViewPort.top + windowInsets.getStableInsetTop(),
+ mViewPort.right - windowInsets.getStableInsetRight(),
+ mViewPort.bottom - windowInsets.getStableInsetBottom());
+ }
+
+ private int getToolbarWidth(int suggestedWidth) {
+ int width = suggestedWidth;
+ refreshViewPort();
+ int maximumWidth = mViewPort.width() - 2 * mParent.getResources()
+ .getDimensionPixelSize(R.dimen.floating_toolbar_horizontal_margin);
+ if (width <= 0) {
+ width = mParent.getResources()
+ .getDimensionPixelSize(R.dimen.floating_toolbar_preferred_width);
+ }
+ return Math.min(width, maximumWidth);
+ }
+
/**
* Sets the touchable region of this popup to be zero. This means that all touch events on
* this popup will go through to the surface behind it.
@@ -856,6 +894,10 @@ public final class FloatingToolbar {
viewTreeObserver.removeOnComputeInternalInsetsListener(mInsetsComputer);
viewTreeObserver.addOnComputeInternalInsetsListener(mInsetsComputer);
}
+
+ private boolean isRTL() {
+ return mContentContainer.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
+ }
}
/**
@@ -901,12 +943,11 @@ public final class FloatingToolbar {
*
* @return The menu items that are not included in this main panel.
*/
- public List<MenuItem> layoutMenuItems(List<MenuItem> menuItems, int suggestedWidth) {
+ public List<MenuItem> layoutMenuItems(List<MenuItem> menuItems, int width) {
Preconditions.checkNotNull(menuItems);
- final int toolbarWidth = getAdjustedToolbarWidth(mContext, suggestedWidth)
- // Reserve space for the "open overflow" button.
- - getEstimatedOpenOverflowButtonWidth(mContext);
+ // Reserve space for the "open overflow" button.
+ final int toolbarWidth = width - getEstimatedOpenOverflowButtonWidth(mContext);
int availableWidth = toolbarWidth;
final LinkedList<MenuItem> remainingMenuItems = new LinkedList<MenuItem>(menuItems);
@@ -1332,14 +1373,14 @@ public final class FloatingToolbar {
*
* @param view The view to animate
*/
- private static AnimatorSet createGrowFadeInFromBottom(View view, int x) {
+ private static AnimatorSet createGrowFadeInFromBottom(View view) {
AnimatorSet growFadeInFromBottomAnimation = new AnimatorSet();
growFadeInFromBottomAnimation.playTogether(
ObjectAnimator.ofFloat(view, View.SCALE_X, 0.5f, 1).setDuration(125),
ObjectAnimator.ofFloat(view, View.SCALE_Y, 0.5f, 1).setDuration(125),
ObjectAnimator.ofFloat(view, View.ALPHA, 0, 1).setDuration(75),
// Make sure that view.x is always fixed throughout the duration of this animation.
- ObjectAnimator.ofFloat(view, View.X, x, x));
+ ObjectAnimator.ofFloat(view, View.X, view.getX(), view.getX()));
growFadeInFromBottomAnimation.setStartDelay(50);
return growFadeInFromBottomAnimation;
}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index aee0ff6..86d11be 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -841,7 +841,7 @@ public class LockPatternUtils {
final byte[] bytes = string.getBytes();
for (int i = 0; i < bytes.length; i++) {
- byte b = bytes[i];
+ byte b = (byte) (bytes[i] - '1');
result.add(LockPatternView.Cell.of(b / 3, b % 3));
}
return result;
@@ -861,7 +861,21 @@ public class LockPatternUtils {
byte[] res = new byte[patternSize];
for (int i = 0; i < patternSize; i++) {
LockPatternView.Cell cell = pattern.get(i);
- res[i] = (byte) (cell.getRow() * 3 + cell.getColumn());
+ res[i] = (byte) (cell.getRow() * 3 + cell.getColumn() + '1');
+ }
+ return new String(res);
+ }
+
+ public static String patternStringToBaseZero(String pattern) {
+ if (pattern == null) {
+ return "";
+ }
+ final int patternSize = pattern.length();
+
+ byte[] res = new byte[patternSize];
+ final byte[] bytes = pattern.getBytes();
+ for (int i = 0; i < patternSize; i++) {
+ res[i] = (byte) (bytes[i] - '1');
}
return new String(res);
}