Merge "Further improved NotificationStackScroller"
diff --git a/Android.mk b/Android.mk
index 84d5dc5..adc9ef1 100644
--- a/Android.mk
+++ b/Android.mk
@@ -420,6 +420,8 @@
frameworks/base/core/java/android/view/MotionEvent.aidl \
frameworks/base/core/java/android/view/Surface.aidl \
frameworks/base/core/java/android/view/WindowManager.aidl \
+ frameworks/base/core/java/android/view/WindowAnimationFrameStats.aidl \
+ frameworks/base/core/java/android/view/WindowContentFrameStats.aidl \
frameworks/base/core/java/android/widget/RemoteViews.aidl \
frameworks/base/core/java/com/android/internal/textservice/ISpellCheckerService.aidl \
frameworks/base/core/java/com/android/internal/textservice/ISpellCheckerSession.aidl \
diff --git a/api/current.txt b/api/current.txt
index bc02fed..8564a89 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4453,6 +4453,7 @@
ctor public Notification.Builder(android.content.Context);
method public android.app.Notification.Builder addAction(int, java.lang.CharSequence, android.app.PendingIntent);
method public android.app.Notification.Builder addExtras(android.os.Bundle);
+ method public android.app.Notification.Builder addPerson(java.lang.String);
method public android.app.Notification build();
method public android.os.Bundle getExtras();
method public deprecated android.app.Notification getNotification();
@@ -4751,9 +4752,13 @@
}
public final class UiAutomation {
+ method public void clearWindowAnimationFrameStats();
+ method public boolean clearWindowContentFrameStats(int);
method public android.view.accessibility.AccessibilityEvent executeAndWaitForEvent(java.lang.Runnable, android.app.UiAutomation.AccessibilityEventFilter, long) throws java.util.concurrent.TimeoutException;
method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow();
method public final android.accessibilityservice.AccessibilityServiceInfo getServiceInfo();
+ method public android.view.WindowAnimationFrameStats getWindowAnimationFrameStats();
+ method public android.view.WindowContentFrameStats getWindowContentFrameStats(int);
method public java.util.List<android.view.accessibility.AccessibilityWindowInfo> getWindows();
method public boolean injectInputEvent(android.view.InputEvent, boolean);
method public final boolean performGlobalAction(int);
@@ -11727,6 +11732,7 @@
field public static final int CONTROL_AWB_STATE_LOCKED = 3; // 0x3
field public static final int CONTROL_AWB_STATE_SEARCHING = 1; // 0x1
field public static final int CONTROL_CAPTURE_INTENT_CUSTOM = 0; // 0x0
+ field public static final int CONTROL_CAPTURE_INTENT_MANUAL = 6; // 0x6
field public static final int CONTROL_CAPTURE_INTENT_PREVIEW = 1; // 0x1
field public static final int CONTROL_CAPTURE_INTENT_STILL_CAPTURE = 2; // 0x2
field public static final int CONTROL_CAPTURE_INTENT_VIDEO_RECORD = 3; // 0x3
@@ -28443,6 +28449,18 @@
method public static android.view.FocusFinder getInstance();
}
+ public abstract class FrameStats {
+ ctor public FrameStats();
+ method public final long getEndTimeNano();
+ method public final int getFrameCount();
+ method public final long getFramePresentedTimeNano(int);
+ method public final long getRefreshPeriodNano();
+ method public final long getStartTimeNano();
+ field public static final long UNDEFINED_TIME_NANO = -1L; // 0xffffffffffffffffL
+ field protected long[] mFramesPresentedTimeNano;
+ field protected long mRefreshPeriodNano;
+ }
+
public class GestureDetector {
ctor public deprecated GestureDetector(android.view.GestureDetector.OnGestureListener, android.os.Handler);
ctor public deprecated GestureDetector(android.view.GestureDetector.OnGestureListener);
@@ -30767,6 +30785,20 @@
method public abstract android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
}
+ public final class WindowAnimationFrameStats extends android.view.FrameStats implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
+ }
+
+ public final class WindowContentFrameStats extends android.view.FrameStats implements android.os.Parcelable {
+ method public int describeContents();
+ method public long getFramePostedTimeNano(int);
+ method public long getFrameReadyTimeNano(int);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
+ }
+
public class WindowId implements android.os.Parcelable {
method public int describeContents();
method public boolean isFocused();
diff --git a/core/java/android/app/IUiAutomationConnection.aidl b/core/java/android/app/IUiAutomationConnection.aidl
index 09bf829..347de97 100644
--- a/core/java/android/app/IUiAutomationConnection.aidl
+++ b/core/java/android/app/IUiAutomationConnection.aidl
@@ -19,6 +19,8 @@
import android.accessibilityservice.IAccessibilityServiceClient;
import android.graphics.Bitmap;
import android.view.InputEvent;
+import android.view.WindowContentFrameStats;
+import android.view.WindowAnimationFrameStats;
import android.os.ParcelFileDescriptor;
/**
@@ -26,7 +28,7 @@
* on behalf of an instrumentation that it runs. These operations require
* special permissions which the shell user has but the instrumentation does
* not. Running privileged operations by the shell user on behalf of an
- * instrumentation is needed for running UiTestCases.
+ * instrumentation is needed for running UiTestCases.
*
* {@hide}
*/
@@ -37,4 +39,8 @@
boolean setRotation(int rotation);
Bitmap takeScreenshot(int width, int height);
void shutdown();
+ boolean clearWindowContentFrameStats(int windowId);
+ WindowContentFrameStats getWindowContentFrameStats(int windowId);
+ void clearWindowAnimationFrameStats();
+ WindowAnimationFrameStats getWindowAnimationFrameStats();
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 36d2635..fe629f6 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1311,6 +1311,7 @@
private Notification mPublicVersion = null;
private boolean mQuantumTheme;
private final LegacyNotificationUtil mLegacyNotificationUtil;
+ private ArrayList<String> mPeople;
/**
* Constructs a new Builder with the defaults:
@@ -1338,6 +1339,7 @@
mWhen = System.currentTimeMillis();
mAudioStreamType = STREAM_DEFAULT;
mPriority = PRIORITY_DEFAULT;
+ mPeople = new ArrayList<String>();
// TODO: Decide on targetSdk from calling app whether to use quantum theme.
mQuantumTheme = true;
@@ -1723,6 +1725,16 @@
}
/**
+ * Add a person that is relevant to this notification.
+ *
+ * @see Notification#EXTRA_PEOPLE
+ */
+ public Builder addPerson(String handle) {
+ mPeople.add(handle);
+ return this;
+ }
+
+ /**
* Merge additional metadata into this notification.
*
* <p>Values within the Bundle will replace existing extras values in this Builder.
@@ -2149,6 +2161,9 @@
if (mLargeIcon != null) {
extras.putParcelable(EXTRA_LARGE_ICON, mLargeIcon);
}
+ if (!mPeople.isEmpty()) {
+ extras.putStringArray(EXTRA_PEOPLE, mPeople.toArray(new String[mPeople.size()]));
+ }
}
/**
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index 354a19f..8523d0c 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -33,6 +33,8 @@
import android.view.InputEvent;
import android.view.KeyEvent;
import android.view.Surface;
+import android.view.WindowAnimationFrameStats;
+import android.view.WindowContentFrameStats;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityInteractionClient;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -674,6 +676,148 @@
}
}
+ /**
+ * Clears the frame statistics for the content of a given window. These
+ * statistics contain information about the most recently rendered content
+ * frames.
+ *
+ * @param windowId The window id.
+ * @return Whether the window is present and its frame statistics
+ * were cleared.
+ *
+ * @see android.view.WindowContentFrameStats
+ * @see #getWindowContentFrameStats(int)
+ * @see #getWindows()
+ * @see AccessibilityWindowInfo#getId() AccessibilityWindowInfo.getId()
+ */
+ public boolean clearWindowContentFrameStats(int windowId) {
+ synchronized (mLock) {
+ throwIfNotConnectedLocked();
+ }
+ try {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Clearing content frame stats for window: " + windowId);
+ }
+ // Calling out without a lock held.
+ return mUiAutomationConnection.clearWindowContentFrameStats(windowId);
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error clearing window content frame stats!", re);
+ }
+ return false;
+ }
+
+ /**
+ * Gets the frame statistics for a given window. These statistics contain
+ * information about the most recently rendered content frames.
+ * <p>
+ * A typical usage requires clearing the window frame statistics via {@link
+ * #clearWindowContentFrameStats(int)} followed by an interaction with the UI and
+ * finally getting the window frame statistics via calling this method.
+ * </p>
+ * <pre>
+ * // Assume we have at least one window.
+ * final int windowId = getWindows().get(0).getId();
+ *
+ * // Start with a clean slate.
+ * uiAutimation.clearWindowContentFrameStats(windowId);
+ *
+ * // Do stuff with the UI.
+ *
+ * // Get the frame statistics.
+ * WindowContentFrameStats stats = uiAutomation.getWindowContentFrameStats(windowId);
+ * </pre>
+ *
+ * @param windowId The window id.
+ * @return The window frame statistics, or null if the window is not present.
+ *
+ * @see android.view.WindowContentFrameStats
+ * @see #clearWindowContentFrameStats(int)
+ * @see #getWindows()
+ * @see AccessibilityWindowInfo#getId() AccessibilityWindowInfo.getId()
+ */
+ public WindowContentFrameStats getWindowContentFrameStats(int windowId) {
+ synchronized (mLock) {
+ throwIfNotConnectedLocked();
+ }
+ try {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Getting content frame stats for window: " + windowId);
+ }
+ // Calling out without a lock held.
+ return mUiAutomationConnection.getWindowContentFrameStats(windowId);
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error getting window content frame stats!", re);
+ }
+ return null;
+ }
+
+ /**
+ * Clears the window animation rendering statistics. These statistics contain
+ * information about the most recently rendered window animation frames, i.e.
+ * for window transition animations.
+ *
+ * @see android.view.WindowAnimationFrameStats
+ * @see #getWindowAnimationFrameStats()
+ * @see android.R.styleable#WindowAnimation
+ */
+ public void clearWindowAnimationFrameStats() {
+ synchronized (mLock) {
+ throwIfNotConnectedLocked();
+ }
+ try {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Clearing window animation frame stats");
+ }
+ // Calling out without a lock held.
+ mUiAutomationConnection.clearWindowAnimationFrameStats();
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error clearing window animation frame stats!", re);
+ }
+ }
+
+ /**
+ * Gets the window animation frame statistics. These statistics contain
+ * information about the most recently rendered window animation frames, i.e.
+ * for window transition animations.
+ *
+ * <p>
+ * A typical usage requires clearing the window animation frame statistics via
+ * {@link #clearWindowAnimationFrameStats()} followed by an interaction that causes
+ * a window transition which uses a window animation and finally getting the window
+ * animation frame statistics by calling this method.
+ * </p>
+ * <pre>
+ * // Start with a clean slate.
+ * uiAutimation.clearWindowAnimationFrameStats();
+ *
+ * // Do stuff to trigger a window transition.
+ *
+ * // Get the frame statistics.
+ * WindowAnimationFrameStats stats = uiAutomation.getWindowAnimationFrameStats();
+ * </pre>
+ *
+ * @return The window animation frame statistics.
+ *
+ * @see android.view.WindowAnimationFrameStats
+ * @see #clearWindowAnimationFrameStats()
+ * @see android.R.styleable#WindowAnimation
+ */
+ public WindowAnimationFrameStats getWindowAnimationFrameStats() {
+ synchronized (mLock) {
+ throwIfNotConnectedLocked();
+ }
+ try {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Getting window animation frame stats");
+ }
+ // Calling out without a lock held.
+ return mUiAutomationConnection.getWindowAnimationFrameStats();
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error getting window animation frame stats!", re);
+ }
+ return null;
+ }
+
private static float getDegreesForRotation(int value) {
switch (value) {
case Surface.ROTATION_90: {
diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java
index 91b0d7c..fa40286 100644
--- a/core/java/android/app/UiAutomationConnection.java
+++ b/core/java/android/app/UiAutomationConnection.java
@@ -22,12 +22,15 @@
import android.graphics.Bitmap;
import android.hardware.input.InputManager;
import android.os.Binder;
+import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.view.IWindowManager;
import android.view.InputEvent;
import android.view.SurfaceControl;
+import android.view.WindowAnimationFrameStats;
+import android.view.WindowContentFrameStats;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.IAccessibilityManager;
@@ -47,6 +50,9 @@
private final IWindowManager mWindowManager = IWindowManager.Stub.asInterface(
ServiceManager.getService(Service.WINDOW_SERVICE));
+ private final IAccessibilityManager mAccessibilityManager = IAccessibilityManager.Stub.asInterface(
+ ServiceManager.getService(Service.ACCESSIBILITY_SERVICE));
+
private final Object mLock = new Object();
private final Binder mToken = new Binder();
@@ -144,6 +150,76 @@
}
@Override
+ public boolean clearWindowContentFrameStats(int windowId) throws RemoteException {
+ synchronized (mLock) {
+ throwIfCalledByNotTrustedUidLocked();
+ throwIfShutdownLocked();
+ throwIfNotConnectedLocked();
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ IBinder token = mAccessibilityManager.getWindowToken(windowId);
+ if (token == null) {
+ return false;
+ }
+ return mWindowManager.clearWindowContentFrameStats(token);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public WindowContentFrameStats getWindowContentFrameStats(int windowId) throws RemoteException {
+ synchronized (mLock) {
+ throwIfCalledByNotTrustedUidLocked();
+ throwIfShutdownLocked();
+ throwIfNotConnectedLocked();
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ IBinder token = mAccessibilityManager.getWindowToken(windowId);
+ if (token == null) {
+ return null;
+ }
+ return mWindowManager.getWindowContentFrameStats(token);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void clearWindowAnimationFrameStats() {
+ synchronized (mLock) {
+ throwIfCalledByNotTrustedUidLocked();
+ throwIfShutdownLocked();
+ throwIfNotConnectedLocked();
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ SurfaceControl.clearAnimationFrameStats();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public WindowAnimationFrameStats getWindowAnimationFrameStats() {
+ synchronized (mLock) {
+ throwIfCalledByNotTrustedUidLocked();
+ throwIfShutdownLocked();
+ throwIfNotConnectedLocked();
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ WindowAnimationFrameStats stats = new WindowAnimationFrameStats();
+ SurfaceControl.getAnimationFrameStats(stats);
+ return stats;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
public void shutdown() {
synchronized (mLock) {
if (isConnectedLocked()) {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 30c84f6..d8be439 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1534,10 +1534,10 @@
/**
* @hide
*/
- public void setActiveAdmin(ComponentName policyReceiver, boolean refreshing) {
+ public void setActiveAdmin(ComponentName policyReceiver, boolean refreshing, int userHandle) {
if (mService != null) {
try {
- mService.setActiveAdmin(policyReceiver, refreshing, UserHandle.myUserId());
+ mService.setActiveAdmin(policyReceiver, refreshing, userHandle);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -1545,6 +1545,13 @@
}
/**
+ * @hide
+ */
+ public void setActiveAdmin(ComponentName policyReceiver, boolean refreshing) {
+ setActiveAdmin(policyReceiver, refreshing, UserHandle.myUserId());
+ }
+
+ /**
* Returns the DeviceAdminInfo as defined by the administrator's package info & meta-data
* @hide
*/
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 101b721..ff3af7c 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -50,6 +50,7 @@
private boolean mAutoConnect;
private int mConnState;
private final Object mStateLock = new Object();
+ private Boolean mDeviceBusy = false;
private static final int CONN_STATE_IDLE = 0;
private static final int CONN_STATE_CONNECTING = 1;
@@ -166,6 +167,10 @@
mConnState = CONN_STATE_IDLE;
}
}
+
+ synchronized(mDeviceBusy) {
+ mDeviceBusy = false;
+ }
}
/**
@@ -301,6 +306,11 @@
if (!address.equals(mDevice.getAddress())) {
return;
}
+
+ synchronized(mDeviceBusy) {
+ mDeviceBusy = false;
+ }
+
if ((status == GATT_INSUFFICIENT_AUTHENTICATION
|| status == GATT_INSUFFICIENT_ENCRYPTION)
&& mAuthRetry == false) {
@@ -348,6 +358,11 @@
if (!address.equals(mDevice.getAddress())) {
return;
}
+
+ synchronized(mDeviceBusy) {
+ mDeviceBusy = false;
+ }
+
BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
srvcInstId, srvcType);
if (service == null) return;
@@ -425,6 +440,11 @@
if (!address.equals(mDevice.getAddress())) {
return;
}
+
+ synchronized(mDeviceBusy) {
+ mDeviceBusy = false;
+ }
+
BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
srvcInstId, srvcType);
if (service == null) return;
@@ -474,6 +494,11 @@
if (!address.equals(mDevice.getAddress())) {
return;
}
+
+ synchronized(mDeviceBusy) {
+ mDeviceBusy = false;
+ }
+
BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
srvcInstId, srvcType);
if (service == null) return;
@@ -519,6 +544,11 @@
if (!address.equals(mDevice.getAddress())) {
return;
}
+
+ synchronized(mDeviceBusy) {
+ mDeviceBusy = false;
+ }
+
try {
mCallback.onReliableWriteCompleted(BluetoothGatt.this, status);
} catch (Exception ex) {
@@ -851,6 +881,11 @@
BluetoothDevice device = service.getDevice();
if (device == null) return false;
+ synchronized(mDeviceBusy) {
+ if (mDeviceBusy) return false;
+ mDeviceBusy = true;
+ }
+
try {
mService.readCharacteristic(mClientIf, device.getAddress(),
service.getType(), service.getInstanceId(),
@@ -858,6 +893,7 @@
new ParcelUuid(characteristic.getUuid()), AUTHENTICATION_NONE);
} catch (RemoteException e) {
Log.e(TAG,"",e);
+ mDeviceBusy = false;
return false;
}
@@ -890,6 +926,11 @@
BluetoothDevice device = service.getDevice();
if (device == null) return false;
+ synchronized(mDeviceBusy) {
+ if (mDeviceBusy) return false;
+ mDeviceBusy = true;
+ }
+
try {
mService.writeCharacteristic(mClientIf, device.getAddress(),
service.getType(), service.getInstanceId(),
@@ -899,6 +940,7 @@
characteristic.getValue());
} catch (RemoteException e) {
Log.e(TAG,"",e);
+ mDeviceBusy = false;
return false;
}
@@ -930,6 +972,11 @@
BluetoothDevice device = service.getDevice();
if (device == null) return false;
+ synchronized(mDeviceBusy) {
+ if (mDeviceBusy) return false;
+ mDeviceBusy = true;
+ }
+
try {
mService.readDescriptor(mClientIf, device.getAddress(), service.getType(),
service.getInstanceId(), new ParcelUuid(service.getUuid()),
@@ -938,6 +985,7 @@
AUTHENTICATION_NONE);
} catch (RemoteException e) {
Log.e(TAG,"",e);
+ mDeviceBusy = false;
return false;
}
@@ -968,6 +1016,11 @@
BluetoothDevice device = service.getDevice();
if (device == null) return false;
+ synchronized(mDeviceBusy) {
+ if (mDeviceBusy) return false;
+ mDeviceBusy = true;
+ }
+
try {
mService.writeDescriptor(mClientIf, device.getAddress(), service.getType(),
service.getInstanceId(), new ParcelUuid(service.getUuid()),
@@ -977,6 +1030,7 @@
descriptor.getValue());
} catch (RemoteException e) {
Log.e(TAG,"",e);
+ mDeviceBusy = false;
return false;
}
@@ -1034,10 +1088,16 @@
if (DBG) Log.d(TAG, "executeReliableWrite() - device: " + mDevice.getAddress());
if (mService == null || mClientIf == 0) return false;
+ synchronized(mDeviceBusy) {
+ if (mDeviceBusy) return false;
+ mDeviceBusy = true;
+ }
+
try {
mService.endReliableWrite(mClientIf, mDevice.getAddress(), true);
} catch (RemoteException e) {
Log.e(TAG,"",e);
+ mDeviceBusy = false;
return false;
}
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 5d02ae9..0d1b262 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -447,6 +447,15 @@
public String nativeLibraryDir;
/**
+ * The ABI that this application requires, This is inferred from the ABIs
+ * of the native JNI libraries the application bundles. Will be {@code null}
+ * if this application does not require any particular ABI.
+ *
+ * {@hide}
+ */
+ public String requiredCpuAbi;
+
+ /**
* The kernel user-ID that has been assigned to this application;
* currently this is not a unique ID (multiple applications can have
* the same uid).
@@ -583,6 +592,7 @@
sourceDir = orig.sourceDir;
publicSourceDir = orig.publicSourceDir;
nativeLibraryDir = orig.nativeLibraryDir;
+ requiredCpuAbi = orig.requiredCpuAbi;
resourceDirs = orig.resourceDirs;
seinfo = orig.seinfo;
sharedLibraryFiles = orig.sharedLibraryFiles;
@@ -624,6 +634,7 @@
dest.writeString(sourceDir);
dest.writeString(publicSourceDir);
dest.writeString(nativeLibraryDir);
+ dest.writeString(requiredCpuAbi);
dest.writeStringArray(resourceDirs);
dest.writeString(seinfo);
dest.writeStringArray(sharedLibraryFiles);
@@ -664,6 +675,7 @@
sourceDir = source.readString();
publicSourceDir = source.readString();
nativeLibraryDir = source.readString();
+ requiredCpuAbi = source.readString();
resourceDirs = source.readStringArray();
seinfo = source.readString();
sharedLibraryFiles = source.readStringArray();
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 3300e9d..d24a472 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -698,6 +698,25 @@
public static final int INSTALL_FAILED_DUPLICATE_PERMISSION = -112;
/**
+ * Installation failed return code: this is passed to the {@link IPackageInstallObserver} by
+ * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
+ * if the system failed to install the package because its packaged native code did not
+ * match any of the ABIs supported by the system.
+ *
+ * @hide
+ */
+ public static final int INSTALL_FAILED_NO_MATCHING_ABIS = -113;
+
+ /**
+ * Internal return code for NativeLibraryHelper methods to indicate that the package
+ * being processed did not contain any native code. This is placed here only so that
+ * it can belong to the same value space as the other install failure codes.
+ *
+ * @hide
+ */
+ public static final int NO_NATIVE_LIBRARIES = -114;
+
+ /**
* Flag parameter for {@link #deletePackage} to indicate that you don't want to delete the
* package's data directory.
*
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 1e34498..9b1bc53 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -940,6 +940,17 @@
*/
public static final int CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG = 5;
+ /**
+ * <p>This request is for manual capture use case where
+ * the applications want to directly control the capture parameters
+ * (e.g. {@link CaptureRequest#SENSOR_EXPOSURE_TIME android.sensor.exposureTime}, {@link CaptureRequest#SENSOR_SENSITIVITY android.sensor.sensitivity} etc.).</p>
+ *
+ * @see CaptureRequest#SENSOR_EXPOSURE_TIME
+ * @see CaptureRequest#SENSOR_SENSITIVITY
+ * @see CaptureRequest#CONTROL_CAPTURE_INTENT
+ */
+ public static final int CONTROL_CAPTURE_INTENT_MANUAL = 6;
+
//
// Enumeration values for CaptureRequest#CONTROL_EFFECT_MODE
//
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 7656505..c4e342c 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -714,16 +714,21 @@
* auto-focus, auto-white balance) routines about the purpose
* of this capture, to help the camera device to decide optimal 3A
* strategy.</p>
- * <p>This control is only effective if <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} != OFF</code>
- * and any 3A routine is active.</p>
+ * <p>This control (except for MANUAL) is only effective if
+ * <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} != OFF</code> and any 3A routine is active.</p>
+ * <p>ZERO_SHUTTER_LAG must be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
+ * contains ZSL. MANUAL must be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
+ * contains MANUAL_SENSOR.</p>
*
* @see CaptureRequest#CONTROL_MODE
+ * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
* @see #CONTROL_CAPTURE_INTENT_CUSTOM
* @see #CONTROL_CAPTURE_INTENT_PREVIEW
* @see #CONTROL_CAPTURE_INTENT_STILL_CAPTURE
* @see #CONTROL_CAPTURE_INTENT_VIDEO_RECORD
* @see #CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT
* @see #CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG
+ * @see #CONTROL_CAPTURE_INTENT_MANUAL
*/
public static final Key<Integer> CONTROL_CAPTURE_INTENT =
new Key<Integer>("android.control.captureIntent", int.class);
diff --git a/core/java/android/hardware/camera2/CaptureResultExtras.aidl b/core/java/android/hardware/camera2/CaptureResultExtras.aidl
new file mode 100644
index 0000000..6587f02
--- /dev/null
+++ b/core/java/android/hardware/camera2/CaptureResultExtras.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2;
+
+/** @hide */
+parcelable CaptureResultExtras;
diff --git a/core/java/android/hardware/camera2/CaptureResultExtras.java b/core/java/android/hardware/camera2/CaptureResultExtras.java
new file mode 100644
index 0000000..e5c2c1c
--- /dev/null
+++ b/core/java/android/hardware/camera2/CaptureResultExtras.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.camera2;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * @hide
+ */
+public class CaptureResultExtras implements Parcelable {
+ private int requestId;
+ private int subsequenceId;
+ private int afTriggerId;
+ private int precaptureTriggerId;
+ private long frameNumber;
+
+ public static final Parcelable.Creator<CaptureResultExtras> CREATOR =
+ new Parcelable.Creator<CaptureResultExtras>() {
+ @Override
+ public CaptureResultExtras createFromParcel(Parcel in) {
+ return new CaptureResultExtras(in);
+ }
+
+ @Override
+ public CaptureResultExtras[] newArray(int size) {
+ return new CaptureResultExtras[size];
+ }
+ };
+
+ private CaptureResultExtras(Parcel in) {
+ readFromParcel(in);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(requestId);
+ dest.writeInt(subsequenceId);
+ dest.writeInt(afTriggerId);
+ dest.writeInt(precaptureTriggerId);
+ dest.writeLong(frameNumber);
+ }
+
+ public void readFromParcel(Parcel in) {
+ requestId = in.readInt();
+ subsequenceId = in.readInt();
+ afTriggerId = in.readInt();
+ precaptureTriggerId = in.readInt();
+ frameNumber = in.readLong();
+ }
+
+ public int getRequestId() {
+ return requestId;
+ }
+
+ public int getSubsequenceId() {
+ return subsequenceId;
+ }
+
+ public int getAfTriggerId() {
+ return afTriggerId;
+ }
+
+ public int getPrecaptureTriggerId() {
+ return precaptureTriggerId;
+ }
+
+ public long getFrameNumber() {
+ return frameNumber;
+ }
+
+}
diff --git a/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl b/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl
index 02a73d66..a14d38b 100644
--- a/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl
+++ b/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl
@@ -17,6 +17,7 @@
package android.hardware.camera2;
import android.hardware.camera2.impl.CameraMetadataNative;
+import android.hardware.camera2.CaptureResultExtras;
/** @hide */
interface ICameraDeviceCallbacks
@@ -25,8 +26,9 @@
* Keep up-to-date with frameworks/av/include/camera/camera2/ICameraDeviceCallbacks.h
*/
- oneway void onCameraError(int errorCode);
+ oneway void onCameraError(int errorCode, in CaptureResultExtras resultExtras);
oneway void onCameraIdle();
- oneway void onCaptureStarted(int requestId, long timestamp);
- oneway void onResultReceived(int requestId, in CameraMetadataNative result);
+ oneway void onCaptureStarted(in CaptureResultExtras resultExtras, long timestamp);
+ oneway void onResultReceived(in CameraMetadataNative result,
+ in CaptureResultExtras resultExtras);
}
diff --git a/core/java/android/hardware/camera2/ICameraDeviceUser.aidl b/core/java/android/hardware/camera2/ICameraDeviceUser.aidl
index 1936963..d77f3d1 100644
--- a/core/java/android/hardware/camera2/ICameraDeviceUser.aidl
+++ b/core/java/android/hardware/camera2/ICameraDeviceUser.aidl
@@ -20,6 +20,8 @@
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.LongParcelable;
+
/** @hide */
interface ICameraDeviceUser
{
@@ -31,9 +33,13 @@
// ints here are status_t
// non-negative value is the requestId. negative value is status_t
- int submitRequest(in CaptureRequest request, boolean streaming);
+ int submitRequest(in CaptureRequest request, boolean streaming,
+ out LongParcelable lastFrameNumber);
- int cancelRequest(int requestId);
+ int submitRequestList(in List<CaptureRequest> requestList, boolean streaming,
+ out LongParcelable lastFrameNumber);
+
+ int cancelRequest(int requestId, out LongParcelable lastFrameNumber);
int deleteStream(int streamId);
@@ -46,5 +52,5 @@
int waitUntilIdle();
- int flush();
+ int flush(out LongParcelable lastFrameNumber);
}
diff --git a/core/java/android/hardware/camera2/LongParcelable.aidl b/core/java/android/hardware/camera2/LongParcelable.aidl
new file mode 100644
index 0000000..7d7e51b
--- /dev/null
+++ b/core/java/android/hardware/camera2/LongParcelable.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2;
+
+/** @hide */
+parcelable LongParcelable;
\ No newline at end of file
diff --git a/core/java/android/hardware/camera2/LongParcelable.java b/core/java/android/hardware/camera2/LongParcelable.java
new file mode 100644
index 0000000..97b0631
--- /dev/null
+++ b/core/java/android/hardware/camera2/LongParcelable.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.camera2;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * @hide
+ */
+public class LongParcelable implements Parcelable {
+ private long number;
+
+ public LongParcelable() {
+ this.number = 0;
+ }
+
+ public LongParcelable(long number) {
+ this.number = number;
+ }
+
+ public static final Parcelable.Creator<LongParcelable> CREATOR =
+ new Parcelable.Creator<LongParcelable>() {
+ @Override
+ public LongParcelable createFromParcel(Parcel in) {
+ return new LongParcelable(in);
+ }
+
+ @Override
+ public LongParcelable[] newArray(int size) {
+ return new LongParcelable[size];
+ }
+ };
+
+ private LongParcelable(Parcel in) {
+ readFromParcel(in);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeLong(number);
+ }
+
+ public void readFromParcel(Parcel in) {
+ number = in.readLong();
+ }
+
+ public long getNumber() {
+ return number;
+ }
+
+ public void setNumber(long number) {
+ this.number = number;
+ }
+
+}
diff --git a/core/java/android/hardware/camera2/impl/CameraDevice.java b/core/java/android/hardware/camera2/impl/CameraDevice.java
index ecc461e..cd44b51 100644
--- a/core/java/android/hardware/camera2/impl/CameraDevice.java
+++ b/core/java/android/hardware/camera2/impl/CameraDevice.java
@@ -21,8 +21,10 @@
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.CaptureResultExtras;
import android.hardware.camera2.ICameraDeviceCallbacks;
import android.hardware.camera2.ICameraDeviceUser;
+import android.hardware.camera2.LongParcelable;
import android.hardware.camera2.utils.CameraBinderDecorator;
import android.hardware.camera2.utils.CameraRuntimeException;
import android.os.Handler;
@@ -33,10 +35,12 @@
import android.util.SparseArray;
import android.view.Surface;
+import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.TreeSet;
/**
* HAL2.1+ implementation of CameraDevice. Use CameraManager#open to instantiate
@@ -69,10 +73,24 @@
private final String mCameraId;
+ /**
+ * A list tracking request and its expected last frame.
+ * Updated when calling ICameraDeviceUser methods.
+ */
+ private final List<SimpleEntry</*frameNumber*/Long, /*requestId*/Integer>>
+ mFrameNumberRequestPairs = new ArrayList<SimpleEntry<Long, Integer>>();
+
+ /**
+ * An object tracking received frame numbers.
+ * Updated when receiving callbacks from ICameraDeviceCallbacks.
+ */
+ private final FrameNumberTracker mFrameNumberTracker = new FrameNumberTracker();
+
// Runnables for all state transitions, except error, which needs the
// error code argument
private final Runnable mCallOnOpened = new Runnable() {
+ @Override
public void run() {
if (!CameraDevice.this.isClosed()) {
mDeviceListener.onOpened(CameraDevice.this);
@@ -81,6 +99,7 @@
};
private final Runnable mCallOnUnconfigured = new Runnable() {
+ @Override
public void run() {
if (!CameraDevice.this.isClosed()) {
mDeviceListener.onUnconfigured(CameraDevice.this);
@@ -89,6 +108,7 @@
};
private final Runnable mCallOnActive = new Runnable() {
+ @Override
public void run() {
if (!CameraDevice.this.isClosed()) {
mDeviceListener.onActive(CameraDevice.this);
@@ -97,6 +117,7 @@
};
private final Runnable mCallOnBusy = new Runnable() {
+ @Override
public void run() {
if (!CameraDevice.this.isClosed()) {
mDeviceListener.onBusy(CameraDevice.this);
@@ -105,12 +126,14 @@
};
private final Runnable mCallOnClosed = new Runnable() {
+ @Override
public void run() {
mDeviceListener.onClosed(CameraDevice.this);
}
};
private final Runnable mCallOnIdle = new Runnable() {
+ @Override
public void run() {
if (!CameraDevice.this.isClosed()) {
mDeviceListener.onIdle(CameraDevice.this);
@@ -119,6 +142,7 @@
};
private final Runnable mCallOnDisconnected = new Runnable() {
+ @Override
public void run() {
if (!CameraDevice.this.isClosed()) {
mDeviceListener.onDisconnected(CameraDevice.this);
@@ -249,22 +273,26 @@
@Override
public int capture(CaptureRequest request, CaptureListener listener, Handler handler)
throws CameraAccessException {
- return submitCaptureRequest(request, listener, handler, /*streaming*/false);
+ if (DEBUG) {
+ Log.d(TAG, "calling capture");
+ }
+ List<CaptureRequest> requestList = new ArrayList<CaptureRequest>();
+ requestList.add(request);
+ return submitCaptureRequest(requestList, listener, handler, /*streaming*/false);
}
@Override
public int captureBurst(List<CaptureRequest> requests, CaptureListener listener,
Handler handler) throws CameraAccessException {
+ // TODO: remove this. Throw IAE if the request is null or empty. Need to update API doc.
if (requests.isEmpty()) {
Log.w(TAG, "Capture burst request list is empty, do nothing!");
return -1;
}
- // TODO
- throw new UnsupportedOperationException("Burst capture implemented yet");
-
+ return submitCaptureRequest(requests, listener, handler, /*streaming*/false);
}
- private int submitCaptureRequest(CaptureRequest request, CaptureListener listener,
+ private int submitCaptureRequest(List<CaptureRequest> requestList, CaptureListener listener,
Handler handler, boolean repeating) throws CameraAccessException {
// Need a valid handler, or current thread needs to have a looper, if
@@ -281,8 +309,13 @@
stopRepeating();
}
+ LongParcelable lastFrameNumberRef = new LongParcelable();
try {
- requestId = mRemoteDevice.submitRequest(request, repeating);
+ requestId = mRemoteDevice.submitRequestList(requestList, repeating,
+ /*out*/lastFrameNumberRef);
+ if (!repeating) {
+ Log.v(TAG, "last frame number " + lastFrameNumberRef.getNumber());
+ }
} catch (CameraRuntimeException e) {
throw e.asChecked();
} catch (RemoteException e) {
@@ -290,12 +323,29 @@
return -1;
}
if (listener != null) {
- mCaptureListenerMap.put(requestId, new CaptureListenerHolder(listener, request,
- handler, repeating));
+ mCaptureListenerMap.put(requestId, new CaptureListenerHolder(listener,
+ requestList, handler, repeating));
}
+ long lastFrameNumber = lastFrameNumberRef.getNumber();
+ /**
+ * If it's the first repeating request, then returned lastFrameNumber can be
+ * negative. Otherwise, it should always be non-negative.
+ */
+ if (((lastFrameNumber < 0) && (requestId > 0))
+ || ((lastFrameNumber < 0) && (!repeating))) {
+ throw new AssertionError(String.format("returned bad frame number %d",
+ lastFrameNumber));
+ }
if (repeating) {
+ if (mRepeatingRequestId != REQUEST_ID_NONE) {
+ mFrameNumberRequestPairs.add(
+ new SimpleEntry<Long, Integer>(lastFrameNumber, mRepeatingRequestId));
+ }
mRepeatingRequestId = requestId;
+ } else {
+ mFrameNumberRequestPairs.add(
+ new SimpleEntry<Long, Integer>(lastFrameNumber, requestId));
}
if (mIdle) {
@@ -310,18 +360,20 @@
@Override
public int setRepeatingRequest(CaptureRequest request, CaptureListener listener,
Handler handler) throws CameraAccessException {
- return submitCaptureRequest(request, listener, handler, /*streaming*/true);
+ List<CaptureRequest> requestList = new ArrayList<CaptureRequest>();
+ requestList.add(request);
+ return submitCaptureRequest(requestList, listener, handler, /*streaming*/true);
}
@Override
public int setRepeatingBurst(List<CaptureRequest> requests, CaptureListener listener,
Handler handler) throws CameraAccessException {
+ // TODO: remove this. Throw IAE if the request is null or empty. Need to update API doc.
if (requests.isEmpty()) {
Log.w(TAG, "Set Repeating burst request list is empty, do nothing!");
return -1;
}
- // TODO
- throw new UnsupportedOperationException("Burst capture implemented yet");
+ return submitCaptureRequest(requests, listener, handler, /*streaming*/true);
}
@Override
@@ -340,7 +392,15 @@
}
try {
- mRemoteDevice.cancelRequest(requestId);
+ LongParcelable lastFrameNumberRef = new LongParcelable();
+ mRemoteDevice.cancelRequest(requestId, /*out*/lastFrameNumberRef);
+ long lastFrameNumber = lastFrameNumberRef.getNumber();
+ if ((lastFrameNumber < 0) && (requestId > 0)) {
+ throw new AssertionError(String.format("returned bad frame number %d",
+ lastFrameNumber));
+ }
+ mFrameNumberRequestPairs.add(
+ new SimpleEntry<Long, Integer>(lastFrameNumber, requestId));
} catch (CameraRuntimeException e) {
throw e.asChecked();
} catch (RemoteException e) {
@@ -379,7 +439,17 @@
mDeviceHandler.post(mCallOnBusy);
try {
- mRemoteDevice.flush();
+ LongParcelable lastFrameNumberRef = new LongParcelable();
+ mRemoteDevice.flush(/*out*/lastFrameNumberRef);
+ if (mRepeatingRequestId != REQUEST_ID_NONE) {
+ long lastFrameNumber = lastFrameNumberRef.getNumber();
+ if (lastFrameNumber < 0) {
+ Log.e(TAG, String.format("returned bad frame number %d", lastFrameNumber));
+ }
+ mFrameNumberRequestPairs.add(
+ new SimpleEntry<Long, Integer>(lastFrameNumber, mRepeatingRequestId));
+ mRepeatingRequestId = REQUEST_ID_NONE;
+ }
} catch (CameraRuntimeException e) {
throw e.asChecked();
} catch (RemoteException e) {
@@ -425,18 +495,18 @@
private final boolean mRepeating;
private final CaptureListener mListener;
- private final CaptureRequest mRequest;
+ private final List<CaptureRequest> mRequestList;
private final Handler mHandler;
- CaptureListenerHolder(CaptureListener listener, CaptureRequest request, Handler handler,
- boolean repeating) {
+ CaptureListenerHolder(CaptureListener listener, List<CaptureRequest> requestList,
+ Handler handler, boolean repeating) {
if (listener == null || handler == null) {
throw new UnsupportedOperationException(
"Must have a valid handler and a valid listener");
}
mRepeating = repeating;
mHandler = handler;
- mRequest = request;
+ mRequestList = new ArrayList<CaptureRequest>(requestList);
mListener = listener;
}
@@ -448,8 +518,24 @@
return mListener;
}
+ public CaptureRequest getRequest(int subsequenceId) {
+ if (subsequenceId >= mRequestList.size()) {
+ throw new IllegalArgumentException(
+ String.format(
+ "Requested subsequenceId %d is larger than request list size %d.",
+ subsequenceId, mRequestList.size()));
+ } else {
+ if (subsequenceId < 0) {
+ throw new IllegalArgumentException(String.format(
+ "Requested subsequenceId %d is negative", subsequenceId));
+ } else {
+ return mRequestList.get(subsequenceId);
+ }
+ }
+ }
+
public CaptureRequest getRequest() {
- return mRequest;
+ return getRequest(0);
}
public Handler getHandler() {
@@ -458,6 +544,105 @@
}
+ /**
+ * This class tracks the last frame number for submitted requests.
+ */
+ public class FrameNumberTracker {
+
+ private long mCompletedFrameNumber = -1;
+ private final TreeSet<Long> mFutureErrorSet = new TreeSet<Long>();
+
+ private void update() {
+ Iterator<Long> iter = mFutureErrorSet.iterator();
+ while (iter.hasNext()) {
+ long errorFrameNumber = iter.next();
+ if (errorFrameNumber == mCompletedFrameNumber + 1) {
+ mCompletedFrameNumber++;
+ iter.remove();
+ } else {
+ break;
+ }
+ }
+ }
+
+ /**
+ * This function is called every time when a result or an error is received.
+ * @param frameNumber: the frame number corresponding to the result or error
+ * @param isError: true if it is an error, false if it is not an error
+ */
+ public void updateTracker(long frameNumber, boolean isError) {
+ if (isError) {
+ mFutureErrorSet.add(frameNumber);
+ } else {
+ /**
+ * HAL cannot send an OnResultReceived for frame N unless it knows for
+ * sure that all frames prior to N have either errored out or completed.
+ * So if the current frame is not an error, then all previous frames
+ * should have arrived. The following line checks whether this holds.
+ */
+ if (frameNumber != mCompletedFrameNumber + 1) {
+ throw new AssertionError(String.format(
+ "result frame number %d comes out of order",
+ frameNumber));
+ }
+ mCompletedFrameNumber++;
+ }
+ update();
+ }
+
+ public long getCompletedFrameNumber() {
+ return mCompletedFrameNumber;
+ }
+
+ }
+
+ private void checkAndFireSequenceComplete() {
+ long completedFrameNumber = mFrameNumberTracker.getCompletedFrameNumber();
+ Iterator<SimpleEntry<Long, Integer> > iter = mFrameNumberRequestPairs.iterator();
+ while (iter.hasNext()) {
+ final SimpleEntry<Long, Integer> frameNumberRequestPair = iter.next();
+ if (frameNumberRequestPair.getKey() <= completedFrameNumber) {
+
+ // remove request from mCaptureListenerMap
+ final int requestId = frameNumberRequestPair.getValue();
+ final CaptureListenerHolder holder;
+ synchronized (mLock) {
+ int index = CameraDevice.this.mCaptureListenerMap.indexOfKey(requestId);
+ holder = (index >= 0) ? CameraDevice.this.mCaptureListenerMap.valueAt(index)
+ : null;
+ if (holder != null) {
+ CameraDevice.this.mCaptureListenerMap.removeAt(index);
+ }
+ }
+ iter.remove();
+
+ // Call onCaptureSequenceCompleted
+ if (holder != null) {
+ Runnable resultDispatch = new Runnable() {
+ @Override
+ public void run() {
+ if (!CameraDevice.this.isClosed()){
+ if (DEBUG) {
+ Log.d(TAG, String.format(
+ "fire sequence complete for request %d",
+ requestId));
+ }
+
+ holder.getListener().onCaptureSequenceCompleted(
+ CameraDevice.this,
+ requestId,
+ // TODO: this is problematic, crop long to int
+ frameNumberRequestPair.getKey().intValue());
+ }
+ }
+ };
+ holder.getHandler().post(resultDispatch);
+ }
+
+ }
+ }
+ }
+
public class CameraDeviceCallbacks extends ICameraDeviceCallbacks.Stub {
//
@@ -492,7 +677,7 @@
}
@Override
- public void onCameraError(final int errorCode) {
+ public void onCameraError(final int errorCode, CaptureResultExtras resultExtras) {
Runnable r = null;
if (isClosed()) return;
@@ -507,6 +692,7 @@
case ERROR_CAMERA_DEVICE:
case ERROR_CAMERA_SERVICE:
r = new Runnable() {
+ @Override
public void run() {
if (!CameraDevice.this.isClosed()) {
mDeviceListener.onError(CameraDevice.this, errorCode);
@@ -517,6 +703,11 @@
}
CameraDevice.this.mDeviceHandler.post(r);
}
+
+ // Fire onCaptureSequenceCompleted
+ mFrameNumberTracker.updateTracker(resultExtras.getFrameNumber(), /*error*/true);
+ checkAndFireSequenceComplete();
+
}
@Override
@@ -535,7 +726,8 @@
}
@Override
- public void onCaptureStarted(int requestId, final long timestamp) {
+ public void onCaptureStarted(final CaptureResultExtras resultExtras, final long timestamp) {
+ int requestId = resultExtras.getRequestId();
if (DEBUG) {
Log.d(TAG, "Capture started for id " + requestId);
}
@@ -555,11 +747,12 @@
// Dispatch capture start notice
holder.getHandler().post(
new Runnable() {
+ @Override
public void run() {
if (!CameraDevice.this.isClosed()) {
holder.getListener().onCaptureStarted(
CameraDevice.this,
- holder.getRequest(),
+ holder.getRequest(resultExtras.getSubsequenceId()),
timestamp);
}
}
@@ -567,48 +760,18 @@
}
@Override
- public void onResultReceived(int requestId, CameraMetadataNative result)
- throws RemoteException {
+ public void onResultReceived(CameraMetadataNative result,
+ CaptureResultExtras resultExtras) throws RemoteException {
+ int requestId = resultExtras.getRequestId();
if (DEBUG) {
Log.d(TAG, "Received result for id " + requestId);
}
- final CaptureListenerHolder holder;
+ final CaptureListenerHolder holder =
+ CameraDevice.this.mCaptureListenerMap.get(requestId);
Boolean quirkPartial = result.get(CaptureResult.QUIRKS_PARTIAL_RESULT);
boolean quirkIsPartialResult = (quirkPartial != null && quirkPartial);
- synchronized (mLock) {
- // TODO: move this whole map into this class to make it more testable,
- // exposing the methods necessary like subscribeToRequest, unsubscribe..
- // TODO: make class static class
-
- holder = CameraDevice.this.mCaptureListenerMap.get(requestId);
-
- // Clean up listener once we no longer expect to see it.
- if (holder != null && !holder.isRepeating() && !quirkIsPartialResult) {
- CameraDevice.this.mCaptureListenerMap.remove(requestId);
- }
-
- // TODO: add 'capture sequence completed' callback to the
- // service, and clean up repeating requests there instead.
-
- // If we received a result for a repeating request and have
- // prior repeating requests queued for deletion, remove those
- // requests from mCaptureListenerMap.
- if (holder != null && holder.isRepeating() && !quirkIsPartialResult
- && mRepeatingRequestIdDeletedList.size() > 0) {
- Iterator<Integer> iter = mRepeatingRequestIdDeletedList.iterator();
- while (iter.hasNext()) {
- int deletedRequestId = iter.next();
- if (deletedRequestId < requestId) {
- CameraDevice.this.mCaptureListenerMap.remove(deletedRequestId);
- iter.remove();
- }
- }
- }
-
- }
-
// Check if we have a listener for this
if (holder == null) {
return;
@@ -616,7 +779,7 @@
if (isClosed()) return;
- final CaptureRequest request = holder.getRequest();
+ final CaptureRequest request = holder.getRequest(resultExtras.getSubsequenceId());
final CaptureResult resultAsCapture = new CaptureResult(result, request, requestId);
Runnable resultDispatch = null;
@@ -651,6 +814,12 @@
}
holder.getHandler().post(resultDispatch);
+
+ // Fire onCaptureSequenceCompleted
+ if (!quirkIsPartialResult) {
+ mFrameNumberTracker.updateTracker(resultExtras.getFrameNumber(), /*error*/false);
+ checkAndFireSequenceComplete();
+ }
}
}
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index c8051aa..7f1a2e4 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -74,7 +74,14 @@
/** A hardware serial number, if available. Alphanumeric only, case-insensitive. */
public static final String SERIAL = getString("ro.serialno");
-
+
+ /**
+ * A list of ABIs (in priority) order supported by this device.
+ *
+ * @hide
+ */
+ public static final String[] SUPPORTED_ABIS = getString("ro.product.cpu.abilist").split(",");
+
/** Various version strings. */
public static class VERSION {
/**
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 79ff49c..c947eda 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -466,6 +466,7 @@
* @param debugFlags Additional flags.
* @param targetSdkVersion The target SDK version for the app.
* @param seInfo null-ok SELinux information for the new process.
+ * @param abi non-null the ABI this app should be started with.
* @param zygoteArgs Additional arguments to supply to the zygote process.
*
* @return An object that describes the result of the attempt to start the process.
@@ -479,12 +480,12 @@
int debugFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
+ String abi,
String[] zygoteArgs) {
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, mountExternal, targetSdkVersion, seInfo,
- null, /* zygoteAbi TODO: Replace this with the real ABI */
- zygoteArgs);
+ abi, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG,
"Starting VM process through Zygote failed");
@@ -702,13 +703,6 @@
primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET, getNumTries(primaryZygoteState));
}
- // TODO: Revert this temporary change. This is required to test
- // and submit this change ahead of the package manager changes
- // that supply this abi.
- if (abi == null) {
- return primaryZygoteState;
- }
-
if (primaryZygoteState.matches(abi)) {
return primaryZygoteState;
}
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java
index 2ef5b66..939cda9 100644
--- a/core/java/android/os/storage/IMountService.java
+++ b/core/java/android/os/storage/IMountService.java
@@ -625,12 +625,13 @@
return _result;
}
- public int encryptStorage(String password) throws RemoteException {
+ public int encryptStorage(int type, String password) throws RemoteException {
Parcel _data = Parcel.obtain();
Parcel _reply = Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeInt(type);
_data.writeString(password);
mRemote.transact(Stub.TRANSACTION_encryptStorage, _data, _reply, 0);
_reply.readException();
@@ -1210,8 +1211,9 @@
}
case TRANSACTION_encryptStorage: {
data.enforceInterface(DESCRIPTOR);
+ int type = data.readInt();
String password = data.readString();
- int result = encryptStorage(password);
+ int result = encryptStorage(type, password);
reply.writeNoException();
reply.writeInt(result);
return true;
@@ -1495,7 +1497,7 @@
/**
* Encrypts storage.
*/
- public int encryptStorage(String password) throws RemoteException;
+ public int encryptStorage(int type, String password) throws RemoteException;
/**
* Changes the encryption password.
diff --git a/core/java/android/view/AnimationRenderStats.aidl b/core/java/android/view/AnimationRenderStats.aidl
new file mode 100644
index 0000000..4599708
--- /dev/null
+++ b/core/java/android/view/AnimationRenderStats.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+parcelable AnimationRenderStats;
diff --git a/core/java/android/view/FrameStats.java b/core/java/android/view/FrameStats.java
new file mode 100644
index 0000000..541b336
--- /dev/null
+++ b/core/java/android/view/FrameStats.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * This is the base class for frame statistics.
+ */
+public abstract class FrameStats {
+ /**
+ * Undefined time.
+ */
+ public static final long UNDEFINED_TIME_NANO = -1;
+
+ protected long mRefreshPeriodNano;
+ protected long[] mFramesPresentedTimeNano;
+
+ /**
+ * Gets the refresh period of the display hosting the window(s) for
+ * which these statistics apply.
+ *
+ * @return The refresh period in nanoseconds.
+ */
+ public final long getRefreshPeriodNano() {
+ return mRefreshPeriodNano;
+ }
+
+ /**
+ * Gets the number of frames for which there is data.
+ *
+ * @return The number of frames.
+ */
+ public final int getFrameCount() {
+ return mFramesPresentedTimeNano != null
+ ? mFramesPresentedTimeNano.length : 0;
+ }
+
+ /**
+ * Gets the start time of the interval for which these statistics
+ * apply. The start interval is the time when the first frame was
+ * presented.
+ *
+ * @return The start time in nanoseconds or {@link #UNDEFINED_TIME_NANO}
+ * if there is no frame data.
+ */
+ public final long getStartTimeNano() {
+ if (getFrameCount() <= 0) {
+ return UNDEFINED_TIME_NANO;
+ }
+ return mFramesPresentedTimeNano[0];
+ }
+
+ /**
+ * Gets the end time of the interval for which these statistics
+ * apply. The end interval is the time when the last frame was
+ * presented.
+ *
+ * @return The end time in nanoseconds or {@link #UNDEFINED_TIME_NANO}
+ * if there is no frame data.
+ */
+ public final long getEndTimeNano() {
+ if (getFrameCount() <= 0) {
+ return UNDEFINED_TIME_NANO;
+ }
+ return mFramesPresentedTimeNano[mFramesPresentedTimeNano.length - 1];
+ }
+
+ /**
+ * Get the time a frame at a given index was presented.
+ *
+ * @param index The frame index.
+ * @return The presented time in nanoseconds or {@link #UNDEFINED_TIME_NANO}
+ * if the frame is not presented yet.
+ */
+ public final long getFramePresentedTimeNano(int index) {
+ if (mFramesPresentedTimeNano == null) {
+ throw new IndexOutOfBoundsException();
+ }
+ return mFramesPresentedTimeNano[index];
+ }
+}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 8f542bb..80d5bf2 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -37,6 +37,7 @@
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.IInputFilter;
+import android.view.WindowContentFrameStats;
/**
* System private interface to the window manager.
@@ -233,4 +234,20 @@
* Device is in safe mode.
*/
boolean isSafeModeEnabled();
+
+ /**
+ * Clears the frame statistics for a given window.
+ *
+ * @param token The window token.
+ * @return Whether the frame statistics were cleared.
+ */
+ boolean clearWindowContentFrameStats(IBinder token);
+
+ /**
+ * Gets the content frame statistics for a given window.
+ *
+ * @param token The window token.
+ * @return The frame statistics or null if the window does not exist.
+ */
+ WindowContentFrameStats getWindowContentFrameStats(IBinder token);
}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 5a8d2c8..2d55a01 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -20,7 +20,6 @@
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.graphics.Region;
-import android.view.Surface;
import android.os.IBinder;
import android.util.Log;
import android.view.Surface.OutOfResourcesException;
@@ -59,6 +58,11 @@
private static native void nativeSetWindowCrop(long nativeObject, int l, int t, int r, int b);
private static native void nativeSetLayerStack(long nativeObject, int layerStack);
+ private static native boolean nativeClearContentFrameStats(long nativeObject);
+ private static native boolean nativeGetContentFrameStats(long nativeObject, WindowContentFrameStats outStats);
+ private static native boolean nativeClearAnimationFrameStats();
+ private static native boolean nativeGetAnimationFrameStats(WindowAnimationFrameStats outStats);
+
private static native IBinder nativeGetBuiltInDisplay(int physicalDisplayId);
private static native IBinder nativeCreateDisplay(String name, boolean secure);
private static native void nativeDestroyDisplay(IBinder displayToken);
@@ -357,6 +361,24 @@
nativeSetTransparentRegionHint(mNativeObject, region);
}
+ public boolean clearContentFrameStats() {
+ checkNotReleased();
+ return nativeClearContentFrameStats(mNativeObject);
+ }
+
+ public boolean getContentFrameStats(WindowContentFrameStats outStats) {
+ checkNotReleased();
+ return nativeGetContentFrameStats(mNativeObject, outStats);
+ }
+
+ public static boolean clearAnimationFrameStats() {
+ return nativeClearAnimationFrameStats();
+ }
+
+ public static boolean getAnimationFrameStats(WindowAnimationFrameStats outStats) {
+ return nativeGetAnimationFrameStats(outStats);
+ }
+
/**
* Sets an alpha value for the entire Surface. This value is combined with the
* per-pixel alpha. It may be used with opaque Surfaces.
@@ -542,7 +564,6 @@
return nativeGetBuiltInDisplay(builtInDisplayId);
}
-
/**
* Copy the current screen contents into the provided {@link Surface}
*
@@ -592,7 +613,6 @@
screenshot(display, consumer, 0, 0, 0, 0, true, false);
}
-
/**
* Copy the current screen contents into a bitmap and return it.
*
@@ -626,8 +646,8 @@
}
/**
- * Like {@link SurfaceControl#screenshot(int, int, int, int)} but includes all
- * Surfaces in the screenshot.
+ * Like {@link SurfaceControl#screenshot(int, int, int, int, boolean)} but
+ * includes all Surfaces in the screenshot.
*
* @param width The desired width of the returned bitmap; the raw
* screen will be scaled down to this size.
diff --git a/core/java/android/view/WindowAnimationFrameStats.aidl b/core/java/android/view/WindowAnimationFrameStats.aidl
new file mode 100644
index 0000000..77f544b
--- /dev/null
+++ b/core/java/android/view/WindowAnimationFrameStats.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+parcelable WindowAnimationFrameStats;
diff --git a/core/java/android/view/WindowAnimationFrameStats.java b/core/java/android/view/WindowAnimationFrameStats.java
new file mode 100644
index 0000000..c60b96c
--- /dev/null
+++ b/core/java/android/view/WindowAnimationFrameStats.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * This class contains window animation frame statistics. For example, a window
+ * animation is usually performed when the application is transitioning from one
+ * activity to another. The frame statistics are a snapshot for the time interval
+ * from {@link #getStartTimeNano()} to {@link #getEndTimeNano()}.
+ * <p>
+ * The key idea is that in order to provide a smooth user experience the system should
+ * run window animations at a specific time interval obtained by calling {@link
+ * #getRefreshPeriodNano()}. If the system does not render a frame every refresh
+ * period the user will see irregular window transitions. The time when the frame was
+ * actually presented on the display by calling {@link #getFramePresentedTimeNano(int)}.
+ */
+public final class WindowAnimationFrameStats extends FrameStats implements Parcelable {
+ /**
+ * @hide
+ */
+ public WindowAnimationFrameStats() {
+ /* do nothing */
+ }
+
+ /**
+ * Initializes this isntance.
+ *
+ * @param refreshPeriodNano The display refresh period.
+ * @param framesPresentedTimeNano The presented frame times.
+ *
+ * @hide
+ */
+ public void init(long refreshPeriodNano, long[] framesPresentedTimeNano) {
+ mRefreshPeriodNano = refreshPeriodNano;
+ mFramesPresentedTimeNano = framesPresentedTimeNano;
+ }
+
+ private WindowAnimationFrameStats(Parcel parcel) {
+ mRefreshPeriodNano = parcel.readLong();
+ mFramesPresentedTimeNano = parcel.createLongArray();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeLong(mRefreshPeriodNano);
+ parcel.writeLongArray(mFramesPresentedTimeNano);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("WindowAnimationFrameStats[");
+ builder.append("frameCount:" + getFrameCount());
+ builder.append(", fromTimeNano:" + getStartTimeNano());
+ builder.append(", toTimeNano:" + getEndTimeNano());
+ builder.append(']');
+ return builder.toString();
+ }
+
+ public static final Creator<WindowAnimationFrameStats> CREATOR =
+ new Creator<WindowAnimationFrameStats>() {
+ @Override
+ public WindowAnimationFrameStats createFromParcel(Parcel parcel) {
+ return new WindowAnimationFrameStats(parcel);
+ }
+
+ @Override
+ public WindowAnimationFrameStats[] newArray(int size) {
+ return new WindowAnimationFrameStats[size];
+ }
+ };
+}
diff --git a/core/java/android/view/WindowContentFrameStats.aidl b/core/java/android/view/WindowContentFrameStats.aidl
new file mode 100644
index 0000000..aa9c2d6
--- /dev/null
+++ b/core/java/android/view/WindowContentFrameStats.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+parcelable WindowContentFrameStats;
diff --git a/core/java/android/view/WindowContentFrameStats.java b/core/java/android/view/WindowContentFrameStats.java
new file mode 100644
index 0000000..c6da2fb
--- /dev/null
+++ b/core/java/android/view/WindowContentFrameStats.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * This class contains window content frame statistics. For example, a window content
+ * is rendred in frames when a view is scrolled. The frame statistics are a snapshot
+ * for the time interval from {@link #getStartTimeNano()} to {@link #getEndTimeNano()}.
+ * <p>
+ * The key idea is that in order to provide a smooth user experience an application
+ * has to draw a frame at a specific time interval obtained by calling {@link
+ * #getRefreshPeriodNano()}. If the application does not render a frame every refresh
+ * period the user will see irregular UI transitions.
+ * </p>
+ * <p>
+ * An application posts a frame for presentation by synchronously rendering its contents
+ * in a buffer which is then posted or posting a buffer to which the application is
+ * asychronously rendering the content via GL. After the frame is posted and rendered
+ * (potentially asynchronosly) it is presented to the user. The time a frame was posted
+ * can be obtained via {@link #getFramePostedTimeNano(int)}, the time a frame content
+ * was rendered and ready for dsiplay (GL case) via {@link #getFrameReadyTimeNano(int)},
+ * and the time a frame was presented on the screen via {@link #getFramePresentedTimeNano(int)}.
+ * </p>
+ */
+public final class WindowContentFrameStats extends FrameStats implements Parcelable {
+ private long[] mFramesPostedTimeNano;
+ private long[] mFramesReadyTimeNano;
+
+ /**
+ * @hide
+ */
+ public WindowContentFrameStats() {
+ /* do nothing */
+ }
+
+ /**
+ * Initializes this isntance.
+ *
+ * @param refreshPeriodNano The display refresh period.
+ * @param framesPostedTimeNano The times in milliseconds for when the frame contents were posted.
+ * @param framesPresentedTimeNano The times in milliseconds for when the frame contents were presented.
+ * @param framesReadyTimeNano The times in milliseconds for when the frame contents were ready to be presented.
+ *
+ * @hide
+ */
+ public void init(long refreshPeriodNano, long[] framesPostedTimeNano,
+ long[] framesPresentedTimeNano, long[] framesReadyTimeNano) {
+ mRefreshPeriodNano = refreshPeriodNano;
+ mFramesPostedTimeNano = framesPostedTimeNano;
+ mFramesPresentedTimeNano = framesPresentedTimeNano;
+ mFramesReadyTimeNano = framesReadyTimeNano;
+ }
+
+ private WindowContentFrameStats(Parcel parcel) {
+ mRefreshPeriodNano = parcel.readLong();
+ mFramesPostedTimeNano = parcel.createLongArray();
+ mFramesPresentedTimeNano = parcel.createLongArray();
+ mFramesReadyTimeNano = parcel.createLongArray();
+ }
+
+ /**
+ * Get the time a frame at a given index was posted by the producer (e.g. the application).
+ * It is either explicitly set or defaulted to the time when the render buffer was posted.
+ * <p>
+ * <strong>Note:</strong> A frame can be posted and still it contents being rendered
+ * asynchronously in GL. To get the time the frame content was completely rendered and
+ * ready to display call {@link #getFrameReadyTimeNano(int)}.
+ * </p>
+ *
+ * @param index The frame index.
+ * @return The posted time in nanoseconds.
+ */
+ public long getFramePostedTimeNano(int index) {
+ if (mFramesPostedTimeNano == null) {
+ throw new IndexOutOfBoundsException();
+ }
+ return mFramesPostedTimeNano[index];
+ }
+
+ /**
+ * Get the time a frame at a given index was ready for presentation.
+ * <p>
+ * <strong>Note:</strong> A frame can be posted and still it contents being rendered
+ * asynchronously in GL. In such a case this is the time when the frame contents were
+ * completely rendered.
+ * </p>
+ *
+ * @param index The frame index.
+ * @return The ready time in nanoseconds or {@link #UNDEFINED_TIME_NANO}
+ * if the frame is not ready yet.
+ */
+ public long getFrameReadyTimeNano(int index) {
+ if (mFramesReadyTimeNano == null) {
+ throw new IndexOutOfBoundsException();
+ }
+ return mFramesReadyTimeNano[index];
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeLong(mRefreshPeriodNano);
+ parcel.writeLongArray(mFramesPostedTimeNano);
+ parcel.writeLongArray(mFramesPresentedTimeNano);
+ parcel.writeLongArray(mFramesReadyTimeNano);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("WindowContentFrameStats[");
+ builder.append("frameCount:" + getFrameCount());
+ builder.append(", fromTimeNano:" + getStartTimeNano());
+ builder.append(", toTimeNano:" + getEndTimeNano());
+ builder.append(']');
+ return builder.toString();
+ }
+
+ public static final Parcelable.Creator<WindowContentFrameStats> CREATOR =
+ new Creator<WindowContentFrameStats>() {
+ @Override
+ public WindowContentFrameStats createFromParcel(Parcel parcel) {
+ return new WindowContentFrameStats(parcel);
+ }
+
+ @Override
+ public WindowContentFrameStats[] newArray(int size) {
+ return new WindowContentFrameStats[size];
+ }
+ };
+}
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index fe3e5c6..b6570cc 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -57,4 +57,6 @@
void temporaryEnableAccessibilityStateUntilKeyguardRemoved(in ComponentName service,
boolean touchExplorationEnabled);
+
+ IBinder getWindowToken(int windowId);
}
diff --git a/core/java/com/android/internal/content/NativeLibraryHelper.java b/core/java/com/android/internal/content/NativeLibraryHelper.java
index 6d65782..ba419f9 100644
--- a/core/java/com/android/internal/content/NativeLibraryHelper.java
+++ b/core/java/com/android/internal/content/NativeLibraryHelper.java
@@ -16,7 +16,7 @@
package com.android.internal.content;
-import android.os.Build;
+import android.content.pm.PackageManager;
import android.util.Slog;
import java.io.File;
@@ -31,38 +31,76 @@
private static final boolean DEBUG_NATIVE = false;
- private static native long nativeSumNativeBinaries(String file, String cpuAbi, String cpuAbi2);
-
/**
- * Sums the size of native binaries in an APK.
+ * A handle to an opened APK. Used as input to the various NativeLibraryHelper
+ * methods. Allows us to scan and parse the APK exactly once instead of doing
+ * it multiple times.
*
- * @param apkFile APK file to scan for native libraries
- * @return size of all native binary files in bytes
+ * @hide
*/
- public static long sumNativeBinariesLI(File apkFile) {
- final String cpuAbi = Build.CPU_ABI;
- final String cpuAbi2 = Build.CPU_ABI2;
- return nativeSumNativeBinaries(apkFile.getPath(), cpuAbi, cpuAbi2);
+ public static class ApkHandle {
+ final String apkPath;
+ final long apkHandle;
+
+ public ApkHandle(String path) {
+ apkPath = path;
+ apkHandle = nativeOpenApk(apkPath);
+ }
+
+ public ApkHandle(File apkFile) {
+ apkPath = apkFile.getPath();
+ apkHandle = nativeOpenApk(apkPath);
+ }
+
+ public void close() {
+ nativeClose(apkHandle);
+ }
}
- private native static int nativeCopyNativeBinaries(String filePath, String sharedLibraryPath,
- String cpuAbi, String cpuAbi2);
+
+ private static native long nativeOpenApk(String path);
+ private static native void nativeClose(long handle);
+
+ private static native long nativeSumNativeBinaries(long handle, String cpuAbi);
+
+ /**
+ * Sums the size of native binaries in an APK for a given ABI.
+ *
+ * @return size of all native binary files in bytes
+ */
+ public static long sumNativeBinariesLI(ApkHandle handle, String abi) {
+ return nativeSumNativeBinaries(handle.apkHandle, abi);
+ }
+
+ private native static int nativeCopyNativeBinaries(long handle,
+ String sharedLibraryPath, String abiToCopy);
/**
* Copies native binaries to a shared library directory.
*
- * @param apkFile APK file to scan for native libraries
+ * @param handle APK file to scan for native libraries
* @param sharedLibraryDir directory for libraries to be copied to
* @return {@link PackageManager#INSTALL_SUCCEEDED} if successful or another
* error code from that class if not
*/
- public static int copyNativeBinariesIfNeededLI(File apkFile, File sharedLibraryDir) {
- final String cpuAbi = Build.CPU_ABI;
- final String cpuAbi2 = Build.CPU_ABI2;
- return nativeCopyNativeBinaries(apkFile.getPath(), sharedLibraryDir.getPath(), cpuAbi,
- cpuAbi2);
+ public static int copyNativeBinariesIfNeededLI(ApkHandle handle, File sharedLibraryDir,
+ String abi) {
+ return nativeCopyNativeBinaries(handle.apkHandle, sharedLibraryDir.getPath(), abi);
}
+ /**
+ * Checks if a given APK contains native code for any of the provided
+ * {@code supportedAbis}. Returns an index into {@code supportedAbis} if a matching
+ * ABI is found, {@link PackageManager#NO_NATIVE_LIBRARIES} if the
+ * APK doesn't contain any native code, and
+ * {@link PackageManager#INSTALL_FAILED_NO_MATCHING_ABIS} if none of the ABIs match.
+ */
+ public static int findSupportedAbi(ApkHandle handle, String[] supportedAbis) {
+ return nativeFindSupportedAbi(handle.apkHandle, supportedAbis);
+ }
+
+ private native static int nativeFindSupportedAbi(long handle, String[] supportedAbis);
+
// Convenience method to call removeNativeBinariesFromDirLI(File)
public static boolean removeNativeBinariesLI(String nativeLibraryPath) {
return removeNativeBinariesFromDirLI(new File(nativeLibraryPath));
diff --git a/core/java/com/android/internal/notification/PeopleNotificationScorer.java b/core/java/com/android/internal/notification/PeopleNotificationScorer.java
new file mode 100644
index 0000000..efb5f63
--- /dev/null
+++ b/core/java/com/android/internal/notification/PeopleNotificationScorer.java
@@ -0,0 +1,227 @@
+/*
+* Copyright (C) 2014 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.android.internal.notification;
+
+import android.app.Notification;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.Contacts;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.LruCache;
+import android.util.Slog;
+
+/**
+ * This {@link NotificationScorer} attempts to validate people references.
+ * Also elevates the priority of real people.
+ */
+public class PeopleNotificationScorer implements NotificationScorer {
+ private static final String TAG = "PeopleNotificationScorer";
+ private static final boolean DBG = false;
+
+ private static final boolean ENABLE_PEOPLE_SCORER = true;
+ private static final String SETTING_ENABLE_PEOPLE_SCORER = "people_scorer_enabled";
+ private static final String[] LOOKUP_PROJECTION = { Contacts._ID };
+ private static final int MAX_PEOPLE = 10;
+ private static final int PEOPLE_CACHE_SIZE = 200;
+ // see NotificationManagerService
+ private static final int NOTIFICATION_PRIORITY_MULTIPLIER = 10;
+
+ protected boolean mEnabled;
+ private Context mContext;
+
+ // maps raw person handle to resolved person object
+ private LruCache<String, LookupResult> mPeopleCache;
+
+ private float findMaxContactScore(Bundle extras) {
+ if (extras == null) {
+ return 0f;
+ }
+
+ final String[] people = extras.getStringArray(Notification.EXTRA_PEOPLE);
+ if (people == null || people.length == 0) {
+ return 0f;
+ }
+
+ float rank = 0f;
+ for (int personIdx = 0; personIdx < people.length && personIdx < MAX_PEOPLE; personIdx++) {
+ final String handle = people[personIdx];
+ if (TextUtils.isEmpty(handle)) continue;
+
+ LookupResult lookupResult = mPeopleCache.get(handle);
+ if (lookupResult == null || lookupResult.isExpired()) {
+ final Uri uri = Uri.parse(handle);
+ if ("tel".equals(uri.getScheme())) {
+ if (DBG) Slog.w(TAG, "checking telephone URI: " + handle);
+ lookupResult = lookupPhoneContact(handle, uri.getSchemeSpecificPart());
+ } else if (handle.startsWith(Contacts.CONTENT_LOOKUP_URI.toString())) {
+ if (DBG) Slog.w(TAG, "checking lookup URI: " + handle);
+ lookupResult = resolveContactsUri(handle, uri);
+ } else {
+ if (DBG) Slog.w(TAG, "unsupported URI " + handle);
+ }
+ } else {
+ if (DBG) Slog.w(TAG, "using cached lookupResult: " + lookupResult.mId);
+ }
+ if (lookupResult != null) {
+ rank = Math.max(rank, lookupResult.getRank());
+ }
+ }
+ return rank;
+ }
+
+ private LookupResult lookupPhoneContact(final String handle, final String number) {
+ LookupResult lookupResult = null;
+ Cursor c = null;
+ try {
+ Uri numberUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
+ Uri.encode(number));
+ c = mContext.getContentResolver().query(numberUri, LOOKUP_PROJECTION, null, null, null);
+ if (c != null && c.getCount() > 0) {
+ c.moveToFirst();
+ final int idIdx = c.getColumnIndex(Contacts._ID);
+ final int id = c.getInt(idIdx);
+ if (DBG) Slog.w(TAG, "is valid: " + id);
+ lookupResult = new LookupResult(id);
+ }
+ } catch(Throwable t) {
+ Slog.w(TAG, "Problem getting content resolver or performing contacts query.", t);
+ } finally {
+ if (c != null) {
+ c.close();
+ }
+ }
+ if (lookupResult == null) {
+ lookupResult = new LookupResult(LookupResult.INVALID_ID);
+ }
+ mPeopleCache.put(handle, lookupResult);
+ return lookupResult;
+ }
+
+ private LookupResult resolveContactsUri(String handle, final Uri personUri) {
+ LookupResult lookupResult = null;
+ Cursor c = null;
+ try {
+ c = mContext.getContentResolver().query(personUri, LOOKUP_PROJECTION, null, null, null);
+ if (c != null && c.getCount() > 0) {
+ c.moveToFirst();
+ final int idIdx = c.getColumnIndex(Contacts._ID);
+ final int id = c.getInt(idIdx);
+ if (DBG) Slog.w(TAG, "is valid: " + id);
+ lookupResult = new LookupResult(id);
+ }
+ } catch(Throwable t) {
+ Slog.w(TAG, "Problem getting content resolver or performing contacts query.", t);
+ } finally {
+ if (c != null) {
+ c.close();
+ }
+ }
+ if (lookupResult == null) {
+ lookupResult = new LookupResult(LookupResult.INVALID_ID);
+ }
+ mPeopleCache.put(handle, lookupResult);
+ return lookupResult;
+ }
+
+ private final static int clamp(int x, int low, int high) {
+ return (x < low) ? low : ((x > high) ? high : x);
+ }
+
+ // TODO: rework this function before shipping
+ private static int priorityBumpMap(int incomingScore) {
+ //assumption is that scale runs from [-2*pm, 2*pm]
+ int pm = NOTIFICATION_PRIORITY_MULTIPLIER;
+ int theScore = incomingScore;
+ // enforce input in range
+ theScore = clamp(theScore, -2 * pm, 2 * pm);
+ if (theScore != incomingScore) return incomingScore;
+ // map -20 -> -20 and -10 -> 5 (when pm = 10)
+ if (theScore <= -pm) {
+ theScore += 1.5 * (theScore + 2 * pm);
+ } else {
+ // map 0 -> 10, 10 -> 15, 20 -> 20;
+ theScore += 0.5 * (2 * pm - theScore);
+ }
+ if (DBG) Slog.v(TAG, "priorityBumpMap: score before: " + incomingScore
+ + ", score after " + theScore + ".");
+ return theScore;
+ }
+
+ @Override
+ public void initialize(Context context) {
+ if (DBG) Slog.v(TAG, "Initializing " + getClass().getSimpleName() + ".");
+ mContext = context;
+ mPeopleCache = new LruCache<String, LookupResult>(PEOPLE_CACHE_SIZE);
+ mEnabled = ENABLE_PEOPLE_SCORER && 1 == Settings.Global.getInt(
+ mContext.getContentResolver(), SETTING_ENABLE_PEOPLE_SCORER, 0);
+ }
+
+ @Override
+ public int getScore(Notification notification, int score) {
+ if (notification == null || !mEnabled) {
+ if (DBG) Slog.w(TAG, "empty notification? scorer disabled?");
+ return score;
+ }
+ float contactScore = findMaxContactScore(notification.extras);
+ if (contactScore > 0f) {
+ if (DBG) Slog.v(TAG, "Notification references a real contact. Promoted!");
+ score = priorityBumpMap(score);
+ } else {
+ if (DBG) Slog.v(TAG, "Notification lacks any valid contact reference. Not promoted!");
+ }
+ return score;
+ }
+
+ private static class LookupResult {
+ private static final long CONTACT_REFRESH_MILLIS = 60 * 60 * 1000; // 1hr
+ public static final int INVALID_ID = -1;
+
+ private final long mExpireMillis;
+ private int mId;
+
+ public LookupResult(int id) {
+ mId = id;
+ mExpireMillis = System.currentTimeMillis() + CONTACT_REFRESH_MILLIS;
+ }
+
+ public boolean isExpired() {
+ return mExpireMillis < System.currentTimeMillis();
+ }
+
+ public boolean isInvalid() {
+ return mId == INVALID_ID || isExpired();
+ }
+
+ public float getRank() {
+ if (isInvalid()) {
+ return 0f;
+ } else {
+ return 1f; // TODO: finer grained score
+ }
+ }
+
+ public LookupResult setId(int id) {
+ mId = id;
+ return this;
+ }
+ }
+}
+
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 159ffb2..8141a00 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -34,6 +34,7 @@
#include <gui/SurfaceComposerClient.h>
#include <ui/DisplayInfo.h>
+#include <ui/FrameStats.h>
#include <ui/Rect.h>
#include <ui/Region.h>
@@ -64,6 +65,16 @@
delete ((ScreenshotClient*) context);
}
+static struct {
+ nsecs_t UNDEFINED_TIME_NANO;
+ jmethodID init;
+} gWindowContentFrameStatsClassInfo;
+
+static struct {
+ nsecs_t UNDEFINED_TIME_NANO;
+ jmethodID init;
+} gWindowAnimationFrameStatsClassInfo;
+
// ----------------------------------------------------------------------------
static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
@@ -371,6 +382,151 @@
SurfaceComposerClient::unblankDisplay(token);
}
+static jboolean nativeClearContentFrameStats(JNIEnv* env, jclass clazz, jlong nativeObject) {
+ SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+ status_t err = ctrl->clearLayerFrameStats();
+
+ if (err < 0 && err != NO_INIT) {
+ doThrowIAE(env);
+ }
+
+ // The other end is not ready, just report we failed.
+ if (err == NO_INIT) {
+ return JNI_FALSE;
+ }
+
+ return JNI_TRUE;
+}
+
+static jboolean nativeGetContentFrameStats(JNIEnv* env, jclass clazz, jlong nativeObject,
+ jobject outStats) {
+ FrameStats stats;
+
+ SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+ status_t err = ctrl->getLayerFrameStats(&stats);
+ if (err < 0 && err != NO_INIT) {
+ doThrowIAE(env);
+ }
+
+ // The other end is not ready, fine just return empty stats.
+ if (err == NO_INIT) {
+ return JNI_FALSE;
+ }
+
+ jlong refreshPeriodNano = static_cast<jlong>(stats.refreshPeriodNano);
+ size_t frameCount = stats.desiredPresentTimesNano.size();
+
+ jlongArray postedTimesNanoDst = env->NewLongArray(frameCount);
+ if (postedTimesNanoDst == NULL) {
+ return JNI_FALSE;
+ }
+
+ jlongArray presentedTimesNanoDst = env->NewLongArray(frameCount);
+ if (presentedTimesNanoDst == NULL) {
+ return JNI_FALSE;
+ }
+
+ jlongArray readyTimesNanoDst = env->NewLongArray(frameCount);
+ if (readyTimesNanoDst == NULL) {
+ return JNI_FALSE;
+ }
+
+ nsecs_t postedTimesNanoSrc[frameCount];
+ nsecs_t presentedTimesNanoSrc[frameCount];
+ nsecs_t readyTimesNanoSrc[frameCount];
+
+ for (size_t i = 0; i < frameCount; i++) {
+ nsecs_t postedTimeNano = stats.desiredPresentTimesNano[i];
+ if (postedTimeNano == INT64_MAX) {
+ postedTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO;
+ }
+ postedTimesNanoSrc[i] = postedTimeNano;
+
+ nsecs_t presentedTimeNano = stats.actualPresentTimesNano[i];
+ if (presentedTimeNano == INT64_MAX) {
+ presentedTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO;
+ }
+ presentedTimesNanoSrc[i] = presentedTimeNano;
+
+ nsecs_t readyTimeNano = stats.frameReadyTimesNano[i];
+ if (readyTimeNano == INT64_MAX) {
+ readyTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO;
+ }
+ readyTimesNanoSrc[i] = readyTimeNano;
+ }
+
+ env->SetLongArrayRegion(postedTimesNanoDst, 0, frameCount, postedTimesNanoSrc);
+ env->SetLongArrayRegion(presentedTimesNanoDst, 0, frameCount, presentedTimesNanoSrc);
+ env->SetLongArrayRegion(readyTimesNanoDst, 0, frameCount, readyTimesNanoSrc);
+
+ env->CallVoidMethod(outStats, gWindowContentFrameStatsClassInfo.init, refreshPeriodNano,
+ postedTimesNanoDst, presentedTimesNanoDst, readyTimesNanoDst);
+
+ if (env->ExceptionCheck()) {
+ return JNI_FALSE;
+ }
+
+ return JNI_TRUE;
+}
+
+static jboolean nativeClearAnimationFrameStats(JNIEnv* env, jclass clazz) {
+ status_t err = SurfaceComposerClient::clearAnimationFrameStats();
+
+ if (err < 0 && err != NO_INIT) {
+ doThrowIAE(env);
+ }
+
+ // The other end is not ready, just report we failed.
+ if (err == NO_INIT) {
+ return JNI_FALSE;
+ }
+
+ return JNI_TRUE;
+}
+
+static jboolean nativeGetAnimationFrameStats(JNIEnv* env, jclass clazz, jobject outStats) {
+ FrameStats stats;
+
+ status_t err = SurfaceComposerClient::getAnimationFrameStats(&stats);
+ if (err < 0 && err != NO_INIT) {
+ doThrowIAE(env);
+ }
+
+ // The other end is not ready, fine just return empty stats.
+ if (err == NO_INIT) {
+ return JNI_FALSE;
+ }
+
+ jlong refreshPeriodNano = static_cast<jlong>(stats.refreshPeriodNano);
+ size_t frameCount = stats.desiredPresentTimesNano.size();
+
+ jlongArray presentedTimesNanoDst = env->NewLongArray(frameCount);
+ if (presentedTimesNanoDst == NULL) {
+ return JNI_FALSE;
+ }
+
+ nsecs_t presentedTimesNanoSrc[frameCount];
+
+ for (size_t i = 0; i < frameCount; i++) {
+ nsecs_t presentedTimeNano = stats.desiredPresentTimesNano[i];
+ if (presentedTimeNano == INT64_MAX) {
+ presentedTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO;
+ }
+ presentedTimesNanoSrc[i] = presentedTimeNano;
+ }
+
+ env->SetLongArrayRegion(presentedTimesNanoDst, 0, frameCount, presentedTimesNanoSrc);
+
+ env->CallVoidMethod(outStats, gWindowAnimationFrameStatsClassInfo.init, refreshPeriodNano,
+ presentedTimesNanoDst);
+
+ if (env->ExceptionCheck()) {
+ return JNI_FALSE;
+ }
+
+ return JNI_TRUE;
+}
+
// ----------------------------------------------------------------------------
static JNINativeMethod sSurfaceControlMethods[] = {
@@ -426,6 +582,14 @@
(void*)nativeBlankDisplay },
{"nativeUnblankDisplay", "(Landroid/os/IBinder;)V",
(void*)nativeUnblankDisplay },
+ {"nativeClearContentFrameStats", "(J)Z",
+ (void*)nativeClearContentFrameStats },
+ {"nativeGetContentFrameStats", "(JLandroid/view/WindowContentFrameStats;)Z",
+ (void*)nativeGetContentFrameStats },
+ {"nativeClearAnimationFrameStats", "()Z",
+ (void*)nativeClearAnimationFrameStats },
+ {"nativeGetAnimationFrameStats", "(Landroid/view/WindowAnimationFrameStats;)Z",
+ (void*)nativeGetAnimationFrameStats },
};
int register_android_view_SurfaceControl(JNIEnv* env)
@@ -441,6 +605,19 @@
gPhysicalDisplayInfoClassInfo.xDpi = env->GetFieldID(clazz, "xDpi", "F");
gPhysicalDisplayInfoClassInfo.yDpi = env->GetFieldID(clazz, "yDpi", "F");
gPhysicalDisplayInfoClassInfo.secure = env->GetFieldID(clazz, "secure", "Z");
+
+ jclass frameStatsClazz = env->FindClass("android/view/FrameStats");
+ jfieldID undefined_time_nano_field = env->GetStaticFieldID(frameStatsClazz, "UNDEFINED_TIME_NANO", "J");
+ nsecs_t undefined_time_nano = env->GetStaticLongField(frameStatsClazz, undefined_time_nano_field);
+
+ jclass contFrameStatsClazz = env->FindClass("android/view/WindowContentFrameStats");
+ gWindowContentFrameStatsClassInfo.init = env->GetMethodID(contFrameStatsClazz, "init", "(J[J[J[J)V");
+ gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO = undefined_time_nano;
+
+ jclass animFrameStatsClazz = env->FindClass("android/view/WindowAnimationFrameStats");
+ gWindowAnimationFrameStatsClassInfo.init = env->GetMethodID(animFrameStatsClazz, "init", "(J[J)V");
+ gWindowAnimationFrameStatsClassInfo.UNDEFINED_TIME_NANO = undefined_time_nano;
+
return err;
}
diff --git a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
index a860918..230658f 100644
--- a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
+++ b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
@@ -19,11 +19,12 @@
#include <android_runtime/AndroidRuntime.h>
-#include <utils/Log.h>
-#include <androidfw/ZipFileRO.h>
-#include <androidfw/ZipUtils.h>
#include <ScopedUtfChars.h>
#include <UniquePtr.h>
+#include <androidfw/ZipFileRO.h>
+#include <androidfw/ZipUtils.h>
+#include <utils/Log.h>
+#include <utils/Vector.h>
#include <zlib.h>
@@ -54,17 +55,19 @@
namespace android {
// These match PackageManager.java install codes
-typedef enum {
+enum install_status_t {
INSTALL_SUCCEEDED = 1,
INSTALL_FAILED_INVALID_APK = -2,
INSTALL_FAILED_INSUFFICIENT_STORAGE = -4,
INSTALL_FAILED_CONTAINER_ERROR = -18,
INSTALL_FAILED_INTERNAL_ERROR = -110,
-} install_status_t;
+ INSTALL_FAILED_NO_MATCHING_ABIS = -113,
+ NO_NATIVE_LIBRARIES = -114
+};
typedef install_status_t (*iterFunc)(JNIEnv*, void*, ZipFileRO*, ZipEntryRO, const char*);
-// Equivalent to isFilenameSafe
+// Equivalent to android.os.FileUtils.isFilenameSafe
static bool
isFilenameSafe(const char* filename)
{
@@ -268,126 +271,252 @@
return INSTALL_SUCCEEDED;
}
-static install_status_t
-iterateOverNativeFiles(JNIEnv *env, jstring javaFilePath, jstring javaCpuAbi, jstring javaCpuAbi2,
- iterFunc callFunc, void* callArg) {
- ScopedUtfChars filePath(env, javaFilePath);
- ScopedUtfChars cpuAbi(env, javaCpuAbi);
- ScopedUtfChars cpuAbi2(env, javaCpuAbi2);
-
- UniquePtr<ZipFileRO> zipFile(ZipFileRO::open(filePath.c_str()));
- if (zipFile.get() == NULL) {
- ALOGI("Couldn't open APK %s\n", filePath.c_str());
- return INSTALL_FAILED_INVALID_APK;
+/*
+ * An iterator over all shared libraries in a zip file. An entry is
+ * considered to be a shared library if all of the conditions below are
+ * satisfied :
+ *
+ * - The entry is under the lib/ directory.
+ * - The entry name ends with ".so" and the entry name starts with "lib",
+ * an exception is made for entries whose name is "gdbserver".
+ * - The entry filename is "safe" (as determined by isFilenameSafe).
+ *
+ */
+class NativeLibrariesIterator {
+private:
+ NativeLibrariesIterator(ZipFileRO* zipFile, void* cookie)
+ : mZipFile(zipFile), mCookie(cookie), mLastSlash(NULL) {
+ fileName[0] = '\0';
}
+public:
+ static NativeLibrariesIterator* create(ZipFileRO* zipFile) {
+ void* cookie = NULL;
+ if (!zipFile->startIteration(&cookie)) {
+ return NULL;
+ }
+
+ return new NativeLibrariesIterator(zipFile, cookie);
+ }
+
+ ZipEntryRO next() {
+ ZipEntryRO next = NULL;
+ while ((next = mZipFile->nextEntry(mCookie)) != NULL) {
+ // Make sure this entry has a filename.
+ if (mZipFile->getEntryFileName(next, fileName, sizeof(fileName))) {
+ continue;
+ }
+
+ // Make sure we're in the lib directory of the ZIP.
+ if (strncmp(fileName, APK_LIB, APK_LIB_LEN)) {
+ continue;
+ }
+
+ // Make sure the filename is at least to the minimum library name size.
+ const size_t fileNameLen = strlen(fileName);
+ static const size_t minLength = APK_LIB_LEN + 2 + LIB_PREFIX_LEN + 1 + LIB_SUFFIX_LEN;
+ if (fileNameLen < minLength) {
+ continue;
+ }
+
+ const char* lastSlash = strrchr(fileName, '/');
+ ALOG_ASSERT(lastSlash != NULL, "last slash was null somehow for %s\n", fileName);
+
+ // Exception: If we find the gdbserver binary, return it.
+ if (!strncmp(lastSlash + 1, GDBSERVER, GDBSERVER_LEN)) {
+ break;
+ }
+
+ // Make sure the filename starts with lib and ends with ".so".
+ if (strncmp(fileName + fileNameLen - LIB_SUFFIX_LEN, LIB_SUFFIX, LIB_SUFFIX_LEN)
+ || strncmp(lastSlash, LIB_PREFIX, LIB_PREFIX_LEN)) {
+ continue;
+ }
+
+ // Make sure the filename is safe.
+ if (!isFilenameSafe(lastSlash + 1)) {
+ continue;
+ }
+
+ mLastSlash = lastSlash;
+ break;
+ }
+
+ return next;
+ }
+
+ inline const char* currentEntry() const {
+ return fileName;
+ }
+
+ inline const char* lastSlash() const {
+ return mLastSlash;
+ }
+
+ virtual ~NativeLibrariesIterator() {
+ mZipFile->endIteration(mCookie);
+ }
+private:
+
char fileName[PATH_MAX];
- bool hasPrimaryAbi = false;
+ ZipFileRO* const mZipFile;
+ void* mCookie;
+ const char* mLastSlash;
+};
- void* cookie = NULL;
- if (!zipFile->startIteration(&cookie)) {
- ALOGI("Couldn't iterate over APK%s\n", filePath.c_str());
+static install_status_t
+iterateOverNativeFiles(JNIEnv *env, jlong apkHandle, jstring javaCpuAbi,
+ iterFunc callFunc, void* callArg) {
+ ZipFileRO* zipFile = reinterpret_cast<ZipFileRO*>(apkHandle);
+ if (zipFile == NULL) {
return INSTALL_FAILED_INVALID_APK;
}
+ UniquePtr<NativeLibrariesIterator> it(NativeLibrariesIterator::create(zipFile));
+ if (it.get() == NULL) {
+ return INSTALL_FAILED_INVALID_APK;
+ }
+
+ const ScopedUtfChars cpuAbi(env, javaCpuAbi);
+ if (cpuAbi.c_str() == NULL) {
+ // This would've thrown, so this return code isn't observable by
+ // Java.
+ return INSTALL_FAILED_INVALID_APK;
+ }
ZipEntryRO entry = NULL;
- while ((entry = zipFile->nextEntry(cookie)) != NULL) {
- // Make sure this entry has a filename.
- if (zipFile->getEntryFileName(entry, fileName, sizeof(fileName))) {
- continue;
- }
-
- // Make sure we're in the lib directory of the ZIP.
- if (strncmp(fileName, APK_LIB, APK_LIB_LEN)) {
- continue;
- }
-
- // Make sure the filename is at least to the minimum library name size.
- const size_t fileNameLen = strlen(fileName);
- static const size_t minLength = APK_LIB_LEN + 2 + LIB_PREFIX_LEN + 1 + LIB_SUFFIX_LEN;
- if (fileNameLen < minLength) {
- continue;
- }
-
- const char* lastSlash = strrchr(fileName, '/');
- ALOG_ASSERT(lastSlash != NULL, "last slash was null somehow for %s\n", fileName);
+ while ((entry = it->next()) != NULL) {
+ const char* fileName = it->currentEntry();
+ const char* lastSlash = it->lastSlash();
// Check to make sure the CPU ABI of this file is one we support.
const char* cpuAbiOffset = fileName + APK_LIB_LEN;
const size_t cpuAbiRegionSize = lastSlash - cpuAbiOffset;
- ALOGV("Comparing ABIs %s and %s versus %s\n", cpuAbi.c_str(), cpuAbi2.c_str(), cpuAbiOffset);
- if (cpuAbi.size() == cpuAbiRegionSize
- && *(cpuAbiOffset + cpuAbi.size()) == '/'
- && !strncmp(cpuAbiOffset, cpuAbi.c_str(), cpuAbiRegionSize)) {
- ALOGV("Using primary ABI %s\n", cpuAbi.c_str());
- hasPrimaryAbi = true;
- } else if (cpuAbi2.size() == cpuAbiRegionSize
- && *(cpuAbiOffset + cpuAbi2.size()) == '/'
- && !strncmp(cpuAbiOffset, cpuAbi2.c_str(), cpuAbiRegionSize)) {
-
- /*
- * If this library matches both the primary and secondary ABIs,
- * only use the primary ABI.
- */
- if (hasPrimaryAbi) {
- ALOGV("Already saw primary ABI, skipping secondary ABI %s\n", cpuAbi2.c_str());
- continue;
- } else {
- ALOGV("Using secondary ABI %s\n", cpuAbi2.c_str());
- }
- } else {
- ALOGV("abi didn't match anything: %s (end at %zd)\n", cpuAbiOffset, cpuAbiRegionSize);
- continue;
- }
-
- // If this is a .so file, check to see if we need to copy it.
- if ((!strncmp(fileName + fileNameLen - LIB_SUFFIX_LEN, LIB_SUFFIX, LIB_SUFFIX_LEN)
- && !strncmp(lastSlash, LIB_PREFIX, LIB_PREFIX_LEN)
- && isFilenameSafe(lastSlash + 1))
- || !strncmp(lastSlash + 1, GDBSERVER, GDBSERVER_LEN)) {
-
- install_status_t ret = callFunc(env, callArg, zipFile.get(), entry, lastSlash + 1);
+ if (cpuAbi.size() == cpuAbiRegionSize && !strncmp(cpuAbiOffset, cpuAbi.c_str(), cpuAbiRegionSize)) {
+ install_status_t ret = callFunc(env, callArg, zipFile, entry, lastSlash + 1);
if (ret != INSTALL_SUCCEEDED) {
ALOGV("Failure for entry %s", lastSlash + 1);
- zipFile->endIteration(cookie);
return ret;
}
}
}
- zipFile->endIteration(cookie);
-
return INSTALL_SUCCEEDED;
}
+
+static int findSupportedAbi(JNIEnv *env, jlong apkHandle, jobjectArray supportedAbisArray) {
+ const int numAbis = env->GetArrayLength(supportedAbisArray);
+ Vector<ScopedUtfChars*> supportedAbis;
+
+ for (int i = 0; i < numAbis; ++i) {
+ supportedAbis.add(new ScopedUtfChars(env,
+ (jstring) env->GetObjectArrayElement(supportedAbisArray, i)));
+ }
+
+ ZipFileRO* zipFile = reinterpret_cast<ZipFileRO*>(apkHandle);
+ if (zipFile == NULL) {
+ return INSTALL_FAILED_INVALID_APK;
+ }
+
+ UniquePtr<NativeLibrariesIterator> it(NativeLibrariesIterator::create(zipFile));
+ if (it.get() == NULL) {
+ return INSTALL_FAILED_INVALID_APK;
+ }
+
+ ZipEntryRO entry = NULL;
+ char fileName[PATH_MAX];
+ int status = NO_NATIVE_LIBRARIES;
+ while ((entry = it->next()) != NULL) {
+ // We're currently in the lib/ directory of the APK, so it does have some native
+ // code. We should return INSTALL_FAILED_NO_MATCHING_ABIS if none of the
+ // libraries match.
+ if (status == NO_NATIVE_LIBRARIES) {
+ status = INSTALL_FAILED_NO_MATCHING_ABIS;
+ }
+
+ const char* fileName = it->currentEntry();
+ const char* lastSlash = it->lastSlash();
+
+ // Check to see if this CPU ABI matches what we are looking for.
+ const char* abiOffset = fileName + APK_LIB_LEN;
+ const size_t abiSize = lastSlash - abiOffset;
+ for (int i = 0; i < numAbis; i++) {
+ const ScopedUtfChars* abi = supportedAbis[i];
+ if (abi->size() == abiSize && !strncmp(abiOffset, abi->c_str(), abiSize)) {
+ // The entry that comes in first (i.e. with a lower index) has the higher priority.
+ if (((i < status) && (status >= 0)) || (status < 0) ) {
+ status = i;
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < numAbis; ++i) {
+ delete supportedAbis[i];
+ }
+
+ return status;
+}
+
static jint
com_android_internal_content_NativeLibraryHelper_copyNativeBinaries(JNIEnv *env, jclass clazz,
- jstring javaFilePath, jstring javaNativeLibPath, jstring javaCpuAbi, jstring javaCpuAbi2)
+ jlong apkHandle, jstring javaNativeLibPath, jstring javaCpuAbi)
{
- return (jint) iterateOverNativeFiles(env, javaFilePath, javaCpuAbi, javaCpuAbi2,
+ return (jint) iterateOverNativeFiles(env, apkHandle, javaCpuAbi,
copyFileIfChanged, &javaNativeLibPath);
}
static jlong
com_android_internal_content_NativeLibraryHelper_sumNativeBinaries(JNIEnv *env, jclass clazz,
- jstring javaFilePath, jstring javaCpuAbi, jstring javaCpuAbi2)
+ jlong apkHandle, jstring javaCpuAbi)
{
size_t totalSize = 0;
- iterateOverNativeFiles(env, javaFilePath, javaCpuAbi, javaCpuAbi2, sumFiles, &totalSize);
+ iterateOverNativeFiles(env, apkHandle, javaCpuAbi, sumFiles, &totalSize);
return totalSize;
}
+static jint
+com_android_internal_content_NativeLibraryHelper_findSupportedAbi(JNIEnv *env, jclass clazz,
+ jlong apkHandle, jobjectArray javaCpuAbisToSearch)
+{
+ return (jint) findSupportedAbi(env, apkHandle, javaCpuAbisToSearch);
+}
+
+static jlong
+com_android_internal_content_NativeLibraryHelper_openApk(JNIEnv *env, jclass, jstring apkPath)
+{
+ ScopedUtfChars filePath(env, apkPath);
+ ZipFileRO* zipFile = ZipFileRO::open(filePath.c_str());
+
+ return reinterpret_cast<jlong>(zipFile);
+}
+
+static void
+com_android_internal_content_NativeLibraryHelper_close(JNIEnv *env, jclass, jlong apkHandle)
+{
+ delete reinterpret_cast<ZipFileRO*>(apkHandle);
+}
+
static JNINativeMethod gMethods[] = {
+ {"nativeOpenApk",
+ "(Ljava/lang/String;)J",
+ (void *)com_android_internal_content_NativeLibraryHelper_openApk},
+ {"nativeClose",
+ "(J)V",
+ (void *)com_android_internal_content_NativeLibraryHelper_close},
{"nativeCopyNativeBinaries",
- "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
+ "(JLjava/lang/String;Ljava/lang/String;)I",
(void *)com_android_internal_content_NativeLibraryHelper_copyNativeBinaries},
{"nativeSumNativeBinaries",
- "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)J",
+ "(JLjava/lang/String;)J",
(void *)com_android_internal_content_NativeLibraryHelper_sumNativeBinaries},
+ {"nativeFindSupportedAbi",
+ "(J[Ljava/lang/String;)I",
+ (void *)com_android_internal_content_NativeLibraryHelper_findSupportedAbi},
};
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 0f772f1..a83942f 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1921,6 +1921,18 @@
android:description="@string/permdesc_filter_events"
android:protectionLevel="signature" />
+ <!-- @hide Allows an application to retrieve the window token from the accessibility manager. -->
+ <permission android:name="android.permission.RETRIEVE_WINDOW_TOKEN"
+ android:label="@string/permlab_retrieveWindowToken"
+ android:description="@string/permdesc_retrieveWindowToken"
+ android:protectionLevel="signature" />
+
+ <!-- @hide Allows an application to collect frame statistics -->
+ <permission android:name="android.permission.FRAME_STATS"
+ android:label="@string/permlab_frameStats"
+ android:description="@string/permdesc_frameStats"
+ android:protectionLevel="signature" />
+
<!-- @hide Allows an application to temporary enable accessibility on the device. -->
<permission android:name="android.permission.TEMPORARY_ENABLE_ACCESSIBILITY"
android:label="@string/permlab_temporary_enable_accessibility"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index b9bdfb9..88f5c54 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Dit laat die houer toe om aan die topvlak-koppelvlak van \'n legstuk-diens te bind. Dit moet nooit vir normale programme nodig wees nie."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"skakel met \'n toestel-admin"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Laat die houer toe om bedoelings na \'n toesteladministrateur te stuur. Dit moet nooit vir normale programme nodig wees nie."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"voeg \'n toesteladministrateur by of verwyder een"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Laat die houer aktiewe toesteladministrateurs byvoeg of verwyder. Behoort nooit nodig te wees vir normale programme nie."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"verander skermoriëntasie"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 22246c1..9795461 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"ያዡ ግቤት ስልቱን ወደ ከፍተኛ-ደረጃ ፍርግም አገልግሎት ለመጠረዝ ይፈቅዳሉ። ለመደበኛ ትግበራዎች በፍፁም አያስፈልግም።"</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"ከመሣሪያ አስተዳደር ጋር ተገናኝ"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"ያዡ በይነመረብን ለመሣሪያ አስተዳዳሪ ለመላክ ይፈቅዳሉ። ለመደበኛ መተግበሪያዎች በፍፁም አያስፈልግም።"</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"የመሣሪያ አስተዳዳሪ ያክሉ ወይም ያስወግዱ"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"ያዢው ንቁ የመሣሪያ አስተዳዳሪዎች እንዲያክል ወይም እንዲያስወግድ ያስችለዋል። ለመደበኛ መተግበሪያዎች ጭራሽ ሊያስፈልግ አይገባም።"</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"የማያ ገፀ አቀማመጥን ለውጥ"</string>
@@ -688,7 +692,7 @@
<string name="permlab_setInputCalibration" msgid="4902620118878467615">"የግቤት መሣሪያ ማስተካከያ ቀይር"</string>
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"መተግበሪያው የማያ ንካ የማስተካከያ ልኬቶቹን እንዲቀይር ያስችለዋል። ለመደበኛ መተግበሪያዎች በጭራሽ ሊያስፈልግ አይገባም።"</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"የDRM የምስክር ወረቀቶች ላይ ይድረሱ"</string>
- <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"አንድ መተግበሪያ የDRM የምስክር ወረቀቶችን እንዲሰጥና እንዲጠም ያስችላል። ለመደበኛ መተግበሪያዎች በፍጹም አስፈላጊ አይሆንም።"</string>
+ <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"አንድ መተግበሪያ የDRM የምስክር ወረቀቶችን እንዲሰጥና እንዲጠቀም ያስችላል። ለመደበኛ መተግበሪያዎች በፍጹም አስፈላጊ አይሆንም።"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"የይለፍ ቃል ደንቦች አዘጋጅ"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"በማያ-መክፈት የተፈቀዱ የይለፍ ቃል ርዝመት እና ቁምፊዎች ተቆጣጠር።"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"የማሳያ-ክፈት ሙከራዎችን አሳይ"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 9efd8eb..101c4dc 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"للسماح للمالك بالالتزام بواجهة المستوى العلوي لخدمة الأداة. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"التفاعل مع مشرف الجهاز"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"للسماح للمالك بإرسال الأهداف إلى أحد مشرفي الجهاز. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"إضافة مشرف جهاز أو إزالته"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"للسماح بحامل البطاقة بإضافة مشرفي أجهزة نشطين أو إزالتهم. لا يلزم ذلك أبدًا للتطبيقات العادية."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"تغيير اتجاه الشاشة"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 366de7c..499280e 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Разрешава на притежателя да се обвърже с интерфейса от най-високото ниво на услуга за приспособления. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"взаимодействие с администратор на устройството"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Разрешава на притежателя да изпраща намерения до администратор на устройството. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"добавяне или премахване на администратор на устройства"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Разрешава на притежателя да добавя или премахва администратори на активни устройства. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"промяна на ориентацията на екрана"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 6cba689..1d063f6 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permet que el titular vinculi a la interfície de nivell superior d\'un servei de widget. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interactuar amb un administrador del dispositiu"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Permet que el titular enviï intents a un administrador del sistema. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"afegeix un administrador al dispositiu o suprimeix-lo"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Permet que el titular afegeixi administradors actius al dispositiu o en suprimeixi. No s\'hauria de necessitar per a les aplicacions normals."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"canviar l\'orientació de la pantalla"</string>
@@ -687,7 +691,7 @@
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Permet que una aplicació conegui les observacions sobre les condicions de la xarxa. No s\'ha de necessitar mai per a aplicacions normals."</string>
<string name="permlab_setInputCalibration" msgid="4902620118878467615">"canviar el calibratge del dispositiu d\'entrada"</string>
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Permet que l\'aplicació modifiqui els paràmetres de calibratge de la pantalla tàctil. No ha de ser mai necessari per a aplicacions normals."</string>
- <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"accés als certificats de DRM"</string>
+ <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"accedir als certificats de DRM"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Permet que una aplicació proporcioni i utilitzi certificats de gestió de drets digitals (DRM, Digital Rights Management). No ha de ser mai necessari per a aplicacions normals."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Definir les normes de contrasenya"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Controla la longitud i els caràcters permesos a les contrasenyes de desbloqueig de pantalla."</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index b4972ef..6a14d0e 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Umožňuje držiteli navázat se na nejvyšší úroveň služby widgetu. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"komunikovat se správcem zařízení"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Umožňuje držiteli oprávnění odesílat informace správci zařízení. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"přidat nebo odebrat správce zařízení"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Opravňuje držitele přidávat nebo odebírat aktivní správce zařízení. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"změna orientace obrazovky"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index d3469f1..3c113f0 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Tillader, at brugeren kan forpligte sig til en grænseflade for en widgettjeneste på øverste niveau. Bør aldrig være nødvendigt til almindelige apps."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"kommunikere med en enhedsadministrator"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Tillader, at brugeren kan sende hensigter til en enhedsadministrator. Dette bør aldrig være nødvendigt for almindelige apps."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"tilføje eller fjerne en enhedsadministrator"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Tillader, at man tilføjer eller fjerner aktive enhedsadministratorer. Dette burde aldrig være nødvendigt til normale apps."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"skift skærmretning"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 52ea81c..c2c8600 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Ermöglicht dem Halter, sich an die Oberfläche eines Widget-Dienstes auf oberster Ebene zu binden. Sollte nie für normale Apps benötigt werden."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"Interaktion mit einem Geräteadministrator"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Ermöglicht dem Halter, Intents an einen Geräteadministrator zu senden. Sollte nie für normale Apps benötigt werden."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"Geräteadministrator hinzufügen oder entfernen"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Ermöglicht dem Inhaber, aktive Geräteadministratoren hinzuzufügen oder zu entfernen. Sollte für normale Apps nie benötigt werden."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"Bildschirmausrichtung ändern"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 8b7e618..e1e9106 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας υπηρεσίας γραφικών στοιχείων. Δεν απαιτείται για κανονικές εφαρμογές."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"επικοινωνία με έναν διαχειριστή συσκευής"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Επιτρέπει στον κάτοχο την αποστολή στόχων σε έναν διαχειριστή συσκευής. Δεν είναι απαραίτητο για συνήθεις εφαρμογές."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"προσθήκη ή κατάργηση ενός διαχειριστή συσκευής"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Επιτρέπει στον κάτοχο να προσθέτει ή να καταργεί ενεργούς διαχειριστές συσκευών. Δεν θα πρέπει να ζητείται ποτέ για κανονικές εφαρμογές."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"αλλαγή προσανατολισμού οθόνης"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 179691b..8da35f1 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Allows the holder to bind to the top-level interface of a widget service. Should never be needed for normal apps."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interact with device admin"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Allows the holder to send intents to a device administrator. Should never be needed for normal apps."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"add or remove a device admin"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Allows the holder to add or remove active device administrators. Should never be needed for normal apps."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"change screen orientation"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 179691b..8da35f1 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Allows the holder to bind to the top-level interface of a widget service. Should never be needed for normal apps."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interact with device admin"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Allows the holder to send intents to a device administrator. Should never be needed for normal apps."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"add or remove a device admin"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Allows the holder to add or remove active device administrators. Should never be needed for normal apps."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"change screen orientation"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index dc67e27..ae96d40 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permite al propietario vincularse a la interfaz de nivel superior del servicio de widget. Las aplicaciones normales no deberían necesitar este permiso."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interactuar con un administrador de dispositivos"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Permite enviar intentos a un administrador de dispositivos. Las aplicaciones normales no deberían necesitar este permiso."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"agregar o eliminar un administrador de dispositivos"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Permite al propietario agregar o eliminar administradores de dispositivos activos. Las aplicaciones normales no deberían necesitar este permiso."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"cambiar la orientación de la pantalla"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 8386b02..638b9f4 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permite enlazar con la interfaz de nivel superior de un servicio de widget. Las aplicaciones normales no deberían necesitar este permiso."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interactuar con el administrador de un dispositivo"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Permite que se envíen intentos a un administrador de dispositivos. Las aplicaciones normales nunca deberían necesitar este permiso."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"añadir o eliminar un administrador de dispositivos"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Permite añadir o eliminar administradores de dispositivos activos. No debe ser necesario para aplicaciones normales."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"cambiar orientación de la pantalla"</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 4d15e4a..adb033f 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Lubab omanikul siduda vidina teenuse ülataseme liidesega. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"seadme administraatoriga suhtlemine"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Võimaldab omanikul saata kavatsusi seadme administraatorile. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"seadme administraatori lisamine või eemaldamine"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Võimaldab omanikul lisada või eemaldada aktiivseid seadme administraatoreid. Tavarakenduste puhul ei tohiks see kunagi vajalik olla."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"muuda ekraani paigutust"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index b621d49..3375255 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"به دارنده اجازه میدهد که به رابط سطح بالای سرویس ابزارک متصل شود. هرگز برای برنامههای معمولی مورد نیاز نیست."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"تعامل با یک سرپرست دستگاه"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"به دارنده اجازه میدهد اهداف خود را به سرپرست دستگاه ارسال کند. برنامههای معمولی هیچگاه به این ویژگی نیازی ندارند."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"اضافه یا حذف سرپرست دستگاه"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"به دارنده اجازه میدهد سرپرستان دستگاه فعال را اضافه یا حذف کند.هرگز نباید برای برنامههای عادی مورد نیاز باشد."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"تغییر جهت صفحه"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 6dd5e56..d2bf01c 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Antaa sovelluksen sitoutua widget-palvelun ylemmän tason käyttöliittymään. Ei tavallisten sovelluksien käyttöön."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"kommunikoi laitteen järjestelmänvalvojan kanssa"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Antaa sovelluksen lähettää aikomuksia laitteen järjestelmänvalvojalle. Ei tavallisten sovellusten käyttöön."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"lisää tai poista laitteen järjestelmänvalvoja"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Haltija voi lisätä tai poistaa aktiivisen laitteen järjestelmänvalvojia. Tätä ei pitäisi tarvita tavallisille sovelluksille."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"muuta näytön suuntaa"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 7a8c975..74df7fe 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un service de widget. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interagir avec l\'administrateur d\'un périphérique"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Permet à l\'application autorisée d\'envoyer des intentions à l\'administrateur de l\'appareil. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"ajouter ou supprimer un administrateur de l\'appareil"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Permet à l\'application d\'ajouter ou de supprimer des administrateurs actifs de l\'appareil. Les applications standards ne devraient jamais utiliser cette autorisation."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"modifier l\'orientation de l\'écran"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index a57823f..691c6a4 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un service widget. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interagir avec l\'administrateur du périphérique"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Permet à l\'application autorisée d\'envoyer des intentions à l\'administrateur de l\'appareil. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"ajouter ou supprimer un administrateur de l\'appareil"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Permet à l\'application autorisée d\'ajouter ou de supprimer des administrateurs actifs de l\'appareil. Les applications standards ne devraient pas nécessiter cette autorisation."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"Changement d\'orientation de l\'écran"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index bdba457..1419bc4 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"धारक को किसी विजेट सेवा के शीर्ष-स्तर इंटरफ़ेस से आबद्ध होने देता है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"किसी उपकरण व्यवस्थापक के साथ सहभागिता करें"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"धारक को किसी उपकरण व्यवस्थापक को उद्देश्य भेजने देता है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"उपकरण उपकरण सुचारू ढ़ंग से चलाने वाले को जोड़ें या निकालें"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"धारक को सक्रिय डिवाइस व्यवस्थापकों को जोड़ने या निकालने देता है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"स्क्रीन अभिविन्यास बदलें"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index fcd51ab..dde0a5b 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Nositelju omogućuje vezanje uz sučelje najviše razine usluge widgeta. Ne bi smjelo biti potrebno za normalne aplikacije."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interakcija s administratorom uređaja"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Nositelju omogućuje slanje namjera administratoru uređaja. Ne bi smjelo biti potrebno za normalne aplikacije."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"dodavanje ili uklanjanje administratora uređaja"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Omogućuje nositelju dodavanje ili uklanjanje administratora aktivnih uređaja. Nikada ne bi trebalo biti potrebno za uobičajene aplikacije."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"promjena orijentacije zaslona"</string>
@@ -688,7 +692,7 @@
<string name="permlab_setInputCalibration" msgid="4902620118878467615">"promjena kalibracije uređaja za unos"</string>
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Omogućuje aplikaciji izmjenu parametara kalibracije dodirnog zaslona. Ne bi trebalo biti potrebno za uobičajene aplikacije."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"pristup DRM certifikatima"</string>
- <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Aplikaciji omogućuje pružanje i korištenje DRM certifikata. Nikad ne bi trebalo biti potrebno za uobičajene aplikacije."</string>
+ <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Aplikaciji omogućuje pružanje i korištenje DRM certifikata. Ne bi trebalo biti potrebno za uobičajene aplikacije."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Postavi pravila zaporke"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Upravljajte duljinom zaporki za otključavanje zaslona i dopuštenim znakovima u tim zaporkama."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Nadgledaj pokušaje otključavanja zaslona"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 4932e88..41a1fb9 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Lehetővé teszi a használó számára, hogy csatlakozzon egy modulszolgáltatás legfelső szintű kezelőfelületéhez. A normál alkalmazásoknak erre soha nincs szüksége."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"az eszközkezelő használata"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Lehetővé teszi a tulajdonos számára, hogy célokat küldjön egy eszközkezelőnek. A normál alkalmazásoknak erre soha nincs szüksége."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"eszközrendszergazda hozzáadása vagy eltávolítása"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Lehetővé teszi a tulajdonos számára, hogy aktív eszközrendszergazdákat adjon meg vagy távolítson el. A normál alkalmazásoknál erre soha nincs szükség."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"képernyő irányának módosítása"</string>
@@ -688,7 +692,7 @@
<string name="permlab_setInputCalibration" msgid="4902620118878467615">"beviteli eszköz kalibrációjának módosítása"</string>
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Lehetővé teszi, hogy az alkalmazás módosítsa az érintőképernyő kalibrációs paramétereit. A normál alkalmazásoknál erre elvileg soha nincs szükség."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"DRM-tanúsítványokhoz való hozzáférés"</string>
- <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Engedélyezi egy alkalmazás számára a DRM-tanúsítványokhoz való hozzáférést és azok használatát. Átlagos alkalmazásoknak erre nem lehet szüksége."</string>
+ <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Engedélyezi egy alkalmazás számára a DRM-tanúsítványokhoz való hozzáférést és azok használatát. Átlagos alkalmazásoknak erre nem lehet szükségük."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Jelszavakkal kapcsolatos szabályok beállítása"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"A képernyőzár-feloldási jelszavakban engedélyezett karakterek és hosszúság vezérlése."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Képernyőzár-feloldási kísérletek figyelése"</string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 805f77b..d2f7c13 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Թույլ է տալիս սեփականատիրոջը միանալ վիջեթ ծառայության վերին մակարդակի ինտերֆեյսին: Սովորական հավելվածների համար երբևէ չպետք է անհրաժեշտ լինի:"</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"փոխգործակցել սարքի կառավարչի հետ"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Թույլ է տալիս սեփականատիրոջը ուղարկել մտադրություններ սարքի կառավարչին: Սովորական հավելվածների համար երբևէ չպետք է անհրաժեշտ լինի:"</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"ավելացնել կամ հեռացնել սարքի արդմինիստրատոր"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Թույլ է տալիս սեփականատիրոջը ավելացնել կամ հեռացնել սարքի ակտիվ ադմինիստրատորներ: Երբեք չպետք է անհրաժեշտ լինի սովորական ծրագրերին:"</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"փոխել էկրանի դիրքավորումը"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index e161466..b1d94e6 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Mengizinkan pemegang mengikat antarmuka tingkat tinggi dari suatu layanan widget. Tidak pernah diperlukan oleh apl normal."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"berinteraksi dengan admin perangkat"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Mengizinkan pemegang mengirimkan tujuan kepada administrator perangkat. Tidak pernah diperlukan oleh apl normal."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"menambah atau menghapus admin perangkat"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Memungkinkan pemegang menambahkan atau menghapus administrator perangkat aktif. Tidak pernah dibutuhkan oleh aplikasi normal."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"ubah orientasi layar"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 740075f..27b05d1 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Consente l\'associazione all\'interfaccia principale di un servizio widget. Non dovrebbe mai essere necessario per le normali applicazioni."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interazione con un amministratore dispositivo"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Consente l\'invio di intent a un amministratore del dispositivo. L\'autorizzazione non dovrebbe mai essere necessaria per le normali applicazioni."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"aggiungere o rimuovere un amministratore del dispositivo"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Consente al titolare di aggiungere o rimuovere gli amministratori attivi del dispositivo. Non dovrebbe mai essere necessario per le normali applicazioni."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"modifica orientamento dello schermo"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 61754c3..222dfe3 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"מאפשר למשתמש לבצע איגוד לממשק הרמה העליונה של שירות Widget. הרשאה זו לעולם אינה נחוצה לאפליקציות רגילים."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"קיים אינטראקציה עם מנהל המכשיר"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"מאפשר למשתמש לשלוח כוונות למנהל התקנים. הרשאה זו לעולם אינה נחוצה לאפליקציות רגילים."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"הוספה או הסרה של מנהלי מכשיר"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"מאפשרת לבעלים להוסיף או להסיר מנהלי מכשיר פעילים. לעולם לא אמורה להיות נחוצה עבור אפליקציות רגילות."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"שנה את כיוון המסך"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 62ee883..d1e1308 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"ウィジェットサービスのトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"デバイス管理者との通信"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"デバイス管理者へのintentの送信を所有者に許可します。通常のアプリでは不要です。"</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"端末の管理者の追加または削除"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"有効な端末の管理者を追加または削除することを所有者に許可します。通常のアプリでは不要です。"</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"画面の向きの変更"</string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index 4855f27..9ea2503 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"აპს შეეძლება ზედა დონის ინტერფეისის ვიჯეტთან დაკავშირება. არასდროს გამოიყენება ჩვეულებრივ აპებში."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"მოწყობილობის ადმინთან ინტერაქცია"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"აპს შეეძლება მოწყობილობის ადმინისტრატორისთვის intent ობიექტების გაგზავნა. არასდროს გამოიყენება ჩვეულებრივ აპებში."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"მოწყობილობის ადმინისტრატორს დამატება ან ამოშლა"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"საშუალებას აძლევს მფლობელს დაამატოს ან ამოშალოს მოწყობილობის აქტიური ადმინისტრატორები. ჩვეულებრივ აპებს, ალბათ, არასოდეს დაჭირდება"</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"ეკრანის ორიენტაციის შეცვლა"</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 73769fb..8dbd6ac 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"ឲ្យម្ចាស់ចងចំណុចប្រទាក់កម្រិតកំពូលនៃសេវាកម្មធាតុក្រាហ្វិក។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"ទាក់ទងជាមួយអ្នកគ្រប់គ្រងឧបករណ៍"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"ឲ្យម្ចាស់ផ្ញើគោលបំណងទៅអ្នកគ្រប់គ្រងឧបករណ៍។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"បន្ថែម ឬលុបកម្មវិធីគ្រប់គ្រងឧបករណ៍"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"អនុញ្ញាតឲ្យម្ចាស់បន្ថែម ឬលុបកម្មវិធីគ្រប់គ្រងឧបករណ៍សកម្មចេញ។ មិនគួរប្រើសម្រាប់កម្មវិធីធម្មតាទេ។"</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"ប្ដូរទិសអេក្រង់"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index bb26d4f..a389466 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"권한을 가진 프로그램이 위젯 서비스에 대한 최상위 인터페이스를 사용하도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"기기 관리자와 상호 작용"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"권한을 가진 프로그램이 기기 관리자에게 인텐트를 보낼 수 있도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"기기 관리자 추가 또는 삭제"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"권한을 가진 프로그램이 활성화된 기기의 관리자를 추가 또는 삭제하도록 합니다. 일반 앱에는 필요하지 않습니다."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"화면 방향 변경"</string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index 60b7da4..79b8a33 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"ອະນຸຍາດໃຫ້ຜູ່ຖືຜູກກັບອິນເຕີເຟດລະດັບສູງສຸດ ຂອງບໍລິການວິເຈັດ. ບໍ່ຈຳເປັນສຳລັບແອັບຯທົ່ວໄປ."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"ຕິດຕໍ່ກັບຜູ່ເບິ່ງແຍງອຸປະກອນ"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"ອະນຸຍາດໃຫ້ເຈົ້າຂອງສົ່ງເຈດຕະນາຫາຜູ່ເບິ່ງແຍງລະບົບອຸປະກອນ. ແອັບຯທົ່ວໄປບໍ່ຄວນຈຳເປັນຕ້ອງໃຊ້."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"ເພີ່ມ ຫຼືລຶບຜູ່ເບິ່ງແຍງລະບົບອຸປະກອນ"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"ອະນຸຍາດໃຫ້ເຈົ້າຂອງສາມາດລຶບ ຫຼືລຶບຂໍ້ມູນອຸປະກອນທີ່ນຳໃຊ້ໄດ້. ແອັບຯທົ່ວໄປບໍ່ຈຳເປັນຕ້ອງໃຊ້."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"ປ່ຽນລວງຂອງໜ້າຈໍ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index b40e10b..99184d2 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Leidžiama savininkui susisaistyti su aukščiausio lygio valdiklio paslaugos sąsaja. Įprastoms programoms to neturėtų prireikti."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"sąveikauti su įrenginio administratoriumi"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Leidžiama savininkui siųsti tikslus įrenginio administratoriui. Įprastoms programoms to neturėtų prireikti."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"pridėti arba pašalinti įrenginio administratorių"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Savininkui leidžiama pridėti aktyvių įrenginio administratorių arba juos pašalinti. Neturėtų reikėti įprastoms programoms."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"keisti ekrano padėtį"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 6b91a6d..433115c 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Ļauj īpašniekam izveidot saiti ar logrīka pakalpojuma augšējā līmeņa saskarni. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"mijiedarboties ar ierīces administratoru"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Ļauj īpašniekam nosūtīt informāciju par nodomiem ierīces administratoram. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"pievienot vai noņemt ierīces administratoru"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Ļauj īpašniekam pievienot vai noņemt aktīvos ierīces administratorus. Nekad nav nepieciešama parastām lietotnēm."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"mainīt ekrāna orientāciju"</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index ea1baa1..442b856 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Эзэмшигч нь виджет үйлчилгээний дээд-төвшиний интерфейстэй холбох боломжтой. Энгийн апп-д шаардлагагүй."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"төхөөрөмжийн админтай харилцан үйлчлэх"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Эзэмшигч нь төхөөрөмжийн админруу интент илгээх боломжтой. Энгийн апп-д шаардлагагүй."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"төхөөрөмжийн админ нэмэх, хасах"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Эзэмшигч нь идэвхтэй төхөөрөмжийн администраторыг нэмэх, хасах боломжтой. Энгийн апп-д шаардлагагүй."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"дэлгэцний чиглэлийг солих"</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index 219e47b..27c413d 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi perkhidmatan widget. Tidak sekali-kali diperlukan untuk apl biasa."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"berinteraksi dengan pentadbir peranti"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Membenarkan pemegang menghantar tujuan kepada pentadbir peranti. Tidak sekali-kali diperlukan untuk apl biasa."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"tambah atau alih keluar pentadbir peranti"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Membenarkan pemegang menambah atau mengalih keluar pentadbir peranti aktif. Tidak sekali-kali diperlukan untuk apl biasa."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"tukar orientasi skrin"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 593d260..a6d186f 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Lar innehaveren binde seg til det øverste nivået av grensesnittet for en modultjeneste. Skal aldri være nødvendig for vanlige apper."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"kommunisere med enhetsadministrator"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Lar innehaveren sende hensikter til en enhetsadministrator. Skal aldri være nødvendig for normale apper."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"legge til eller fjerne en enhetsadministrator"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Tillater innehaveren å legge til eller fjerne aktive enhetsadministratorer. Dette skal aldri være nødvendig for vanlige apper."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"snu skjermen"</string>
@@ -688,7 +692,7 @@
<string name="permlab_setInputCalibration" msgid="4902620118878467615">"endre kalibreringen av inndataenheter"</string>
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Lar appen endre kalibrasjonsparametrene for berøringsskjermen. Denne tillatelsen bør aldri være nødvendig for vanlige apper."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"tilgang til DRM-sertifikater"</string>
- <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Lar en app klargjøre og bruke DRM-sertifikater. Denne tillatelsen bør aldri være nødvendig for vanlige apper."</string>
+ <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Tillater at en app klargjøre og bruke DRM-sertifikater. Denne tillatelsen bør aldri være nødvendig for vanlige apper."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Angi passordregler"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontroller tillatt lengde og tillatte tegn i passord for opplåsing av skjerm."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Overvåk forsøk på opplåsing av skjerm"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 9225c23..9014f5a 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Hiermee wordt de houder toegestaan verbinding te maken met de hoofdinterface van een widgetservice. Nooit vereist voor normale apps."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interactie met apparaatbeheer"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Hiermee kan de houder intenties verzenden naar een apparaatbeheerder. Nooit vereist voor normale apps."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"een apparaatbeheerder toevoegen of verwijderen"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Hiermee kan de rechtenhouder actieve apparaatbeheerders toevoegen of verwijderen. Nooit vereist voor normale apps."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"schermstand wijzigen"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 931c24c..b08e236 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Zezwala na tworzenie powiązania z interfejsem najwyższego poziomu usługi widżetów. Nie powinno być nigdy potrzebne w przypadku zwykłych aplikacji."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interakcja z administratorem urządzenia"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Zezwala na wysyłanie intencji do administratora urządzenia. Nie powinno być nigdy potrzebne w przypadku zwykłych aplikacji."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"dodaj lub usuń administratora urządzenia"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Umożliwia właścicielowi dodawanie i usuwanie aktywnych administratorów urządzenia. Ta opcja nie jest wykorzystywana w przypadku standardowych aplikacji."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"zmienianie orientacji ekranu"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 9eb7512..379e3dd 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permite que o titular vincule a interface de nível superior de um serviço de widget. Nunca deverá ser necessário para aplicações normais."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interagir com um administrador do dispositivo"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Permite ao titular enviar intenções para um administrador do aparelho. Nunca deverá ser necessário para aplicações normais."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"adicionar ou remover um administrador de dispositivos"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Permite que o titular adicione ou remova administradores de dispositivos ativos. Nunca deverá ser necessário para aplicações normais."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"mudar orientação do ecrã"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index fd75660..7feb69b 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permite que o proprietário utilize a interface de nível superior de um serviço de widget. Nunca deve ser necessário para aplicativos normais."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interagir com o administrador de um dispositivo"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Permite que o proprietário envie tentativas ao administrador de um aparelho. Nunca deve ser necessário para aplicativos normais."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"adicionar ou remover um administrador do dispositivo"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Permite que o proprietário adicione ou remova administradores do dispositivo ativos. Não deve ser necessário para aplicativos comuns."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"alterar orientação da tela"</string>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 4e9806b..7fc7436 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -601,6 +601,10 @@
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interacziun cun in administratur dad apparats"</string>
<!-- no translation found for permdesc_bindDeviceAdmin (569715419543907930) -->
<skip />
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<!-- no translation found for permlab_manageDeviceAdmins (4248828900045808722) -->
<skip />
<!-- no translation found for permdesc_manageDeviceAdmins (5025608167709942485) -->
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index a8a75a5..2dfc1870 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permite proprietarului să se conecteze la interfaţa de nivel superior a unui serviciu widget. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interacţionare cu administratorul unui dispozitiv"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Permite proprietarului să trimită intenţii către un administrator al dispozitivului. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"adăugarea sau eliminarea unui administrator de dispozitiv"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Permite proprietarului să adauge sau să elimine administratorii activi ai dispozitivului. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"modificare orientare ecran"</string>
@@ -687,7 +691,7 @@
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Permite unei aplicații să asculte observații despre starea rețelei. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
<string name="permlab_setInputCalibration" msgid="4902620118878467615">"schimbați calibrarea dispozitivului de intrare"</string>
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Permite aplicației să modifice parametrii de calibrare a ecranului tactil. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
- <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"accesați certificatele DRM"</string>
+ <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"accesează certificatele DRM"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Permite unei aplicații să furnizeze și să utilizeze certificate DRM. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Setaţi reguli pentru parolă"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Stabiliţi lungimea şi tipul de caractere permise în parolele pentru deblocarea ecranului."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index d142e9a..7f07d6d 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Приложение сможет подключаться к базовому интерфейсу службы виджетов. Это разрешение не используется обычными приложениями."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"Взаимодействие с администратором устройства"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Приложение сможет отправлять объекты intent администратору устройства. Это разрешение не используется обычными приложениями."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"Добавление/удаление администратора устройства"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Владелец сможет добавлять и удалять администраторов устройства (используется лишь в некоторых приложениях)."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"Изменение ориентации экрана"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 707bdf1..aa467bb 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania služby miniaplikácií. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"komunikovať so správcom zariadenia"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Umožňuje držiteľovi odosielať informácie správcovi zariadenia. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"pridanie alebo odstránenie správcu zariadenia"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Umožňuje držiteľovi pridať alebo odstrániť správcov aktívnych zariadení. Bežné aplikácie by toto povolenie nemali nikdy potrebovať."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"zmena orientácie obrazovky"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index e93b128..808026c 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Lastniku omogoča povezovanje z vmesnikom storitve pripomočka najvišje ravni. Tega ni treba nikoli uporabiti za navadne programe."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interakcija s skrbnikom naprave"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Omogoča lastniku, da pošlje namere skrbniku naprave. Nikoli se ne uporablja za navadne programe."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"dodajanje ali odstranjevanje skrbnikov naprave"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Imetniku omogoča, da doda ali odstrani aktivne skrbnike naprave. Normalne aplikacije tega načeloma ne potrebujejo."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"spreminjanje usmerjenosti zaslona"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index b2928e4..0fed1e3 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Дозвољава власнику да се обавеже на интерфејс услуге виџета највишег нивоа. Уобичајене апликације никада не би требало да је користе."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"интеракција са администратором уређаја"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Омогућава да власник шаље своје намере администратору уређаја. Уобичајене апликације никада не би требало да је користе."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"додавање или уклањање администратора уређаја"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Дозвољава власнику да додаје или уклања активне администраторе уређаја. Уобичајене апликације никада не би требало да је користе."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"промена положаја екрана"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index b134a85..5afc0cd 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en widget. Ska inte behövas för vanliga appar."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"arbeta med en enhetsadministratör"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Tillåter att innehavaren skickar avsikter till en enhetsadministratör. Vanliga appar behöver aldrig göra detta."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"lägga till eller ta bort en enhetsadministratör"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Innehavaren får lägga till eller ta bort aktiva enhetsadministratörer. Detta ska normalt inte behövas för vanliga appar."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"ändra bildskärmens rikting"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 8f319f3..9885014 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Inaruhusu mmiliki kushurutisha kusano ya kiwango cha juu ya huduma ya wijeti. Haipaswi kuhitajika kwa programu za kawaida."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"jiunge na msimamizi wa kifaa"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Inamruhusu mmiliki kutuma malengo kwa msimamizi wa kifaa. Haipaswi kuhitajika kwa programu za kawaida."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"ongeza au ondoa msimamizi wa kifaa"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Inaruhusu mmiliki kuongeza au kuondoa wasimamizi wa kifaa waliopo. Kamwe kisihitajike kwa ajili ya programu za kawaida."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"badilisha uelekezo wa skrini"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index ecb3a58..ee35eae 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"อนุญาตให้ผู้ใช้เชื่อมโยงกับส่วนติดต่อผู้ใช้ระดับสูงสุดของบริการวิดเจ็ต ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"ติดต่อกับผู้ดูแลอุปกรณ์"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"อนุญาตให้ผู้ใช้ส่งการติดต่อไปยังโปรแกรมควบคุมอุปกรณ์ ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"เพิ่มหรือลบผู้ดูแลระบบอุปกรณ์"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"อนุญาตให้เจ้าของเพิ่มหรือลบผู้ดูแลระบบอุปกรณ์ที่ใช้งาน ไม่ควรต้องใช้สำหรับแอปปกติ"</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"เปลี่ยนการวางแนวหน้าจอ"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 0a5e64c..ba7033e 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Pinapayagan ang may-hawak na sumailalim sa nangungunang interface ng serbisyo ng widget. Hindi kailanman dapat na kailanganin para sa normal na apps."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"makipag-ugnay sa tagapangasiwa ng device"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Pinapayagan ang mga may-ari na magpadala ng mga layunin sa administrator ng device. Hindi kailanman dapat na kailanganin para sa normal na apps."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"magdagdag o mag-alis ng admin ng device"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Pinapayagan ang may-ari na magdagdag o mag-alis ng mga aktibong administrator ng device. Hindi dapat kailanganin kailanman para sa normal na apps."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"baguhin ang orientation ng screen"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 72e149f..e78e291 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Cihazın sahibine bir widget hizmetinin en üst düzey arayüzüne bağlanma izni verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"bir cihaz yöneticisi ile etkileşimde bulun"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Cihazın sahibinin cihaz yöneticisine amaç göndermesine izin verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"cihaz yöneticisi ekle veya kaldır"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"İzin sahibine, etkin cihaz yöneticileri ekleyip kaldırma izni verir. Normal uygulamalar için hiçbir zaman gerekmez."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"ekran yönünü değiştir"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 563d5ee..e31392e 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Дозволяє власникові прив’язуватися до інтерфейсу верхнього рівня служби віджетів. Ніколи не застосовується для звичайних програм."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"взаємодіяти з адмін. пристрою"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Дозволяє власнику надсилати задавані функції адміністратору пристрою. Ніколи не застосовується для звичайних програм."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"додавати чи вилучати адміністраторів пристрою"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Дозволяє власнику додавати чи вилучати активних адміністраторів пристрою. Ніколи не застосовується для звичайних програм."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"змінювати орієнтацію екрана"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 8c424c3..ea0ef68 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Cho phép chủ sở hữu liên kết với giao diện cấp cao nhất của dịch vụ tiện ích con. Không cần thiết cho các ứng dụng thông thường."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"tương tác với quản trị viên thiết bị"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Cho phép chủ sở hữu gửi các ý định đến quản trị viên thiết bị. Không cần thiết cho các ứng dụng thông thường."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"thêm hoặc xóa quản trị viên thiết bị"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Cho phép chủ sở hữu thêm hoặc xóa quản trị viên thiết bị đang hoạt động. Không cần thiết cho các ứng dụng thông thường."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"thay đổi hướng màn hình"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index acb4a81..73f2b8d 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"允许应用绑定到小部件服务的顶级接口。普通应用绝不需要此权限。"</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"与设备管理器交互"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"允许用户将意向发送给设备管理员。普通应用绝不需要此权限。"</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"添加或删除设备管理员"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"允许应用添加或删除有效的设备管理员。普通应用绝不需要此权限。"</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"更改屏幕显示方向"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index deb5a11..fa499d9 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"允許應用程式繫結至小工具服務的頂層介面 (不建議一般應用程式使用)。"</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"與裝置管理員互動"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"允許應用程式將調用請求傳送至裝置管理員 (不建議一般應用程式使用)。"</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"新增或移除裝置管理員"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"允許應用程式新增或移除有效的裝置管理員 (不建議一般應用程式使用)。"</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"更改屏幕瀏覽方向"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index b058860..6bf2593 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"允許應用程式繫結至小工具服務的頂層介面 (一般應用程式不需使用)。"</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"與裝置管理員互動"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"允許應用程式將調用請求傳送至裝置管理員 (一般應用程式不需使用)。"</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"新增或移除裝置管理員"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"允許應用程式新增或移除有效的裝置管理員 (一般應用程式並不需要)。"</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"變更螢幕顯示方向"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index aacd3c1..1359dd9 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -384,6 +384,10 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Ivumela umbambi ukuhlanganisa uxhumano nomsebenzisi kwezinga eliphezulu lensizakalo yesinqunjwana. Akusoze kwadingeka kwezinhlelo zokusebenza ezivamile."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"xhumana nomphathi wedivaysi"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Ivumela ummeli ukuthumela okuqukethwe kumphathi wedivaysi. Akusoze kwadingeka kwizinhlelo zokusebenza ezivamile."</string>
+ <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+ <skip />
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"engeza noma susa umlawuli wedivayisi"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Ivumela umnikazi ukuthi angeze noma asuse abalawuli bedivayisi esebenzayo. Akumele idingelwe izinhlelo zokusebenza ezijwayelekile."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"shintsha ukujikeleza kwesikrini"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index fbe066a..d5e78a5 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1370,7 +1370,7 @@
</string-array>
<string-array name="config_notificationScorers">
- <item>com.android.internal.notification.DemoContactNotificationScorer</item>
+ <item>com.android.internal.notification.PeopleNotificationScorer</item>
</string-array>
<!-- Flag indicating that this device does not rotate and will always remain in its default
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 4a121d1..6266393 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -830,6 +830,20 @@
user consent.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_retrieveWindowToken">retrieve window token</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_retrieveWindowToken">Allows an application to retrieve
+ the window token. Malicious apps may perfrom unauthorized interaction with
+ the application window impersonating the system.</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_frameStats">retrieve frame statistics</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_frameStats">Allows an application to collect
+ frame statistics. Malicious apps may observe the frame statistics
+ of windows from other apps.</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_filter_events">filter events</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_filter_events">Allows an application to register an input filter
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 6c0b722..28b92019 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -17,8 +17,8 @@
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.res.Resources;
-import android.content.res.TypedArray;
import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
@@ -30,7 +30,6 @@
import android.graphics.Region;
import android.util.AttributeSet;
import android.util.Log;
-import android.util.Xml;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
@@ -39,7 +38,6 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlPullParserFactory;
import java.io.IOException;
import java.util.ArrayList;
@@ -47,6 +45,7 @@
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
+
/**
* This lets you create a drawable based on an XML vector graphic
* It can be defined in an XML file with the <code><vector></code> element.
@@ -172,7 +171,8 @@
private static final int DEFAULT_DURATION = 1000;
private static final long DEFAULT_INFINITE_DURATION = 60 * 60 * 1000;
- private VectorDrawableState mVectorState;
+ private final VectorDrawableState mVectorState;
+
private int mAlpha = 0xFF;
public VectorDrawable() {
@@ -282,14 +282,17 @@
@Override
protected boolean onStateChange(int[] state) {
+ super.onStateChange(state);
+
mVectorState.mVAnimatedPath.setState(state);
- int direction = mVectorState.mVAnimatedPath.getTrigger(state);
- if (direction>0) {
+
+ final int direction = mVectorState.mVAnimatedPath.getTrigger(state);
+ if (direction > 0) {
animateForward();
- } else if (direction<0) {
+ } else if (direction < 0) {
animateBackward();
}
- super.onStateChange(state);
+
invalidateSelf();
return true;
}
@@ -310,7 +313,11 @@
@Override
public void draw(Canvas canvas) {
- mVectorState.mVAnimatedPath.draw(canvas);
+ final int saveCount = canvas.save();
+ final Rect bounds = getBounds();
+ canvas.translate(bounds.left, bounds.top);
+ mVectorState.mVAnimatedPath.draw(canvas, bounds.width(), bounds.height());
+ canvas.restoreToCount(saveCount);
}
@Override
@@ -327,10 +334,6 @@
// TODO: support color filter
}
- /**
- * Returns a {@link android.graphics.PixelFormat graphics.PixelFormat}
- * value of TRANSLUCENT.
- */
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
@@ -364,38 +367,14 @@
invalidateSelf();
}
- /**
- * Sets the intrinsic (default) width for this shape.
- *
- * @param width the intrinsic width (in pixels)
- */
- public void setIntrinsicWidth(int width) {
- if (mVectorState.mIntrinsicWidth != width) {
- mVectorState.mIntrinsicWidth = width;
- invalidateSelf();
- }
- }
-
- /**
- * Sets the intrinsic (default) height for this shape.
- *
- * @param height the intrinsic height (in pixels)
- */
- public void setIntrinsicHeight(int height) {
- if (mVectorState.mIntrinsicHeight != height) {
- mVectorState.mIntrinsicHeight = height;
- invalidateSelf();
- }
- }
-
@Override
public int getIntrinsicWidth() {
- return mVectorState.mIntrinsicWidth;
+ return (int) mVectorState.mVAnimatedPath.mBaseWidth;
}
@Override
public int getIntrinsicHeight() {
- return mVectorState.mIntrinsicHeight;
+ return (int) mVectorState.mVAnimatedPath.mBaseHeight;
}
@Override
@@ -408,25 +387,6 @@
}
}
- /** @hide */
- public static VectorDrawable create(Resources resources, int rid) {
- try {
- VectorDrawable drawable = new VectorDrawable();
- XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
- factory.setNamespaceAware(true);
- XmlPullParser xpp = resources.getXml(rid);
- AttributeSet attrs = Xml.asAttributeSet(xpp);
- drawable.inflate(resources, xpp, attrs);
- drawable.setAnimationFraction(0);
- return drawable;
- } catch (XmlPullParserException e) {
- Log.e(LOGTAG, "parser error", e);
- } catch (IOException e) {
- Log.e(LOGTAG, "parser error", e);
- }
- return null;
- }
-
@Override
public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme)
throws XmlPullParserException, IOException {
@@ -543,9 +503,6 @@
private void setAnimatedPath(VAnimatedPath animatedPath) {
mVectorState.mVAnimatedPath = animatedPath;
- setIntrinsicWidth((int) mVectorState.mVAnimatedPath.mBaseWidth);
- setIntrinsicHeight((int) mVectorState.mVAnimatedPath.mBaseHeight);
-
long duration = mVectorState.mVAnimatedPath.getTotalAnimationDuration();
if (duration == -1) { // if it set to infinite set to 1 hour
duration = DEFAULT_INFINITE_DURATION; // TODO define correct approach for infinite
@@ -575,18 +532,12 @@
ValueAnimator mBasicAnimator;
VAnimatedPath mVAnimatedPath;
Rect mPadding;
- int mIntrinsicHeight;
- int mIntrinsicWidth;
public VectorDrawableState(VectorDrawableState copy) {
if (copy != null) {
mChangingConfigurations = copy.mChangingConfigurations;
mVAnimatedPath = new VAnimatedPath(copy.mVAnimatedPath);
mPadding = new Rect(copy.mPadding);
- mIntrinsicHeight = copy.mIntrinsicHeight;
- mIntrinsicWidth = copy.mIntrinsicWidth;
- } else {
- mVAnimatedPath = new VAnimatedPath();
}
}
@@ -612,17 +563,31 @@
}
private static class VAnimatedPath {
- private ArrayList<VAnimation> mCurrentAnimList = null;
+ private static final int [] TRIGGER_MAP = {
+ 0,
+ R.attr.state_pressed,
+ R.attr.state_focused,
+ R.attr.state_hovered,
+ R.attr.state_selected,
+ R.attr.state_checkable,
+ R.attr.state_checked,
+ R.attr.state_activated,
+ R.attr.state_focused
+ };
+
+ private final Path mPath = new Path();
+ private final Path mRenderPath = new Path();
+ private final Matrix mMatrix = new Matrix();
+
+ private ArrayList<VAnimation> mCurrentAnimList;
private VPath[] mCurrentPaths;
- private float mAnimationValue = 0; // value goes from 0 to 1
- private Paint mStrokePaint = null;
- private Paint mFillPaint = null;
+ private Paint mStrokePaint;
+ private Paint mFillPaint;
private PathMeasure mPathMeasure;
- private Path mPath = new Path();
- private Path mRenderPath = new Path();
- private Matrix mMatrix = new Matrix();
- private long mTotalDuration;
+
private int[] mCurrentState = new int[0];
+ private float mAnimationValue;
+ private long mTotalDuration;
private int mTrigger;
private boolean mTriggerState;
@@ -634,11 +599,9 @@
float mViewportHeight;
public VAnimatedPath() {
- setup();
}
public VAnimatedPath(VAnimatedPath copy) {
- setup();
mCurrentAnimList = new ArrayList<VAnimation>(copy.mCurrentAnimList);
mGroupList.addAll(copy.mGroupList);
if (copy.mCurrentPaths != null) {
@@ -703,28 +666,7 @@
}
public void setTrigger(int trigger){
- final int [] lut = {
- 0,
- R.attr.state_pressed,
- R.attr.state_focused,
- R.attr.state_hovered,
- R.attr.state_selected,
- R.attr.state_checkable,
- R.attr.state_checked,
- R.attr.state_activated,
- R.attr.state_focused
- };
-
- mTrigger = lut[trigger];
- }
-
- private void setup(){
- mStrokePaint = new Paint();
- mStrokePaint.setStyle(Paint.Style.STROKE);
- mStrokePaint.setAntiAlias(true);
- mFillPaint = new Paint();
- mFillPaint.setStyle(Paint.Style.FILL);
- mFillPaint.setAntiAlias(true);
+ mTrigger = VAnimatedPath.getStateForTrigger(trigger);
}
public long getTotalAnimationDuration() {
@@ -780,16 +722,12 @@
}
}
- public void draw(Canvas canvas) {
+ public void draw(Canvas canvas, int w, int h) {
if (mCurrentPaths == null) {
Log.e(LOGTAG,"mCurrentPaths == null");
return;
}
- // TODO: This should probably use getBounds().
- final int w = canvas.getWidth();
- final int h = canvas.getHeight();
-
for (int i = 0; i < mCurrentPaths.length; i++) {
if (mCurrentPaths[i] != null && mCurrentPaths[i].isVisible(mCurrentState)) {
drawPath(mCurrentPaths[i], canvas, w, h);
@@ -801,7 +739,7 @@
final float scale = Math.min(h / mViewportHeight, w / mViewportWidth);
vPath.toPath(mPath);
- Path path = mPath;
+ final Path path = mPath;
if (vPath.mTrimPathStart != 0.0f || vPath.mTrimPathEnd != 1.0f) {
float start = (vPath.mTrimPathStart + vPath.mTrimPathOffset) % 1.0f;
@@ -839,24 +777,36 @@
}
if (vPath.mFillColor != 0) {
+ if (mFillPaint == null) {
+ mFillPaint = new Paint();
+ mFillPaint.setStyle(Paint.Style.FILL);
+ mFillPaint.setAntiAlias(true);
+ }
+
mFillPaint.setColor(vPath.mFillColor);
- int alpha = 0xFF & (vPath.mFillColor >> 24);
- mFillPaint.setAlpha(alpha);
canvas.drawPath(mRenderPath, mFillPaint);
}
if (vPath.mStrokeColor != 0) {
+ if (mStrokePaint == null) {
+ mStrokePaint = new Paint();
+ mStrokePaint.setStyle(Paint.Style.STROKE);
+ mStrokePaint.setAntiAlias(true);
+ }
+
+ final Paint strokePaint = mStrokePaint;
if (vPath.mStrokeLineJoin != null) {
- mStrokePaint.setStrokeJoin(vPath.mStrokeLineJoin);
+ strokePaint.setStrokeJoin(vPath.mStrokeLineJoin);
}
+
if (vPath.mStrokeLineCap != null) {
- mStrokePaint.setStrokeCap(vPath.mStrokeLineCap);
+ strokePaint.setStrokeCap(vPath.mStrokeLineCap);
}
- mStrokePaint.setStrokeMiter(vPath.mStrokeMiterlimit * scale);
- mStrokePaint.setColor(vPath.mStrokeColor);
- mStrokePaint.setAlpha(0xFF & (vPath.mStrokeColor >> 24));
- mStrokePaint.setStrokeWidth(vPath.mStrokeWidth * scale);
- canvas.drawPath(mRenderPath, mStrokePaint);
+
+ strokePaint.setStrokeMiter(vPath.mStrokeMiterlimit * scale);
+ strokePaint.setColor(vPath.mStrokeColor);
+ strokePaint.setStrokeWidth(vPath.mStrokeWidth * scale);
+ canvas.drawPath(mRenderPath, strokePaint);
}
}
@@ -926,7 +876,7 @@
private void parseViewport(Resources r, AttributeSet attrs)
throws XmlPullParserException {
- TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableViewport);
+ final TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableViewport);
mViewportWidth = a.getFloat(R.styleable.VectorDrawableViewport_viewportWidth, 0);
mViewportHeight = a.getFloat(R.styleable.VectorDrawableViewport_viewportHeight, 0);
if (mViewportWidth == 0 || mViewportHeight == 0) {
@@ -938,7 +888,7 @@
private void parseSize(Resources r, AttributeSet attrs)
throws XmlPullParserException {
- TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableSize);
+ final TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableSize);
mBaseWidth = a.getDimension(R.styleable.VectorDrawableSize_width, 0);
mBaseHeight = a.getDimension(R.styleable.VectorDrawableSize_height, 0);
if (mBaseWidth == 0 || mBaseHeight == 0) {
@@ -947,6 +897,10 @@
}
a.recycle();
}
+
+ private static final int getStateForTrigger(int trigger) {
+ return TRIGGER_MAP[trigger];
+ }
}
private static class VAnimation {
@@ -1324,8 +1278,8 @@
boolean mAnimated = false;
boolean mClip = false;
- Paint.Cap mStrokeLineCap = null;
- Paint.Join mStrokeLineJoin = null;
+ Paint.Cap mStrokeLineCap = Paint.Cap.BUTT;
+ Paint.Join mStrokeLineJoin = Paint.Join.MITER;
float mStrokeMiterlimit = 4;
private VNode[] mNode = null;
@@ -1775,32 +1729,29 @@
return returnPath;
}
- private static int rgbInterpolate(float t, int color1, int color2) {
- int ret;
- if (color1 == color2) {
- return color2;
- }
- if (color1 == 0) {
- return color2;
- }
- if (color2 == 0) {
- return color1;
+ private static int rgbInterpolate(float fraction, int startColor, int endColor) {
+ if (startColor == endColor) {
+ return startColor;
+ } else if (startColor == 0) {
+ return endColor;
+ } else if (endColor == 0) {
+ return startColor;
}
- float t1 = 1 - t;
- ret = 0xFF & (((int) ((color1 & 0xFF) * t1 + (color2 & 0xFF) * t)));
- color1 >>= 8;
- color2 >>= 8;
+ final int startA = (startColor >> 24) & 0xff;
+ final int startR = (startColor >> 16) & 0xff;
+ final int startG = (startColor >> 8) & 0xff;
+ final int startB = startColor & 0xff;
- ret |= 0xFF00 & (((int) ((color1 & 0xFF) * t1 + (color2 & 0xFF) * t)) << 8);
- color1 >>= 8;
- color2 >>= 8;
- ret |= 0xFF0000 & (((int) ((color1 & 0xFF) * t1 + (color2 & 0xFF) * t)) << 16);
- color1 >>= 8;
- color2 >>= 8;
- ret |= 0xFF000000 & (((int) ((color1 & 0xFF) * t1 + (color2 & 0xFF) * t)) << 24);
+ final int endA = (endColor >> 24) & 0xff;
+ final int endR = (endColor >> 16) & 0xff;
+ final int endG = (endColor >> 8) & 0xff;
+ final int endB = endColor & 0xff;
- return ret;
+ return ((startA + (int)(fraction * (endA - startA))) << 24) |
+ ((startR + (int)(fraction * (endR - startR))) << 16) |
+ ((startG + (int)(fraction * (endG - startG))) << 8) |
+ ((startB + (int)(fraction * (endB - startB))));
}
public boolean isVisible(int[] state) {
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index f68d1a9..48ef9db 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -30,6 +30,7 @@
import android.content.res.ObbInfo;
import android.content.res.ObbScanner;
import android.net.Uri;
+import android.os.Build;
import android.os.Environment;
import android.os.Environment.UserEnvironment;
import android.os.FileUtils;
@@ -341,11 +342,13 @@
// The .apk file
String codePath = packageURI.getPath();
File codeFile = new File(codePath);
+ NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(codePath);
+ final int abi = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_ABIS);
// Calculate size of container needed to hold base APK.
final int sizeMb;
try {
- sizeMb = calculateContainerSize(codeFile, isForwardLocked);
+ sizeMb = calculateContainerSize(handle, codeFile, abi, isForwardLocked);
} catch (IOException e) {
Slog.w(TAG, "Problem when trying to copy " + codeFile.getPath());
return null;
@@ -408,7 +411,14 @@
final File sharedLibraryDir = new File(newCachePath, LIB_DIR_NAME);
if (sharedLibraryDir.mkdir()) {
- int ret = NativeLibraryHelper.copyNativeBinariesIfNeededLI(codeFile, sharedLibraryDir);
+ int ret = PackageManager.INSTALL_SUCCEEDED;
+ if (abi >= 0) {
+ ret = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle,
+ sharedLibraryDir, Build.SUPPORTED_ABIS[abi]);
+ } else if (abi != PackageManager.NO_NATIVE_LIBRARIES) {
+ ret = abi;
+ }
+
if (ret != PackageManager.INSTALL_SUCCEEDED) {
Slog.e(TAG, "Could not copy native libraries to " + sharedLibraryDir.getPath());
PackageHelper.destroySdDir(newCid);
@@ -822,6 +832,17 @@
return availSdMb > sizeMb;
}
+ private int calculateContainerSize(File apkFile, boolean forwardLocked) throws IOException {
+ NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(apkFile);
+ final int abi = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_ABIS);
+
+ try {
+ return calculateContainerSize(handle, apkFile, abi, forwardLocked);
+ } finally {
+ handle.close();
+ }
+ }
+
/**
* Calculate the container size for an APK. Takes into account the
*
@@ -829,7 +850,8 @@
* @return size in megabytes (2^20 bytes)
* @throws IOException when there is a problem reading the file
*/
- private int calculateContainerSize(File apkFile, boolean forwardLocked) throws IOException {
+ private int calculateContainerSize(NativeLibraryHelper.ApkHandle apkHandle,
+ File apkFile, int abiIndex, boolean forwardLocked) throws IOException {
// Calculate size of container needed to hold base APK.
long sizeBytes = apkFile.length();
if (sizeBytes == 0 && !apkFile.exists()) {
@@ -838,7 +860,10 @@
// Check all the native files that need to be copied and add that to the
// container size.
- sizeBytes += NativeLibraryHelper.sumNativeBinariesLI(apkFile);
+ if (abiIndex >= 0) {
+ sizeBytes += NativeLibraryHelper.sumNativeBinariesLI(apkHandle,
+ Build.SUPPORTED_ABIS[abiIndex]);
+ }
if (forwardLocked) {
sizeBytes += PackageHelper.extractPublicFiles(apkFile.getPath(), null);
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 19286c8..e1c17cb 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -87,6 +87,8 @@
<uses-permission android:name="android.permission.MANAGE_USERS" />
<uses-permission android:name="android.permission.BLUETOOTH_STACK" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
+ <uses-permission android:name="android.permission.RETRIEVE_WINDOW_TOKEN" />
+ <uses-permission android:name="android.permission.RENDER_STATS" />
<application android:label="@string/app_label">
<provider
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index c3db55e..53ac063 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -132,6 +132,8 @@
private static final String TEMPORARY_ENABLE_ACCESSIBILITY_UNTIL_KEYGUARD_REMOVED =
"temporaryEnableAccessibilityStateUntilKeyguardRemoved";
+ private static final String GET_WINDOW_TOKEN = "getWindowToken";
+
private static final ComponentName sFakeAccessibilityServiceComponentName =
new ComponentName("foo.bar", "FakeService");
@@ -360,6 +362,7 @@
}, UserHandle.ALL, intentFilter, null, null);
}
+ @Override
public int addClient(IAccessibilityManagerClient client, int userId) {
synchronized (mLock) {
final int resolvedUserId = mSecurityPolicy
@@ -388,6 +391,7 @@
}
}
+ @Override
public boolean sendAccessibilityEvent(AccessibilityEvent event, int userId) {
synchronized (mLock) {
final int resolvedUserId = mSecurityPolicy
@@ -412,6 +416,7 @@
return (OWN_PROCESS_ID != Binder.getCallingPid());
}
+ @Override
public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(int userId) {
synchronized (mLock) {
final int resolvedUserId = mSecurityPolicy
@@ -430,6 +435,7 @@
}
}
+ @Override
public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType,
int userId) {
List<AccessibilityServiceInfo> result = null;
@@ -463,6 +469,7 @@
return result;
}
+ @Override
public void interrupt(int userId) {
CopyOnWriteArrayList<Service> services;
synchronized (mLock) {
@@ -485,6 +492,7 @@
}
}
+ @Override
public int addAccessibilityInteractionConnection(IWindow windowToken,
IAccessibilityInteractionConnection connection, int userId) throws RemoteException {
synchronized (mLock) {
@@ -521,6 +529,7 @@
}
}
+ @Override
public void removeAccessibilityInteractionConnection(IWindow window) {
synchronized (mLock) {
mSecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked(
@@ -570,6 +579,7 @@
return -1;
}
+ @Override
public void registerUiTestAutomationService(IBinder owner,
IAccessibilityServiceClient serviceClient,
AccessibilityServiceInfo accessibilityServiceInfo) {
@@ -612,6 +622,7 @@
}
}
+ @Override
public void unregisterUiTestAutomationService(IAccessibilityServiceClient serviceClient) {
synchronized (mLock) {
UserState userState = getCurrentUserStateLocked();
@@ -630,6 +641,7 @@
}
}
+ @Override
public void temporaryEnableAccessibilityStateUntilKeyguardRemoved(
ComponentName service, boolean touchExplorationEnabled) {
mSecurityPolicy.enforceCallingPermission(
@@ -662,6 +674,29 @@
}
}
+ @Override
+ public IBinder getWindowToken(int windowId) {
+ mSecurityPolicy.enforceCallingPermission(
+ Manifest.permission.RETRIEVE_WINDOW_TOKEN,
+ GET_WINDOW_TOKEN);
+ synchronized (mLock) {
+ final int resolvedUserId = mSecurityPolicy
+ .resolveCallingUserIdEnforcingPermissionsLocked(
+ UserHandle.getCallingUserId());
+ if (resolvedUserId != mCurrentUserId) {
+ return null;
+ }
+ if (mSecurityPolicy.findWindowById(windowId) == null) {
+ return null;
+ }
+ IBinder token = mGlobalWindowTokens.get(windowId);
+ if (token != null) {
+ return token;
+ }
+ return getCurrentUserStateLocked().mWindowTokens.get(windowId);
+ }
+ }
+
boolean onGesture(int gestureId) {
synchronized (mLock) {
boolean handled = notifyGestureLocked(gestureId, false);
@@ -689,7 +724,7 @@
* @param outBounds The output to which to write the focus bounds.
* @return Whether accessibility focus was found and the bounds are populated.
*/
- // TODO: (multi-display) Make sure this works for multiple displays.
+ // TODO: (multi-display) Make sure this works for multiple displays.
boolean getAccessibilityFocusBoundsInActiveWindow(Rect outBounds) {
// Instead of keeping track of accessibility focus events per
// window to be able to find the focus in the active window,
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index b6e761c..7ec9b82 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -52,6 +52,7 @@
import android.os.storage.IMountShutdownObserver;
import android.os.storage.IObbActionListener;
import android.os.storage.OnObbStateChangeListener;
+import android.os.storage.StorageManager;
import android.os.storage.StorageResultCode;
import android.os.storage.StorageVolume;
import android.text.TextUtils;
@@ -2145,8 +2146,8 @@
}
}
- public int encryptStorage(String password) {
- if (TextUtils.isEmpty(password)) {
+ public int encryptStorage(int type, String password) {
+ if (TextUtils.isEmpty(password) && type != StorageManager.CRYPT_TYPE_DEFAULT) {
throw new IllegalArgumentException("password cannot be empty");
}
@@ -2160,7 +2161,7 @@
}
try {
- mConnector.execute("cryptfs", "enablecrypto", "inplace",
+ mConnector.execute("cryptfs", "enablecrypto", "inplace", CRYPTO_TYPES[type],
new SensitiveArg(toHex(password)));
} catch (NativeDaemonConnectorException e) {
// Encryption failed
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5bfb3fb..7607419 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2756,11 +2756,16 @@
debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
}
+ String requiredAbi = app.info.requiredCpuAbi;
+ if (requiredAbi == null) {
+ requiredAbi = Build.SUPPORTED_ABIS[0];
+ }
+
// Start the process. It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
app.processName, uid, uid, gids, debugFlags, mountExternal,
- app.info.targetSdkVersion, app.info.seinfo, null);
+ app.info.targetSdkVersion, app.info.seinfo, requiredAbi, null);
BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
synchronized (bs) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index ff90cae..747d0a7 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -60,8 +60,8 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
-import android.content.ServiceConnection;
import android.content.IntentSender.SendIntentException;
+import android.content.ServiceConnection;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.ContainerEncryptionParams;
@@ -74,14 +74,15 @@
import android.content.pm.IPackageMoveObserver;
import android.content.pm.IPackageStatsObserver;
import android.content.pm.InstrumentationInfo;
+import android.content.pm.ManifestDigest;
import android.content.pm.PackageCleanItem;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInfoLite;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
-import android.content.pm.PackageUserState;
import android.content.pm.PackageParser.ActivityIntentInfo;
import android.content.pm.PackageStats;
+import android.content.pm.PackageUserState;
import android.content.pm.ParceledListSlice;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
@@ -89,7 +90,6 @@
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.Signature;
-import android.content.pm.ManifestDigest;
import android.content.pm.VerificationParams;
import android.content.pm.VerifierDeviceIdentity;
import android.content.pm.VerifierInfo;
@@ -100,6 +100,7 @@
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
+import android.os.Environment.UserEnvironment;
import android.os.FileObserver;
import android.os.FileUtils;
import android.os.Handler;
@@ -116,7 +117,6 @@
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
-import android.os.Environment.UserEnvironment;
import android.os.UserManager;
import android.security.KeyStore;
import android.security.SystemKeyStore;
@@ -2054,6 +2054,7 @@
pkg.applicationInfo.dataDir =
getDataPathForPackage(packageName, 0).getPath();
pkg.applicationInfo.nativeLibraryDir = ps.nativeLibraryPathString;
+ pkg.applicationInfo.requiredCpuAbi = ps.requiredCpuAbiString;
}
return generatePackageInfo(pkg, flags, userId);
}
@@ -3994,6 +3995,8 @@
codePath = pkg.mScanPath;
// Set application objects path explicitly.
setApplicationInfoPaths(pkg, codePath, resPath);
+ // Applications can run with the primary Cpu Abi unless otherwise is specified
+ pkg.applicationInfo.requiredCpuAbi = null;
// Note that we invoke the following method only if we are about to unpack an application
PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanMode
| SCAN_UPDATE_SIGNATURE, currentTime, user);
@@ -4565,6 +4568,7 @@
// the PkgSetting exists already and doesn't have to be created.
pkgSetting = mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile,
destResourceFile, pkg.applicationInfo.nativeLibraryDir,
+ pkg.applicationInfo.requiredCpuAbi,
pkg.applicationInfo.flags, user, false);
if (pkgSetting == null) {
Slog.w(TAG, "Creating application package " + pkg.packageName + " failed");
@@ -4870,11 +4874,20 @@
}
try {
- if (copyNativeLibrariesForInternalApp(scanFile, nativeLibraryDir) != PackageManager.INSTALL_SUCCEEDED) {
+ int copyRet = copyNativeLibrariesForInternalApp(scanFile, nativeLibraryDir);
+ if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
Slog.e(TAG, "Unable to copy native libraries");
mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
return null;
}
+
+ // We've successfully copied native libraries across, so we make a
+ // note of what ABI we're using
+ if (copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
+ pkg.applicationInfo.requiredCpuAbi = Build.SUPPORTED_ABIS[copyRet];
+ } else {
+ pkg.applicationInfo.requiredCpuAbi = null;
+ }
} catch (IOException e) {
Slog.e(TAG, "Unable to copy native libraries", e);
mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
@@ -5430,7 +5443,21 @@
* If this is an internal application or our nativeLibraryPath points to
* the app-lib directory, unpack the libraries if necessary.
*/
- return NativeLibraryHelper.copyNativeBinariesIfNeededLI(scanFile, nativeLibraryDir);
+ final NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(scanFile);
+ try {
+ int abi = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_ABIS);
+ if (abi >= 0) {
+ int copyRet = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle,
+ nativeLibraryDir, Build.SUPPORTED_ABIS[abi]);
+ if (copyRet != PackageManager.INSTALL_SUCCEEDED) {
+ return copyRet;
+ }
+ }
+
+ return abi;
+ } finally {
+ handle.close();
+ }
}
private void killApplication(String pkgName, int appId, String reason) {
@@ -8384,7 +8411,7 @@
}
try {
int copyRet = copyNativeLibrariesForInternalApp(codeFile, nativeLibraryFile);
- if (copyRet != PackageManager.INSTALL_SUCCEEDED) {
+ if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
return copyRet;
}
} catch (IOException e) {
@@ -11898,8 +11925,17 @@
final File newNativeDir = new File(newNativePath);
if (!isForwardLocked(pkg) && !isExternal(pkg)) {
- NativeLibraryHelper.copyNativeBinariesIfNeededLI(
- new File(newCodePath), newNativeDir);
+ // NOTE: We do not report any errors from the APK scan and library
+ // copy at this point.
+ NativeLibraryHelper.ApkHandle handle =
+ new NativeLibraryHelper.ApkHandle(newCodePath);
+ final int abi = NativeLibraryHelper.findSupportedAbi(
+ handle, Build.SUPPORTED_ABIS);
+ if (abi >= 0) {
+ NativeLibraryHelper.copyNativeBinariesIfNeededLI(
+ handle, newNativeDir, Build.SUPPORTED_ABIS[abi]);
+ }
+ handle.close();
}
final int[] users = sUserManager.getUserIds();
for (int user : users) {
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index b447861..15df3d2 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -30,8 +30,8 @@
SharedUserSetting sharedUser;
PackageSetting(String name, String realName, File codePath, File resourcePath,
- String nativeLibraryPathString, int pVersionCode, int pkgFlags) {
- super(name, realName, codePath, resourcePath, nativeLibraryPathString, pVersionCode,
+ String nativeLibraryPathString, String requiredCpuAbiString, int pVersionCode, int pkgFlags) {
+ super(name, realName, codePath, resourcePath, nativeLibraryPathString, requiredCpuAbiString, pVersionCode,
pkgFlags);
}
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 2a5698b9..c8af9d1 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -50,6 +50,7 @@
File resourcePath;
String resourcePathString;
String nativeLibraryPathString;
+ String requiredCpuAbiString;
long timeStamp;
long firstInstallTime;
long lastUpdateTime;
@@ -77,11 +78,11 @@
/* package name of the app that installed this package */
String installerPackageName;
PackageSettingBase(String name, String realName, File codePath, File resourcePath,
- String nativeLibraryPathString, int pVersionCode, int pkgFlags) {
+ String nativeLibraryPathString, String requiredCpuAbiString, int pVersionCode, int pkgFlags) {
super(pkgFlags);
this.name = name;
this.realName = realName;
- init(codePath, resourcePath, nativeLibraryPathString, pVersionCode);
+ init(codePath, resourcePath, nativeLibraryPathString, requiredCpuAbiString, pVersionCode);
}
/**
@@ -98,6 +99,7 @@
resourcePath = base.resourcePath;
resourcePathString = base.resourcePathString;
nativeLibraryPathString = base.nativeLibraryPathString;
+ requiredCpuAbiString = base.requiredCpuAbiString;
timeStamp = base.timeStamp;
firstInstallTime = base.firstInstallTime;
lastUpdateTime = base.lastUpdateTime;
@@ -125,12 +127,13 @@
}
void init(File codePath, File resourcePath, String nativeLibraryPathString,
- int pVersionCode) {
+ String requiredCpuAbiString, int pVersionCode) {
this.codePath = codePath;
this.codePathString = codePath.toString();
this.resourcePath = resourcePath;
this.resourcePathString = resourcePath.toString();
this.nativeLibraryPathString = nativeLibraryPathString;
+ this.requiredCpuAbiString = requiredCpuAbiString;
this.versionCode = pVersionCode;
}
@@ -161,6 +164,7 @@
grantedPermissions = base.grantedPermissions;
gids = base.gids;
+ requiredCpuAbiString = base.requiredCpuAbiString;
timeStamp = base.timeStamp;
firstInstallTime = base.firstInstallTime;
lastUpdateTime = base.lastUpdateTime;
diff --git a/services/core/java/com/android/server/pm/PendingPackage.java b/services/core/java/com/android/server/pm/PendingPackage.java
index c17cc46..36c3a34 100644
--- a/services/core/java/com/android/server/pm/PendingPackage.java
+++ b/services/core/java/com/android/server/pm/PendingPackage.java
@@ -22,8 +22,8 @@
final int sharedId;
PendingPackage(String name, String realName, File codePath, File resourcePath,
- String nativeLibraryPathString, int sharedId, int pVersionCode, int pkgFlags) {
- super(name, realName, codePath, resourcePath, nativeLibraryPathString, pVersionCode,
+ String nativeLibraryPathString, String requiredCpuAbiString, int sharedId, int pVersionCode, int pkgFlags) {
+ super(name, realName, codePath, resourcePath, nativeLibraryPathString, requiredCpuAbiString, pVersionCode,
pkgFlags);
this.sharedId = sharedId;
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index d1e34a1..80f716c 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -217,10 +217,10 @@
PackageSetting getPackageLPw(PackageParser.Package pkg, PackageSetting origPackage,
String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
- String nativeLibraryPathString, int pkgFlags, UserHandle user, boolean add) {
+ String nativeLibraryPathString, String requiredCpuAbiString, int pkgFlags, UserHandle user, boolean add) {
final String name = pkg.packageName;
PackageSetting p = getPackageLPw(name, origPackage, realName, sharedUser, codePath,
- resourcePath, nativeLibraryPathString, pkg.mVersionCode, pkgFlags,
+ resourcePath, nativeLibraryPathString, requiredCpuAbiString, pkg.mVersionCode, pkgFlags,
user, add, true /* allowInstall */);
return p;
}
@@ -302,7 +302,7 @@
p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
}
PackageSetting ret = addPackageLPw(name, p.realName, p.codePath, p.resourcePath,
- p.nativeLibraryPathString, p.appId, p.versionCode, p.pkgFlags);
+ p.nativeLibraryPathString, p.requiredCpuAbiString, p.appId, p.versionCode, p.pkgFlags);
mDisabledSysPackages.remove(name);
return ret;
}
@@ -316,7 +316,7 @@
}
PackageSetting addPackageLPw(String name, String realName, File codePath, File resourcePath,
- String nativeLibraryPathString, int uid, int vc, int pkgFlags) {
+ String nativeLibraryPathString, String requiredCpuAbiString, int uid, int vc, int pkgFlags) {
PackageSetting p = mPackages.get(name);
if (p != null) {
if (p.appId == uid) {
@@ -326,7 +326,7 @@
"Adding duplicate package, keeping first: " + name);
return null;
}
- p = new PackageSetting(name, realName, codePath, resourcePath, nativeLibraryPathString,
+ p = new PackageSetting(name, realName, codePath, resourcePath, nativeLibraryPathString, requiredCpuAbiString,
vc, pkgFlags);
p.appId = uid;
if (addUserIdLPw(uid, p, name)) {
@@ -395,10 +395,11 @@
private PackageSetting getPackageLPw(String name, PackageSetting origPackage,
String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
- String nativeLibraryPathString, int vc, int pkgFlags,
+ String nativeLibraryPathString, String requiredCpuAbiString, int vc, int pkgFlags,
UserHandle installUser, boolean add, boolean allowInstall) {
PackageSetting p = mPackages.get(name);
if (p != null) {
+ p.requiredCpuAbiString = requiredCpuAbiString;
if (!p.codePath.equals(codePath)) {
// Check to see if its a disabled system app
if ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) {
@@ -442,7 +443,7 @@
if (origPackage != null) {
// We are consuming the data from an existing package.
p = new PackageSetting(origPackage.name, name, codePath, resourcePath,
- nativeLibraryPathString, vc, pkgFlags);
+ nativeLibraryPathString, requiredCpuAbiString, vc, pkgFlags);
if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG, "Package "
+ name + " is adopting original package " + origPackage.name);
// Note that we will retain the new package's signature so
@@ -459,7 +460,7 @@
p.setTimeStamp(codePath.lastModified());
} else {
p = new PackageSetting(name, realName, codePath, resourcePath,
- nativeLibraryPathString, vc, pkgFlags);
+ nativeLibraryPathString, requiredCpuAbiString, vc, pkgFlags);
p.setTimeStamp(codePath.lastModified());
p.sharedUser = sharedUser;
// If this is not a system app, it starts out stopped.
@@ -585,6 +586,8 @@
&& !nativeLibraryPath.equalsIgnoreCase(p.nativeLibraryPathString)) {
p.nativeLibraryPathString = nativeLibraryPath;
}
+ // Update the required Cpu Abi
+ p.requiredCpuAbiString = pkg.applicationInfo.requiredCpuAbi;
// Update version code if needed
if (pkg.mVersionCode != p.versionCode) {
p.versionCode = pkg.mVersionCode;
@@ -1551,6 +1554,9 @@
if (pkg.nativeLibraryPathString != null) {
serializer.attribute(null, "nativeLibraryPath", pkg.nativeLibraryPathString);
}
+ if (pkg.requiredCpuAbiString != null) {
+ serializer.attribute(null, "requiredCpuAbi", pkg.requiredCpuAbiString);
+ }
if (pkg.sharedUser == null) {
serializer.attribute(null, "userId", Integer.toString(pkg.appId));
} else {
@@ -1593,6 +1599,9 @@
if (pkg.nativeLibraryPathString != null) {
serializer.attribute(null, "nativeLibraryPath", pkg.nativeLibraryPathString);
}
+ if (pkg.requiredCpuAbiString != null) {
+ serializer.attribute(null, "requiredCpuAbi", pkg.requiredCpuAbiString);
+ }
serializer.attribute(null, "flags", Integer.toString(pkg.pkgFlags));
serializer.attribute(null, "ft", Long.toHexString(pkg.timeStamp));
serializer.attribute(null, "it", Long.toHexString(pkg.firstInstallTime));
@@ -1861,7 +1870,7 @@
if (idObj != null && idObj instanceof SharedUserSetting) {
PackageSetting p = getPackageLPw(pp.name, null, pp.realName,
(SharedUserSetting) idObj, pp.codePath, pp.resourcePath,
- pp.nativeLibraryPathString, pp.versionCode, pp.pkgFlags,
+ pp.nativeLibraryPathString, pp.requiredCpuAbiString, pp.versionCode, pp.pkgFlags,
null, true /* add */, false /* allowInstall */);
if (p == null) {
PackageManagerService.reportSettingsProblem(Log.WARN,
@@ -2281,6 +2290,8 @@
String codePathStr = parser.getAttributeValue(null, "codePath");
String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
String nativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath");
+ String requiredCpuAbiString = parser.getAttributeValue(null, "requiredCpuAbi");
+
if (resourcePathStr == null) {
resourcePathStr = codePathStr;
}
@@ -2300,7 +2311,7 @@
pkgFlags |= ApplicationInfo.FLAG_PRIVILEGED;
}
PackageSetting ps = new PackageSetting(name, realName, codePathFile,
- new File(resourcePathStr), nativeLibraryPathStr, versionCode, pkgFlags);
+ new File(resourcePathStr), nativeLibraryPathStr, requiredCpuAbiString, versionCode, pkgFlags);
String timeStampStr = parser.getAttributeValue(null, "ft");
if (timeStampStr != null) {
try {
@@ -2367,6 +2378,7 @@
String codePathStr = null;
String resourcePathStr = null;
String nativeLibraryPathStr = null;
+ String requiredCpuAbiString = null;
String systemStr = null;
String installerPackageName = null;
String uidError = null;
@@ -2386,6 +2398,8 @@
codePathStr = parser.getAttributeValue(null, "codePath");
resourcePathStr = parser.getAttributeValue(null, "resourcePath");
nativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath");
+ requiredCpuAbiString = parser.getAttributeValue(null, "requiredCpuAbi");
+
version = parser.getAttributeValue(null, "version");
if (version != null) {
try {
@@ -2462,7 +2476,7 @@
+ parser.getPositionDescription());
} else if (userId > 0) {
packageSetting = addPackageLPw(name.intern(), realName, new File(codePathStr),
- new File(resourcePathStr), nativeLibraryPathStr, userId, versionCode,
+ new File(resourcePathStr), nativeLibraryPathStr, requiredCpuAbiString, userId, versionCode,
pkgFlags);
if (PackageManagerService.DEBUG_SETTINGS)
Log.i(PackageManagerService.TAG, "Reading package " + name + ": userId="
@@ -2480,7 +2494,7 @@
userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
if (userId > 0) {
packageSetting = new PendingPackage(name.intern(), realName, new File(
- codePathStr), new File(resourcePathStr), nativeLibraryPathStr, userId,
+ codePathStr), new File(resourcePathStr), nativeLibraryPathStr, requiredCpuAbiString, userId,
versionCode, pkgFlags);
packageSetting.setTimeStamp(timeStamp);
packageSetting.firstInstallTime = firstInstallTime;
@@ -2509,6 +2523,7 @@
packageSetting.uidError = "true".equals(uidError);
packageSetting.installerPackageName = installerPackageName;
packageSetting.nativeLibraryPathString = nativeLibraryPathStr;
+ packageSetting.requiredCpuAbiString = requiredCpuAbiString;
// Handle legacy string here for single-user mode
final String enabledStr = parser.getAttributeValue(null, ATTR_ENABLED);
if (enabledStr != null) {
@@ -3008,6 +3023,7 @@
pw.print(prefix); pw.print(" codePath="); pw.println(ps.codePathString);
pw.print(prefix); pw.print(" resourcePath="); pw.println(ps.resourcePathString);
pw.print(prefix); pw.print(" nativeLibraryPath="); pw.println(ps.nativeLibraryPathString);
+ pw.print(prefix); pw.print(" requiredCpuAbi="); pw.println(ps.requiredCpuAbiString);
pw.print(prefix); pw.print(" versionCode="); pw.print(ps.versionCode);
if (ps.pkg != null) {
pw.print(" targetSdk="); pw.print(ps.pkg.applicationInfo.targetSdkVersion);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index b12ae4f..c24f53f 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -24,6 +24,7 @@
import android.util.TimeUtils;
import android.view.IWindowId;
+import android.view.WindowContentFrameStats;
import com.android.internal.app.IBatteryStats;
import com.android.internal.policy.PolicyManager;
import com.android.internal.policy.impl.PhoneWindowManager;
@@ -626,6 +627,8 @@
private final PointerEventDispatcher mPointerEventDispatcher;
+ private WindowContentFrameStats mTempWindowRenderStats;
+
final class DragInputEventReceiver extends InputEventReceiver {
public DragInputEventReceiver(InputChannel inputChannel, Looper looper) {
super(inputChannel, looper);
@@ -10264,6 +10267,51 @@
return mSafeMode;
}
+ @Override
+ public boolean clearWindowContentFrameStats(IBinder token) {
+ if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
+ "clearWindowContentFrameStats()")) {
+ throw new SecurityException("Requires FRAME_STATS permission");
+ }
+ synchronized (mWindowMap) {
+ WindowState windowState = mWindowMap.get(token);
+ if (windowState == null) {
+ return false;
+ }
+ SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl;
+ if (surfaceControl == null) {
+ return false;
+ }
+ return surfaceControl.clearContentFrameStats();
+ }
+ }
+
+ @Override
+ public WindowContentFrameStats getWindowContentFrameStats(IBinder token) {
+ if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
+ "getWindowContentFrameStats()")) {
+ throw new SecurityException("Requires FRAME_STATS permission");
+ }
+ synchronized (mWindowMap) {
+ WindowState windowState = mWindowMap.get(token);
+ if (windowState == null) {
+ return null;
+ }
+ SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl;
+ if (surfaceControl == null) {
+ return null;
+ }
+ if (mTempWindowRenderStats == null) {
+ mTempWindowRenderStats = new WindowContentFrameStats();
+ }
+ WindowContentFrameStats stats = mTempWindowRenderStats;
+ if (!surfaceControl.getContentFrameStats(stats)) {
+ return null;
+ }
+ return stats;
+ }
+ }
+
void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) {
pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
mPolicy.dump(" ", pw, args);
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
index 6ca1aa7..1507058 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
@@ -28,14 +28,14 @@
<path
android:name="check"
android:pathData="m20,200l100,90l180,-180l-35,-35l-145,145l-60,-60l-40,40z"
- android:fill="?android:attr/colorControlActivated" />
+ android:fill="?attr/colorControlActivated" />
</group>
<group>
<path
android:name="box1"
android:pathData="m127,171l37,38l33,-31l-37,-40l-1,3l-2,0l-30,30z"
- android:fill="?android:attr/colorControlActivated"
- android:stroke="?android:attr/colorControlActivated"
+ android:fill="?attr/colorControlActivated"
+ android:stroke="?attr/colorControlActivated"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
</group>
@@ -46,8 +46,8 @@
android:rotation="46.757"
android:pivotX="162"
android:pivotY="173.5"
- android:fill="?attr/android:colorControlNormal"
- android:stroke="?attr/android:colorControlNormal"
+ android:fill="?attr/colorControlNormal"
+ android:stroke="?attr/colorControlNormal"
android:strokeWidth="3"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
@@ -56,7 +56,7 @@
<path
android:name="box3"
android:pathData="m187,147l-1,55l-49,-1l2,-53l48,0z"
- android:stroke="?attr/android:colorControlNormal"
+ android:stroke="?attr/colorControlNormal"
android:strokeWidth="10"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
@@ -65,7 +65,7 @@
<path
android:name="box4"
android:pathData="m248,74l0,164l-177,0l1,-165l173,-1l3,2z"
- android:stroke="?attr/android:colorControlNormal"
+ android:stroke="?attr/colorControlNormal"
android:strokeWidth="30"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 743a26c..1f2342a 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -23,22 +23,11 @@
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
-import android.graphics.Rect;
import android.os.Bundle;
import android.os.IBinder;
import android.os.IRemoteCallback;
import android.os.RemoteException;
import android.util.DisplayMetrics;
-import android.view.Display;
-import android.view.Gravity;
-import android.view.IApplicationToken;
-import android.view.IInputFilter;
-import android.view.IOnKeyguardExitResult;
-import android.view.IRotationWatcher;
-import android.view.IWindowManager;
-import android.view.IWindowSession;
-
-import java.util.List;
/**
* Basic implementation of {@link IWindowManager} so that {@link Display} (and
@@ -462,4 +451,16 @@
// TODO Auto-generated method stub
return false;
}
+
+ @Override
+ public boolean clearWindowContentRenderStats(IBinder token) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public WindowContentFrameStats getWindowContentRenderStats(IBinder token) {
+ // TODO Auto-generated method stub
+ return null;
+ }
}