Merge "UsageStats: Fix issue where initializing data for first time would cause crash"
diff --git a/Android.mk b/Android.mk
index b95ab2e..c5917df 100644
--- a/Android.mk
+++ b/Android.mk
@@ -341,6 +341,7 @@
media/java/android/media/IAudioRoutesObserver.aidl \
media/java/android/media/IMediaHTTPConnection.aidl \
media/java/android/media/IMediaHTTPService.aidl \
+ media/java/android/media/IMediaResourceMonitor.aidl \
media/java/android/media/IMediaRouterClient.aidl \
media/java/android/media/IMediaRouterService.aidl \
media/java/android/media/IMediaScannerListener.aidl \
diff --git a/api/current.txt b/api/current.txt
index 1dcd309..1d251ec 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2750,15 +2750,12 @@
method public android.os.Bundle addAccountFromCredentials(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, android.os.Bundle) throws android.accounts.NetworkErrorException;
method public abstract android.os.Bundle confirmCredentials(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, android.os.Bundle) throws android.accounts.NetworkErrorException;
method public abstract android.os.Bundle editProperties(android.accounts.AccountAuthenticatorResponse, java.lang.String);
- method public android.os.Bundle finishSession(android.accounts.AccountAuthenticatorResponse, java.lang.String, android.os.Bundle) throws android.accounts.NetworkErrorException;
method public android.os.Bundle getAccountCredentialsForCloning(android.accounts.AccountAuthenticatorResponse, android.accounts.Account) throws android.accounts.NetworkErrorException;
method public android.os.Bundle getAccountRemovalAllowed(android.accounts.AccountAuthenticatorResponse, android.accounts.Account) throws android.accounts.NetworkErrorException;
method public abstract android.os.Bundle getAuthToken(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String, android.os.Bundle) throws android.accounts.NetworkErrorException;
method public abstract java.lang.String getAuthTokenLabel(java.lang.String);
method public final android.os.IBinder getIBinder();
method public abstract android.os.Bundle hasFeatures(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String[]) throws android.accounts.NetworkErrorException;
- method public android.os.Bundle startAddAccountSession(android.accounts.AccountAuthenticatorResponse, java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle) throws android.accounts.NetworkErrorException;
- method public android.os.Bundle startUpdateCredentialsSession(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String, android.os.Bundle) throws android.accounts.NetworkErrorException;
method public abstract android.os.Bundle updateCredentials(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String, android.os.Bundle) throws android.accounts.NetworkErrorException;
field public static final java.lang.String KEY_CUSTOM_TOKEN_EXPIRY = "android.accounts.expiry";
}
@@ -2796,7 +2793,6 @@
method public void clearPassword(android.accounts.Account);
method public android.accounts.AccountManagerFuture<android.os.Bundle> confirmCredentials(android.accounts.Account, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AccountManagerFuture<android.os.Bundle> editProperties(java.lang.String, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
- method public android.accounts.AccountManagerFuture<android.os.Bundle> finishSession(android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public static android.accounts.AccountManager get(android.content.Context);
method public android.accounts.Account[] getAccounts();
method public android.accounts.Account[] getAccountsByType(java.lang.String);
@@ -2824,8 +2820,6 @@
method public void setAuthToken(android.accounts.Account, java.lang.String, java.lang.String);
method public void setPassword(android.accounts.Account, java.lang.String);
method public void setUserData(android.accounts.Account, java.lang.String, java.lang.String);
- method public android.accounts.AccountManagerFuture<android.os.Bundle> startAddAccountSession(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
- method public android.accounts.AccountManagerFuture<android.os.Bundle> startUpdateCredentialsSession(android.accounts.Account, java.lang.String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AccountManagerFuture<android.os.Bundle> updateCredentials(android.accounts.Account, java.lang.String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
field public static final java.lang.String ACTION_AUTHENTICATOR_INTENT = "android.accounts.AccountAuthenticator";
field public static final java.lang.String AUTHENTICATOR_ATTRIBUTES_NAME = "account-authenticator";
@@ -2842,8 +2836,6 @@
field public static final java.lang.String KEY_ACCOUNT_AUTHENTICATOR_RESPONSE = "accountAuthenticatorResponse";
field public static final java.lang.String KEY_ACCOUNT_MANAGER_RESPONSE = "accountManagerResponse";
field public static final java.lang.String KEY_ACCOUNT_NAME = "authAccount";
- field public static final java.lang.String KEY_ACCOUNT_SESSION_BUNDLE = "accountSessionBundle";
- field public static final java.lang.String KEY_ACCOUNT_STATUS_TOKEN = "accountStatusToken";
field public static final java.lang.String KEY_ACCOUNT_TYPE = "accountType";
field public static final java.lang.String KEY_ANDROID_PACKAGE_NAME = "androidPackageName";
field public static final java.lang.String KEY_AUTHENTICATOR_TYPES = "authenticator_types";
@@ -33726,17 +33718,24 @@
method public java.lang.CharSequence getContentDescription();
method public android.graphics.drawable.Icon getIcon();
method public java.lang.CharSequence getLabel();
+ method public int getState();
method public void setContentDescription(java.lang.CharSequence);
method public void setIcon(android.graphics.drawable.Icon);
method public void setLabel(java.lang.CharSequence);
+ method public void setState(int);
method public void updateTile();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.quicksettings.Tile> CREATOR;
+ field public static final int STATE_ACTIVE = 2; // 0x2
+ field public static final int STATE_INACTIVE = 1; // 0x1
+ field public static final int STATE_UNAVAILABLE = 0; // 0x0
}
public class TileService extends android.app.Service {
ctor public TileService();
method public final android.service.quicksettings.Tile getQsTile();
+ method public final boolean isLocked();
+ method public final boolean isSecure();
method public android.os.IBinder onBind(android.content.Intent);
method public void onClick();
method public void onStartListening();
@@ -33745,6 +33744,8 @@
method public void onTileRemoved();
method public static final void requestListeningState(android.content.Context, android.content.ComponentName);
method public final void showDialog(android.app.Dialog);
+ method public final void startActivityAndCollapse(android.content.Intent);
+ method public final void unlockAndRun(java.lang.Runnable);
field public static final java.lang.String ACTION_QS_TILE = "android.service.quicksettings.action.QS_TILE";
field public static final int TILE_MODE_ACTIVE = 2; // 0x2
field public static final int TILE_MODE_PASSIVE = 1; // 0x1
diff --git a/api/system-current.txt b/api/system-current.txt
index adce480..d1421e5 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -35896,17 +35896,24 @@
method public java.lang.CharSequence getContentDescription();
method public android.graphics.drawable.Icon getIcon();
method public java.lang.CharSequence getLabel();
+ method public int getState();
method public void setContentDescription(java.lang.CharSequence);
method public void setIcon(android.graphics.drawable.Icon);
method public void setLabel(java.lang.CharSequence);
+ method public void setState(int);
method public void updateTile();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.quicksettings.Tile> CREATOR;
+ field public static final int STATE_ACTIVE = 2; // 0x2
+ field public static final int STATE_INACTIVE = 1; // 0x1
+ field public static final int STATE_UNAVAILABLE = 0; // 0x0
}
public class TileService extends android.app.Service {
ctor public TileService();
method public final android.service.quicksettings.Tile getQsTile();
+ method public final boolean isLocked();
+ method public final boolean isSecure();
method public android.os.IBinder onBind(android.content.Intent);
method public void onClick();
method public void onStartListening();
@@ -35916,6 +35923,8 @@
method public static final void requestListeningState(android.content.Context, android.content.ComponentName);
method public final void setStatusIcon(android.graphics.drawable.Icon, java.lang.String);
method public final void showDialog(android.app.Dialog);
+ method public final void startActivityAndCollapse(android.content.Intent);
+ method public final void unlockAndRun(java.lang.Runnable);
field public static final java.lang.String ACTION_QS_TILE = "android.service.quicksettings.action.QS_TILE";
field public static final int TILE_MODE_ACTIVE = 2; // 0x2
field public static final int TILE_MODE_PASSIVE = 1; // 0x1
diff --git a/api/test-current.txt b/api/test-current.txt
index 3fed632..91dcf34 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -2750,15 +2750,12 @@
method public android.os.Bundle addAccountFromCredentials(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, android.os.Bundle) throws android.accounts.NetworkErrorException;
method public abstract android.os.Bundle confirmCredentials(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, android.os.Bundle) throws android.accounts.NetworkErrorException;
method public abstract android.os.Bundle editProperties(android.accounts.AccountAuthenticatorResponse, java.lang.String);
- method public android.os.Bundle finishSession(android.accounts.AccountAuthenticatorResponse, java.lang.String, android.os.Bundle) throws android.accounts.NetworkErrorException;
method public android.os.Bundle getAccountCredentialsForCloning(android.accounts.AccountAuthenticatorResponse, android.accounts.Account) throws android.accounts.NetworkErrorException;
method public android.os.Bundle getAccountRemovalAllowed(android.accounts.AccountAuthenticatorResponse, android.accounts.Account) throws android.accounts.NetworkErrorException;
method public abstract android.os.Bundle getAuthToken(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String, android.os.Bundle) throws android.accounts.NetworkErrorException;
method public abstract java.lang.String getAuthTokenLabel(java.lang.String);
method public final android.os.IBinder getIBinder();
method public abstract android.os.Bundle hasFeatures(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String[]) throws android.accounts.NetworkErrorException;
- method public android.os.Bundle startAddAccountSession(android.accounts.AccountAuthenticatorResponse, java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle) throws android.accounts.NetworkErrorException;
- method public android.os.Bundle startUpdateCredentialsSession(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String, android.os.Bundle) throws android.accounts.NetworkErrorException;
method public abstract android.os.Bundle updateCredentials(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String, android.os.Bundle) throws android.accounts.NetworkErrorException;
field public static final java.lang.String KEY_CUSTOM_TOKEN_EXPIRY = "android.accounts.expiry";
}
@@ -2796,7 +2793,6 @@
method public void clearPassword(android.accounts.Account);
method public android.accounts.AccountManagerFuture<android.os.Bundle> confirmCredentials(android.accounts.Account, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AccountManagerFuture<android.os.Bundle> editProperties(java.lang.String, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
- method public android.accounts.AccountManagerFuture<android.os.Bundle> finishSession(android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public static android.accounts.AccountManager get(android.content.Context);
method public android.accounts.Account[] getAccounts();
method public android.accounts.Account[] getAccountsByType(java.lang.String);
@@ -2824,8 +2820,6 @@
method public void setAuthToken(android.accounts.Account, java.lang.String, java.lang.String);
method public void setPassword(android.accounts.Account, java.lang.String);
method public void setUserData(android.accounts.Account, java.lang.String, java.lang.String);
- method public android.accounts.AccountManagerFuture<android.os.Bundle> startAddAccountSession(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
- method public android.accounts.AccountManagerFuture<android.os.Bundle> startUpdateCredentialsSession(android.accounts.Account, java.lang.String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AccountManagerFuture<android.os.Bundle> updateCredentials(android.accounts.Account, java.lang.String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
field public static final java.lang.String ACTION_AUTHENTICATOR_INTENT = "android.accounts.AccountAuthenticator";
field public static final java.lang.String AUTHENTICATOR_ATTRIBUTES_NAME = "account-authenticator";
@@ -2842,8 +2836,6 @@
field public static final java.lang.String KEY_ACCOUNT_AUTHENTICATOR_RESPONSE = "accountAuthenticatorResponse";
field public static final java.lang.String KEY_ACCOUNT_MANAGER_RESPONSE = "accountManagerResponse";
field public static final java.lang.String KEY_ACCOUNT_NAME = "authAccount";
- field public static final java.lang.String KEY_ACCOUNT_SESSION_BUNDLE = "accountSessionBundle";
- field public static final java.lang.String KEY_ACCOUNT_STATUS_TOKEN = "accountStatusToken";
field public static final java.lang.String KEY_ACCOUNT_TYPE = "accountType";
field public static final java.lang.String KEY_ANDROID_PACKAGE_NAME = "androidPackageName";
field public static final java.lang.String KEY_AUTHENTICATOR_TYPES = "authenticator_types";
@@ -33740,17 +33732,24 @@
method public java.lang.CharSequence getContentDescription();
method public android.graphics.drawable.Icon getIcon();
method public java.lang.CharSequence getLabel();
+ method public int getState();
method public void setContentDescription(java.lang.CharSequence);
method public void setIcon(android.graphics.drawable.Icon);
method public void setLabel(java.lang.CharSequence);
+ method public void setState(int);
method public void updateTile();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.quicksettings.Tile> CREATOR;
+ field public static final int STATE_ACTIVE = 2; // 0x2
+ field public static final int STATE_INACTIVE = 1; // 0x1
+ field public static final int STATE_UNAVAILABLE = 0; // 0x0
}
public class TileService extends android.app.Service {
ctor public TileService();
method public final android.service.quicksettings.Tile getQsTile();
+ method public final boolean isLocked();
+ method public final boolean isSecure();
method public android.os.IBinder onBind(android.content.Intent);
method public void onClick();
method public void onStartListening();
@@ -33759,6 +33758,8 @@
method public void onTileRemoved();
method public static final void requestListeningState(android.content.Context, android.content.ComponentName);
method public final void showDialog(android.app.Dialog);
+ method public final void startActivityAndCollapse(android.content.Intent);
+ method public final void unlockAndRun(java.lang.Runnable);
field public static final java.lang.String ACTION_QS_TILE = "android.service.quicksettings.action.QS_TILE";
field public static final int TILE_MODE_ACTIVE = 2; // 0x2
field public static final int TILE_MODE_PASSIVE = 1; // 0x1
diff --git a/core/java/android/accounts/AbstractAccountAuthenticator.java b/core/java/android/accounts/AbstractAccountAuthenticator.java
index a312e3f..690e674 100644
--- a/core/java/android/accounts/AbstractAccountAuthenticator.java
+++ b/core/java/android/accounts/AbstractAccountAuthenticator.java
@@ -25,6 +25,7 @@
import android.content.Context;
import android.content.Intent;
import android.Manifest;
+import android.annotation.SystemApi;
import android.util.Log;
import java.util.Arrays;
@@ -762,7 +763,9 @@
* @throws NetworkErrorException if the authenticator could not honor the
* request due to a network error
* @see #finishSession(AccountAuthenticatorResponse, String, Bundle)
+ * @hide
*/
+ @SystemApi
public Bundle startAddAccountSession(
final AccountAuthenticatorResponse response,
final String accountType,
@@ -818,7 +821,9 @@
* @throws NetworkErrorException if the authenticator could not honor the
* request due to a network error
* @see #finishSession(AccountAuthenticatorResponse, String, Bundle)
+ * @hide
*/
+ @SystemApi
public Bundle startUpdateCredentialsSession(
final AccountAuthenticatorResponse response,
final Account account,
@@ -870,7 +875,9 @@
* </ul>
* @throws NetworkErrorException
* @see #startAddAccountSession and #startUpdateCredentialsSession
+ * @hide
*/
+ @SystemApi
public Bundle finishSession(
final AccountAuthenticatorResponse response,
final String accountType,
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index ada1ac2..2449ee5 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.Size;
+import android.annotation.SystemApi;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -244,14 +245,18 @@
* Bundle key used for a {@link Bundle} in result from
* {@link #startAddAccountSession} and friends which returns session data
* for installing an account later.
+ * @hide
*/
+ @SystemApi
public static final String KEY_ACCOUNT_SESSION_BUNDLE = "accountSessionBundle";
/**
* Bundle key used for the {@link String} account status token in result
* from {@link #startAddAccountSession} and friends which returns
* information about a particular account.
+ * @hide
*/
+ @SystemApi
public static final String KEY_ACCOUNT_STATUS_TOKEN = "accountStatusToken";
public static final String ACTION_AUTHENTICATOR_INTENT =
@@ -2667,7 +2672,9 @@
* trouble
* </ul>
* @see #finishSession
+ * @hide
*/
+ @SystemApi
public AccountManagerFuture<Bundle> startAddAccountSession(
final String accountType,
final String authTokenType,
@@ -2749,7 +2756,9 @@
* trouble
* </ul>
* @see #finishSession
+ * @hide
*/
+ @SystemApi
public AccountManagerFuture<Bundle> startUpdateCredentialsSession(
final Account account,
final String authTokenType,
@@ -2818,7 +2827,9 @@
* trouble
* </ul>
* @see #startAddAccountSession and #startUpdateCredentialsSession
+ * @hide
*/
+ @SystemApi
public AccountManagerFuture<Bundle> finishSession(
final Bundle sessionBundle,
final Activity activity,
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 35cd2be..519e5a0 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3034,6 +3034,24 @@
public static final String ACTION_GLOBAL_BUTTON = "android.intent.action.GLOBAL_BUTTON";
/**
+ * Broadcast Action: Sent when media resource is granted.
+ * <p>
+ * {@link #EXTRA_PACKAGES} specifies the packages on the process holding the media resource
+ * granted.
+ * </p>
+ * <p class="note">
+ * This is a protected intent that can only be sent by the system.
+ * </p>
+ * <p class="note">
+ * This requires the RECEIVE_MEDIA_RESOURCE_USAGE permission.
+ * </p>
+ *
+ * @hide
+ */
+ public static final String ACTION_MEDIA_RESOURCE_GRANTED =
+ "android.intent.action.MEDIA_RESOURCE_GRANTED";
+
+ /**
* Activity Action: Allow the user to select and return one or more existing
* documents. When invoked, the system will display the various
* {@link DocumentsProvider} instances installed on the device, letting the
@@ -4077,6 +4095,34 @@
* Optional boolean extra indicating whether quiet mode has been switched on or off.
*/
public static final String EXTRA_QUIET_MODE = "android.intent.extra.QUIET_MODE";
+
+ /**
+ * Used as an int extra field in {@link android.content.Intent#ACTION_MEDIA_RESOURCE_GRANTED}
+ * intents to specify the resource type granted. Possible values are
+ * {@link android.content.Intent#EXTRA_MEDIA_RESOURCE_TYPE_VIDEO_CODEC} or
+ * {@link android.content.Intent#EXTRA_MEDIA_RESOURCE_TYPE_AUDIO_CODEC}.
+ *
+ * @hide
+ */
+ public static final String EXTRA_MEDIA_RESOURCE_TYPE =
+ "android.intent.extra.MEDIA_RESOURCE_TYPE";
+
+ /**
+ * Used as an int value for {@link android.content.Intent#EXTRA_MEDIA_RESOURCE_TYPE}
+ * to represent that a video codec is allowed to use.
+ *
+ * @hide
+ */
+ public static final int EXTRA_MEDIA_RESOURCE_TYPE_VIDEO_CODEC = 0;
+
+ /**
+ * Used as an int value for {@link android.content.Intent#EXTRA_MEDIA_RESOURCE_TYPE}
+ * to represent that a audio codec is allowed to use.
+ *
+ * @hide
+ */
+ public static final int EXTRA_MEDIA_RESOURCE_TYPE_AUDIO_CODEC = 1;
+
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Intent flags (see mFlags variable).
diff --git a/core/java/android/service/quicksettings/IQSService.aidl b/core/java/android/service/quicksettings/IQSService.aidl
index 9991d41..4bfc948 100644
--- a/core/java/android/service/quicksettings/IQSService.aidl
+++ b/core/java/android/service/quicksettings/IQSService.aidl
@@ -27,5 +27,9 @@
void updateStatusIcon(in Tile tile, in Icon icon,
String contentDescription);
void onShowDialog(in Tile tile);
+ void onStartActivity(in Tile tile);
void setTileMode(in ComponentName component, int mode);
+ boolean isLocked();
+ boolean isSecure();
+ void startUnlockAndRun(in Tile tile);
}
diff --git a/core/java/android/service/quicksettings/IQSTileService.aidl b/core/java/android/service/quicksettings/IQSTileService.aidl
index 4997f75..bfde870 100644
--- a/core/java/android/service/quicksettings/IQSTileService.aidl
+++ b/core/java/android/service/quicksettings/IQSTileService.aidl
@@ -29,4 +29,5 @@
void onStartListening();
void onStopListening();
void onClick(IBinder wtoken);
+ void onUnlockComplete();
}
diff --git a/core/java/android/service/quicksettings/Tile.java b/core/java/android/service/quicksettings/Tile.java
index 6104913..85f1955 100644
--- a/core/java/android/service/quicksettings/Tile.java
+++ b/core/java/android/service/quicksettings/Tile.java
@@ -36,10 +36,37 @@
private static final String TAG = "Tile";
+ /**
+ * This is the default state of any tile, until updated by the {@link TileService}.
+ * <p>
+ * An unavailable state indicates that for some reason this tile is not currently
+ * available to the user for some reason, and will have no click action. The tile's
+ * icon will be tinted differently to reflect this state.
+ */
+ public static final int STATE_UNAVAILABLE = 0;
+
+ /**
+ * This represents a tile that is currently in a disabled state but is still interactable.
+ *
+ * A disabled state indicates that the tile is not currently active (e.g. wifi disconnected or
+ * bluetooth disabled), but is still interactable by the user to modify this state. Tiles
+ * that have boolean states should use this to represent one of their states. The tile's
+ * icon will be tinted differently to reflect this state, but still be distinct from unavailable.
+ */
+ public static final int STATE_INACTIVE = 1;
+
+ /**
+ * This represents a tile that is currently active. (e.g. wifi is connected, bluetooth is on,
+ * cast is casting).
+ */
+ public static final int STATE_ACTIVE = 2;
+
private ComponentName mComponentName;
private Icon mIcon;
private CharSequence mLabel;
private CharSequence mContentDescription;
+ // Default to active until clients of the new API can update.
+ private int mState = STATE_ACTIVE;
private IQSService mService;
@@ -79,6 +106,29 @@
}
/**
+ * The current state of the tile.
+ *
+ * @see #STATE_UNAVAILABLE
+ * @see #STATE_INACTIVE
+ * @see #STATE_ACTIVE
+ */
+ public int getState() {
+ return mState;
+ }
+
+ /**
+ * Sets the current state for the tile.
+ *
+ * Does not take effect until {@link #updateTile()} is called.
+ *
+ * @param state One of {@link #STATE_UNAVAILABLE}, {@link #STATE_INACTIVE},
+ * {@link #STATE_ACTIVE}
+ */
+ public void setState(int state) {
+ mState = state;
+ }
+
+ /**
* Gets the current icon for the tile.
*/
public Icon getIcon() {
@@ -165,6 +215,7 @@
} else {
dest.writeByte((byte) 0);
}
+ dest.writeInt(mState);
TextUtils.writeToParcel(mLabel, dest, flags);
TextUtils.writeToParcel(mContentDescription, dest, flags);
}
@@ -180,6 +231,7 @@
} else {
mIcon = null;
}
+ mState = source.readInt();
mLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
}
diff --git a/core/java/android/service/quicksettings/TileService.java b/core/java/android/service/quicksettings/TileService.java
index 6b12193..c02465b 100644
--- a/core/java/android/service/quicksettings/TileService.java
+++ b/core/java/android/service/quicksettings/TileService.java
@@ -118,6 +118,7 @@
private Tile mTile;
private IBinder mToken;
private IQSService mService;
+ private Runnable mUnlockRunnable;
@Override
public void onDestroy() {
@@ -199,6 +200,8 @@
* This will collapse the Quick Settings panel and show the dialog.
*
* @param dialog Dialog to show.
+ *
+ * @see #isLocked()
*/
public final void showDialog(Dialog dialog) {
dialog.getWindow().getAttributes().token = mToken;
@@ -211,6 +214,67 @@
}
/**
+ * Prompts the user to unlock the device before executing the Runnable.
+ * <p>
+ * The user will be prompted for their current security method if applicable
+ * and if successful, runnable will be executed. The Runnable will not be
+ * executed if the user fails to unlock the device or cancels the operation.
+ */
+ public final void unlockAndRun(Runnable runnable) {
+ mUnlockRunnable = runnable;
+ try {
+ mService.startUnlockAndRun(mTile);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
+ * Checks if the device is in a secure state.
+ *
+ * TileServices should detect when the device is secure and change their behavior
+ * accordingly.
+ *
+ * @return true if the device is secure.
+ */
+ public final boolean isSecure() {
+ try {
+ return mService.isSecure();
+ } catch (RemoteException e) {
+ return true;
+ }
+ }
+
+ /**
+ * Checks if the lock screen is showing.
+ *
+ * When a device is locked, then {@link #showDialog} will not present a dialog, as it will
+ * be under the lock screen. If the behavior of the Tile is safe to do while locked,
+ * then the user should use {@link #startActivity} to launch an activity on top of the lock
+ * screen, otherwise the tile should use {@link #unlockAndRun(Runnable)} to give the
+ * user their security challenge.
+ *
+ * @return true if the device is locked.
+ */
+ public final boolean isLocked() {
+ try {
+ return mService.isLocked();
+ } catch (RemoteException e) {
+ return true;
+ }
+ }
+
+ /**
+ * Start an activity while collapsing the panel.
+ */
+ public final void startActivityAndCollapse(Intent intent) {
+ startActivity(intent);
+ try {
+ mService.onStartActivity(mTile);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
* Gets the {@link Tile} for this service.
* <p/>
* This tile may be used to get or set the current state for this
@@ -258,6 +322,11 @@
public void onClick(IBinder wtoken) throws RemoteException {
mHandler.obtainMessage(H.MSG_TILE_CLICKED, wtoken).sendToTarget();
}
+
+ @Override
+ public void onUnlockComplete() throws RemoteException{
+ mHandler.sendEmptyMessage(H.MSG_UNLOCK_COMPLETE);
+ }
};
}
@@ -269,6 +338,7 @@
private static final int MSG_TILE_REMOVED = 5;
private static final int MSG_TILE_CLICKED = 6;
private static final int MSG_SET_SERVICE = 7;
+ private static final int MSG_UNLOCK_COMPLETE = 8;
public H(Looper looper) {
super(looper);
@@ -323,6 +393,11 @@
mToken = (IBinder) msg.obj;
TileService.this.onClick();
break;
+ case MSG_UNLOCK_COMPLETE:
+ if (mUnlockRunnable != null) {
+ mUnlockRunnable.run();
+ }
+ break;
}
}
}
diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java
index e0dbe2f..1536c29 100644
--- a/core/java/android/view/animation/Animation.java
+++ b/core/java/android/view/animation/Animation.java
@@ -850,7 +850,7 @@
normalizedTime = currentTime < mStartTime ? 0.0f : 1.0f;
}
- final boolean expired = normalizedTime >= 1.0f;
+ final boolean expired = normalizedTime >= 1.0f || isCanceled();
mMore = !expired;
if (!mFillEnabled) normalizedTime = Math.max(Math.min(normalizedTime, 1.0f), 0.0f);
@@ -875,7 +875,7 @@
}
if (expired) {
- if (mRepeatCount == mRepeated) {
+ if (mRepeatCount == mRepeated || isCanceled()) {
if (!mEnded) {
mEnded = true;
guard.close();
@@ -905,6 +905,10 @@
return mMore;
}
+ private boolean isCanceled() {
+ return mStartTime == Long.MIN_VALUE;
+ }
+
private void fireAnimationStart() {
if (mListener != null) {
if (mListenerHandler == null) mListener.onAnimationStart(this);
diff --git a/core/java/android/widget/ActionMenuPresenter.java b/core/java/android/widget/ActionMenuPresenter.java
index 48d1d2b..ac8d578 100644
--- a/core/java/android/widget/ActionMenuPresenter.java
+++ b/core/java/android/widget/ActionMenuPresenter.java
@@ -59,7 +59,6 @@
*/
public class ActionMenuPresenter extends BaseMenuPresenter
implements ActionProvider.SubUiVisibilityListener {
- private static final String TAG = "ActionMenuPresenter";
private static final int ITEM_ANIMATION_DURATION = 150;
private static final boolean ACTIONBAR_ANIMATIONS_ENABLED = false;
@@ -87,20 +86,16 @@
private OpenOverflowRunnable mPostedOpenRunnable;
private ActionMenuPopupCallback mPopupCallback;
- private final boolean mShowCascadingMenus;
-
final PopupPresenterCallback mPopupPresenterCallback = new PopupPresenterCallback();
int mOpenSubMenuId;
// These collections are used to store pre- and post-layout information for menu items,
// which is used to determine appropriate animations to run for changed items.
- private SparseArray<MenuItemLayoutInfo> mPreLayoutItems =
- new SparseArray<MenuItemLayoutInfo>();
- private SparseArray<MenuItemLayoutInfo> mPostLayoutItems =
- new SparseArray<MenuItemLayoutInfo>();
+ private SparseArray<MenuItemLayoutInfo> mPreLayoutItems = new SparseArray<>();
+ private SparseArray<MenuItemLayoutInfo> mPostLayoutItems = new SparseArray<>();
// The list of currently running animations on menu items.
- private List<ItemAnimationInfo> mRunningItemAnimations = new ArrayList<ItemAnimationInfo>();
+ private List<ItemAnimationInfo> mRunningItemAnimations = new ArrayList<>();
private ViewTreeObserver.OnPreDrawListener mItemAnimationPreDrawListener =
new ViewTreeObserver.OnPreDrawListener() {
@Override
@@ -130,9 +125,6 @@
public ActionMenuPresenter(Context context) {
super(context, com.android.internal.R.layout.action_menu_layout,
com.android.internal.R.layout.action_menu_item_layout);
-
- mShowCascadingMenus = context.getResources().getBoolean(
- com.android.internal.R.bool.config_enableCascadingSubmenus);
}
@Override
@@ -845,8 +837,6 @@
}
private class OverflowMenuButton extends ImageButton implements ActionMenuView.ActionMenuChildView {
- private final float[] mTempPts = new float[2];
-
public OverflowMenuButton(Context context) {
super(context, null, com.android.internal.R.attr.actionOverflowButtonStyle);
diff --git a/core/java/android/widget/ForwardingListener.java b/core/java/android/widget/ForwardingListener.java
index 7ddeff9..b383e1c 100644
--- a/core/java/android/widget/ForwardingListener.java
+++ b/core/java/android/widget/ForwardingListener.java
@@ -53,12 +53,6 @@
/** Whether this listener is currently forwarding touch events. */
private boolean mForwarding;
- /**
- * Whether forwarding was initiated by a long-press. If so, we won't
- * force the window to dismiss when the touch stream ends.
- */
- private boolean mWasLongPress;
-
/** The id of the first pointer down in the current event stream. */
private int mActivePointerId;
@@ -172,7 +166,6 @@
switch (actionMasked) {
case MotionEvent.ACTION_DOWN:
mActivePointerId = srcEvent.getPointerId(0);
- mWasLongPress = false;
if (mDisallowIntercept == null) {
mDisallowIntercept = new DisallowIntercept();
@@ -243,7 +236,6 @@
e.recycle();
mForwarding = true;
- mWasLongPress = true;
}
/**
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index b95bc28..595adc2 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -16,18 +16,20 @@
package android.widget;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
+import com.android.internal.R;
+import com.android.internal.view.menu.ShowableListMenu;
+
+import android.annotation.AttrRes;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.StyleRes;
import android.content.Context;
import android.content.res.TypedArray;
import android.database.DataSetObserver;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Handler;
-import android.text.TextUtils;
import android.util.AttributeSet;
-import android.util.IntProperty;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
@@ -38,13 +40,7 @@
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.WindowManager;
-import android.view.animation.AccelerateDecelerateInterpolator;
-
-import com.android.internal.R;
-import com.android.internal.view.menu.ShowableListMenu;
-import com.android.internal.widget.AutoScrollHelper.AbsListViewAutoScroller;
-
-import java.util.Locale;
+import android.widget.AdapterView.OnItemSelectedListener;
/**
* A ListPopupWindow anchors itself to a host view and displays a
@@ -109,8 +105,6 @@
private boolean mModal;
- private int mLayoutDirection;
-
PopupWindow mPopup;
/**
@@ -174,7 +168,7 @@
*
* @param context Context used for contained views.
*/
- public ListPopupWindow(Context context) {
+ public ListPopupWindow(@NonNull Context context) {
this(context, null, com.android.internal.R.attr.listPopupWindowStyle, 0);
}
@@ -185,7 +179,7 @@
* @param context Context used for contained views.
* @param attrs Attributes from inflating parent views used to style the popup.
*/
- public ListPopupWindow(Context context, AttributeSet attrs) {
+ public ListPopupWindow(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs, com.android.internal.R.attr.listPopupWindowStyle, 0);
}
@@ -197,7 +191,8 @@
* @param attrs Attributes from inflating parent views used to style the popup.
* @param defStyleAttr Default style attribute to use for popup content.
*/
- public ListPopupWindow(Context context, AttributeSet attrs, int defStyleAttr) {
+ public ListPopupWindow(@NonNull Context context, @Nullable AttributeSet attrs,
+ @AttrRes int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
@@ -210,7 +205,8 @@
* @param defStyleAttr Style attribute to read for default styling of popup content.
* @param defStyleRes Style resource ID to use for default styling of popup content.
*/
- public ListPopupWindow(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ public ListPopupWindow(@NonNull Context context, @Nullable AttributeSet attrs,
+ @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
mContext = context;
mHandler = new Handler(context.getMainLooper());
@@ -227,9 +223,6 @@
mPopup = new PopupWindow(context, attrs, defStyleAttr, defStyleRes);
mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
- // Set the default layout direction to match the default locale one
- final Locale locale = mContext.getResources().getConfiguration().locale;
- mLayoutDirection = TextUtils.getLayoutDirectionFromLocale(locale);
}
/**
@@ -238,7 +231,7 @@
*
* @param adapter The adapter to use to create this window's content.
*/
- public void setAdapter(ListAdapter adapter) {
+ public void setAdapter(@Nullable ListAdapter adapter) {
if (mObserver == null) {
mObserver = new PopupDataSetObserver();
} else if (mAdapter != null) {
@@ -371,7 +364,7 @@
/**
* @return The background drawable for the popup window.
*/
- public Drawable getBackground() {
+ public @Nullable Drawable getBackground() {
return mPopup.getBackground();
}
@@ -380,7 +373,7 @@
*
* @param d A drawable to set as the background.
*/
- public void setBackgroundDrawable(Drawable d) {
+ public void setBackgroundDrawable(@Nullable Drawable d) {
mPopup.setBackgroundDrawable(d);
}
@@ -389,7 +382,7 @@
*
* @param animationStyle Animation style to use.
*/
- public void setAnimationStyle(int animationStyle) {
+ public void setAnimationStyle(@StyleRes int animationStyle) {
mPopup.setAnimationStyle(animationStyle);
}
@@ -399,7 +392,7 @@
*
* @return Animation style that will be used.
*/
- public int getAnimationStyle() {
+ public @StyleRes int getAnimationStyle() {
return mPopup.getAnimationStyle();
}
@@ -408,7 +401,7 @@
*
* @return The popup's anchor view
*/
- public View getAnchorView() {
+ public @Nullable View getAnchorView() {
return mDropDownAnchorView;
}
@@ -418,7 +411,7 @@
*
* @param anchor The view to use as an anchor.
*/
- public void setAnchorView(View anchor) {
+ public void setAnchorView(@Nullable View anchor) {
mDropDownAnchorView = anchor;
}
@@ -537,7 +530,7 @@
*
* @see ListView#setOnItemClickListener(android.widget.AdapterView.OnItemClickListener)
*/
- public void setOnItemClickListener(AdapterView.OnItemClickListener clickListener) {
+ public void setOnItemClickListener(@Nullable AdapterView.OnItemClickListener clickListener) {
mItemClickListener = clickListener;
}
@@ -546,9 +539,9 @@
*
* @param selectedListener Listener to register.
*
- * @see ListView#setOnItemSelectedListener(android.widget.AdapterView.OnItemSelectedListener)
+ * @see ListView#setOnItemSelectedListener(OnItemSelectedListener)
*/
- public void setOnItemSelectedListener(AdapterView.OnItemSelectedListener selectedListener) {
+ public void setOnItemSelectedListener(@Nullable OnItemSelectedListener selectedListener) {
mItemSelectedListener = selectedListener;
}
@@ -558,7 +551,7 @@
*
* @param prompt View to use as an informational prompt.
*/
- public void setPromptView(View prompt) {
+ public void setPromptView(@Nullable View prompt) {
boolean showing = isShowing();
if (showing) {
removePromptView();
@@ -686,7 +679,7 @@
*
* @param listener Listener that will be notified when the popup is dismissed.
*/
- public void setOnDismissListener(PopupWindow.OnDismissListener listener) {
+ public void setOnDismissListener(@Nullable PopupWindow.OnDismissListener listener) {
mPopup.setOnDismissListener(listener);
}
@@ -795,7 +788,7 @@
/**
* @return The currently selected item or null if the popup is not showing.
*/
- public Object getSelectedItem() {
+ public @Nullable Object getSelectedItem() {
if (!isShowing()) {
return null;
}
@@ -834,7 +827,7 @@
*
* @see ListView#getSelectedView()
*/
- public View getSelectedView() {
+ public @Nullable View getSelectedView() {
if (!isShowing()) {
return null;
}
@@ -846,11 +839,11 @@
* Only valid when {@link #isShowing()} == {@code true}.
*/
@Override
- public ListView getListView() {
+ public @Nullable ListView getListView() {
return mDropDownList;
}
- DropDownListView createDropDownListView(Context context, boolean hijackFocus) {
+ @NonNull DropDownListView createDropDownListView(Context context, boolean hijackFocus) {
return new DropDownListView(context, hijackFocus);
}
@@ -874,7 +867,7 @@
*
* @see #setModal(boolean)
*/
- public boolean onKeyDown(int keyCode, KeyEvent event) {
+ public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) {
// when the drop down is shown, we drive it directly
if (isShowing()) {
// the key events are forwarded to the list in the drop down view
@@ -969,7 +962,7 @@
*
* @see #setModal(boolean)
*/
- public boolean onKeyUp(int keyCode, KeyEvent event) {
+ public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
if (isShowing() && mDropDownList.getSelectedItemPosition() >= 0) {
boolean consumed = mDropDownList.onKeyUp(keyCode, event);
if (consumed && KeyEvent.isConfirmKey(keyCode)) {
@@ -993,7 +986,7 @@
*
* @see #setModal(boolean)
*/
- public boolean onKeyPreIme(int keyCode, KeyEvent event) {
+ public boolean onKeyPreIme(int keyCode, @NonNull KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && isShowing()) {
// special case for the back key, we do not even try to send it
// to the drop down list but instead, consume it immediately
@@ -1159,7 +1152,6 @@
mPopup.setContentView(dropDownView);
} else {
- dropDownView = (ViewGroup) mPopup.getContentView();
final View view = mPromptView;
if (view != null) {
LinearLayout.LayoutParams hintParams =
diff --git a/core/java/com/android/internal/view/menu/StandardMenuPopup.java b/core/java/com/android/internal/view/menu/StandardMenuPopup.java
index c2adc42..a67e43a 100644
--- a/core/java/com/android/internal/view/menu/StandardMenuPopup.java
+++ b/core/java/com/android/internal/view/menu/StandardMenuPopup.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package com.android.internal.view.menu;
import android.content.Context;
@@ -7,7 +23,6 @@
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.ViewGroup;
import android.view.View.OnAttachStateChangeListener;
import android.view.View.OnKeyListener;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
@@ -30,7 +45,7 @@
MenuPresenter, OnKeyListener {
private final Context mContext;
- private final LayoutInflater mInflater;
+
private final MenuBuilder mMenu;
private final MenuAdapter mAdapter;
private final boolean mOverflowOnly;
@@ -79,8 +94,6 @@
private Callback mPresenterCallback;
private ViewTreeObserver mTreeObserver;
- private ViewGroup mMeasureParent;
-
/** Whether the popup has been dismissed. Once dismissed, it cannot be opened again. */
private boolean mWasDismissed;
@@ -99,10 +112,10 @@
public StandardMenuPopup(Context context, MenuBuilder menu, View anchorView, int popupStyleAttr,
int popupStyleRes, boolean overflowOnly) {
mContext = Preconditions.checkNotNull(context);
- mInflater = LayoutInflater.from(context);
mMenu = menu;
mOverflowOnly = overflowOnly;
- mAdapter = new MenuAdapter(menu, mInflater, mOverflowOnly);
+ final LayoutInflater inflater = LayoutInflater.from(context);
+ mAdapter = new MenuAdapter(menu, inflater, mOverflowOnly);
mPopupStyleAttr = popupStyleAttr;
mPopupStyleRes = popupStyleRes;
@@ -155,8 +168,7 @@
mPopup.setDropDownGravity(mDropDownGravity);
if (!mHasContentWidth) {
- mContentWidth = measureIndividualMenuWidth(
- mAdapter, mMeasureParent, mContext, mPopupMaxWidth);
+ mContentWidth = measureIndividualMenuWidth(mAdapter, null, mContext, mPopupMaxWidth);
mHasContentWidth = true;
}
@@ -177,7 +189,9 @@
false);
TextView titleView = (TextView) titleItemView.findViewById(
com.android.internal.R.id.title);
- titleView.setText(mMenu.getHeaderTitle());
+ if (titleView != null) {
+ titleView.setText(mMenu.getHeaderTitle());
+ }
titleItemView.setEnabled(false);
listView.addHeaderView(titleItemView, null, false);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 75077df..b02de0e 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -385,6 +385,7 @@
<protected-broadcast android:name="com.android.server.device_idle.STEP_LIGHT_IDLE_STATE" />
<protected-broadcast android:name="com.android.server.Wifi.action.TOGGLE_PNO" />
<protected-broadcast android:name="intent.action.ACTION_RF_BAND_INFO" />
+ <protected-broadcast android:name="android.intent.action.MEDIA_RESOURCE_GRANTED" />
<protected-broadcast android:name="android.app.action.INTERRUPTION_FILTER_CHANGED" />
<protected-broadcast android:name="android.app.action.INTERRUPTION_FILTER_CHANGED_INTERNAL" />
@@ -2828,6 +2829,12 @@
<permission android:name="android.permission.ACCESS_EPHEMERAL_APPS"
android:protectionLevel="signature" />
+ <!-- Allows receiving the usage of media resource e.g. video/audio codec and
+ graphic memory.
+ @hide -->
+ <permission android:name="android.permission.RECEIVE_MEDIA_RESOURCE_USAGE"
+ android:protectionLevel="signature|privileged" />
+
<application android:process="system"
android:persistent="true"
android:hasCode="false"
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index 166656c..c4c655b 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -51,20 +51,25 @@
// updated in the order they're passed in (mLayerBuilders are issued to Renderer in reverse)
for (int i = layers.entries().size() - 1; i >= 0; i--) {
RenderNode* layerNode = layers.entries()[i].renderNode;
- const Rect& layerDamage = layers.entries()[i].damage;
- layerNode->computeOrdering();
+ // only schedule repaint if node still on layer - possible it may have been
+ // removed during a dropped frame, but layers may still remain scheduled so
+ // as not to lose info on what portion is damaged
+ if (CC_LIKELY(layerNode->getLayer() != nullptr)) {
+ const Rect& layerDamage = layers.entries()[i].damage;
+ layerNode->computeOrdering();
- // map current light center into RenderNode's coordinate space
- Vector3 lightCenter = mCanvasState.currentSnapshot()->getRelativeLightCenter();
- layerNode->getLayer()->inverseTransformInWindow.mapPoint3d(lightCenter);
+ // map current light center into RenderNode's coordinate space
+ Vector3 lightCenter = mCanvasState.currentSnapshot()->getRelativeLightCenter();
+ layerNode->getLayer()->inverseTransformInWindow.mapPoint3d(lightCenter);
- saveForLayer(layerNode->getWidth(), layerNode->getHeight(), 0, 0,
- layerDamage, lightCenter, nullptr, layerNode);
+ saveForLayer(layerNode->getWidth(), layerNode->getHeight(), 0, 0,
+ layerDamage, lightCenter, nullptr, layerNode);
- if (layerNode->getDisplayList()) {
- deferNodeOps(*layerNode);
+ if (layerNode->getDisplayList()) {
+ deferNodeOps(*layerNode);
+ }
+ restoreForLayer();
}
- restoreForLayer();
}
// Defer Fbo0
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 644f356..24d43df 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -512,11 +512,11 @@
void CanvasContext::prepareAndDraw(RenderNode* node) {
ATRACE_CALL();
+ nsecs_t vsync = mRenderThread.timeLord().computeFrameTimeNanos();
int64_t frameInfo[UI_THREAD_FRAME_INFO_SIZE];
UiFrameInfoBuilder(frameInfo)
.addFlag(FrameInfoFlags::RTAnimation)
- .setVsync(mRenderThread.timeLord().computeFrameTimeNanos(),
- mRenderThread.timeLord().latestVsync());
+ .setVsync(vsync, vsync);
TreeInfo info(TreeInfo::MODE_RT_ONLY, *this);
prepareTree(info, frameInfo, systemTime(CLOCK_MONOTONIC), node);
@@ -578,7 +578,7 @@
node->setPropertyFieldsDirty(RenderNode::GENERIC);
#if HWUI_NEW_OPS
- LOG_ALWAYS_FATAL("unsupported");
+ // TODO: support buildLayer
#else
mCanvas->markLayersAsBuildLayers();
mCanvas->flushLayerUpdates();
diff --git a/media/java/android/media/IMediaResourceMonitor.aidl b/media/java/android/media/IMediaResourceMonitor.aidl
new file mode 100644
index 0000000..7b4bc39
--- /dev/null
+++ b/media/java/android/media/IMediaResourceMonitor.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2016 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.media;
+
+/** {@hide} */
+interface IMediaResourceMonitor
+{
+ oneway void notifyResourceGranted(in int pid, String type, String subType, long value);
+}
+
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index 180a48e..dfeef50 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -176,6 +176,12 @@
return true;
}
+ @Override
+ protected void onDestroy() {
+ mRoots.setOnCacheUpdateListener(null);
+ super.onDestroy();
+ }
+
State buildDefaultState() {
State state = new State();
@@ -518,7 +524,7 @@
@Override
protected void onPostExecute(DocumentInfo result) {
- if (result != null) {
+ if (result != null && !isDestroyed()) {
openContainerDocument(result);
}
}
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 905da13..0a56f92 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -147,4 +147,8 @@
<color name="default_remote_input_background">@*android:color/notification_default_color</color>
<color name="remote_input_hint">#4dffffff</color>
+
+ <color name="qs_tile_tint_unavailable">#40ffffff</color>
+ <color name="qs_tile_tint_inactive">#4dffffff</color>
+ <color name="qs_tile_tint_active">#ffffffff</color>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/BlankCustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/customize/BlankCustomTile.java
index 95ff611..ac4f05f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/BlankCustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/BlankCustomTile.java
@@ -19,8 +19,9 @@
import android.content.ComponentName;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
-
+import android.graphics.drawable.Drawable;
import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
public class BlankCustomTile extends QSTile<QSTile.State> {
@@ -72,7 +73,9 @@
try {
PackageManager pm = mContext.getPackageManager();
ServiceInfo info = pm.getServiceInfo(mComponent, 0);
- state.icon = new DrawableIcon(info.loadIcon(pm));
+ Drawable drawable = info.loadIcon(pm);
+ drawable.setTint(mContext.getColor(R.color.qs_tile_tint_active));
+ state.icon = new DrawableIcon(drawable);
state.label = info.loadLabel(pm).toString();
state.contentDescription = state.label;
} catch (Exception e) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index eefff30..d398b64 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -25,11 +25,14 @@
import android.service.quicksettings.IQSTileService;
import android.service.quicksettings.Tile;
import android.service.quicksettings.TileService;
+import android.text.SpannableStringBuilder;
+import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.view.IWindowManager;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.phone.QSTileHost;
@@ -88,6 +91,7 @@
mTile.setIcon(tile.getIcon());
mTile.setLabel(tile.getLabel());
mTile.setContentDescription(tile.getContentDescription());
+ mTile.setState(tile.getState());
}
public void onDialogShown() {
@@ -147,6 +151,9 @@
@Override
protected void handleClick() {
+ if (mTile.getState() == Tile.STATE_UNAVAILABLE) {
+ return;
+ }
try {
if (DEBUG) Log.d(TAG, "Adding token");
mWindowManager.addWindowToken(mToken, WindowManager.LayoutParams.TYPE_QS_DIALOG);
@@ -172,9 +179,15 @@
@Override
protected void handleUpdateState(State state, Object arg) {
Drawable drawable = mTile.getIcon().loadDrawable(mContext);
- drawable.setTint(mContext.getColor(android.R.color.white));
+ int color = mContext.getColor(getColor(mTile.getState()));
+ drawable.setTint(color);
state.icon = new DrawableIcon(drawable);
state.label = mTile.getLabel();
+ if (mTile.getState() == Tile.STATE_UNAVAILABLE) {
+ state.label = new SpannableStringBuilder().append(state.label,
+ new ForegroundColorSpan(color),
+ SpannableStringBuilder.SPAN_INCLUSIVE_INCLUSIVE);
+ }
if (mTile.getContentDescription() != null) {
state.contentDescription = mTile.getContentDescription();
} else {
@@ -187,6 +200,30 @@
return MetricsLogger.QS_CUSTOM;
}
+ public void startUnlockAndRun() {
+ mHost.startRunnableDismissingKeyguard(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ mService.onUnlockComplete();
+ } catch (RemoteException e) {
+ }
+ }
+ });
+ }
+
+ private static int getColor(int state) {
+ switch (state) {
+ case Tile.STATE_UNAVAILABLE:
+ return R.color.qs_tile_tint_unavailable;
+ case Tile.STATE_INACTIVE:
+ return R.color.qs_tile_tint_inactive;
+ case Tile.STATE_ACTIVE:
+ return R.color.qs_tile_tint_active;
+ }
+ return 0;
+ }
+
public static ComponentName getComponentFromSpec(String spec) {
final String action = spec.substring(PREFIX.length(), spec.length() - 1);
if (action.isEmpty()) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java b/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java
index d41cdde..3830ac5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java
@@ -104,4 +104,14 @@
return false;
}
}
+
+ public boolean onUnlockComplete() {
+ try {
+ mService.onUnlockComplete();
+ return true;
+ } catch (Exception e) {
+ Log.d(TAG, "Caught exception from TileService", e);
+ return false;
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index 8c5e87e..4977d80 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -55,6 +55,7 @@
private static final int MSG_ON_ADDED = 0;
private static final int MSG_ON_REMOVED = 1;
private static final int MSG_ON_CLICK = 2;
+ private static final int MSG_ON_UNLOCK_COMPLETE = 3;
// Bind retry control.
private static final int MAX_BIND_RETRIES = 5;
@@ -174,6 +175,15 @@
onClick(mClickBinder);
}
}
+ if (queue.contains(MSG_ON_UNLOCK_COMPLETE)) {
+ if (DEBUG) Log.d(TAG, "Handling pending onUnlockComplete");
+ if (!mListening) {
+ Log.w(TAG, "Managed to get unlock on non-listening state...");
+ // Skipping unlock since lost click privileges.
+ } else {
+ onUnlockComplete();
+ }
+ }
if (queue.contains(MSG_ON_REMOVED)) {
if (DEBUG) Log.d(TAG, "Handling pending onRemoved");
if (mListening) {
@@ -348,6 +358,15 @@
}
@Override
+ public void onUnlockComplete() {
+ if (DEBUG) Log.d(TAG, "onUnlockComplete");
+ if (mWrapper == null || !mWrapper.onUnlockComplete()) {
+ queueMessage(MSG_ON_UNLOCK_COMPLETE);
+ handleDeath();
+ }
+ }
+
+ @Override
public IBinder asBinder() {
return mWrapper != null ? mWrapper.asBinder() : null;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
index a831c87..44d8776 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
@@ -36,6 +36,7 @@
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.statusbar.phone.QSTileHost;
import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
import java.util.ArrayList;
import java.util.Collections;
@@ -199,6 +200,16 @@
}
@Override
+ public void onStartActivity(Tile tile) {
+ ComponentName componentName = tile.getComponentName();
+ verifyCaller(componentName.getPackageName());
+ CustomTile customTile = getTileForComponent(componentName);
+ if (customTile != null) {
+ mHost.collapsePanels();
+ }
+ }
+
+ @Override
public void updateStatusIcon(Tile tile, Icon icon, String contentDescription) {
final ComponentName componentName = tile.getComponentName();
String packageName = componentName.getPackageName();
@@ -228,6 +239,28 @@
}
}
+ @Override
+ public void startUnlockAndRun(Tile tile) {
+ ComponentName componentName = tile.getComponentName();
+ verifyCaller(componentName.getPackageName());
+ CustomTile customTile = getTileForComponent(componentName);
+ if (customTile != null) {
+ customTile.startUnlockAndRun();
+ }
+ }
+
+ @Override
+ public boolean isLocked() {
+ KeyguardMonitor keyguardMonitor = mHost.getKeyguardMonitor();
+ return keyguardMonitor.isShowing();
+ }
+
+ @Override
+ public boolean isSecure() {
+ KeyguardMonitor keyguardMonitor = mHost.getKeyguardMonitor();
+ return keyguardMonitor.isSecure() && keyguardMonitor.isShowing();
+ }
+
private CustomTile getTileForComponent(ComponentName component) {
synchronized (mServices) {
return mTiles.get(component);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index b65bf43..ad8e3bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -440,6 +440,7 @@
+ " dataState=" + state.getDataRegState());
}
mServiceState = state;
+ mDataNetType = state.getDataNetworkType();
updateTelephony();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java
index 6ebf488..f86c6a4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java
@@ -283,6 +283,11 @@
public void onClick(IBinder iBinder) throws RemoteException {
sendCallback("onClick");
}
+
+ @Override
+ public void onUnlockComplete() throws RemoteException {
+ sendCallback("onUnlockComplete");
+ }
};
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 13fc47d..b64fbea 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -60,8 +60,8 @@
protected NetworkControllerImpl mNetworkController;
protected MobileSignalController mMobileSignalController;
protected PhoneStateListener mPhoneStateListener;
- private SignalStrength mSignalStrength;
- private ServiceState mServiceState;
+ protected SignalStrength mSignalStrength;
+ protected ServiceState mServiceState;
protected ConnectivityManager mMockCm;
protected WifiManager mMockWm;
protected SubscriptionManager mMockSm;
@@ -235,7 +235,7 @@
mPhoneStateListener.onSignalStrengthsChanged(mSignalStrength);
}
- private void updateServiceState() {
+ protected void updateServiceState() {
Log.d(TAG, "Sending Service State: " + mServiceState);
mPhoneStateListener.onServiceStateChanged(mServiceState);
}
@@ -246,6 +246,7 @@
}
public void updateDataConnectionState(int dataState, int dataNetType) {
+ when(mServiceState.getDataNetworkType()).thenReturn(dataNetType);
mPhoneStateListener.onDataConnectionStateChanged(dataState, dataNetType);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
index 587e2b5..e4f858b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
@@ -115,6 +115,21 @@
TelephonyIcons.QS_DATA_4G);
}
+ public void testDataChangeWithoutConnectionState() {
+ setupDefaultSignal();
+ updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
+ TelephonyManager.NETWORK_TYPE_LTE);
+
+ verifyDataIndicators(TelephonyIcons.DATA_LTE[1][0 /* No direction */],
+ TelephonyIcons.QS_DATA_LTE);
+
+ Mockito.when(mServiceState.getDataNetworkType())
+ .thenReturn(TelephonyManager.NETWORK_TYPE_HSPA);
+ updateServiceState();
+ verifyDataIndicators(TelephonyIcons.DATA_H[1][0 /* No direction */],
+ TelephonyIcons.QS_DATA_H);
+ }
+
public void testDataActivity() {
setupDefaultSignal();
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 11f9e2d..f345d7e 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -2312,6 +2312,14 @@
}
final int uid = Binder.getCallingUid();
+ // Only allow system to start session
+ if (!isSystemUid(uid)) {
+ String msg = String.format(
+ "uid %s cannot stat add account session.",
+ uid);
+ throw new SecurityException(msg);
+ }
+
final int userId = UserHandle.getUserId(uid);
if (!canUserModifyAccounts(userId, uid)) {
try {
@@ -2499,6 +2507,14 @@
}
final int uid = Binder.getCallingUid();
+ // Only allow system to finish session
+ if (!isSystemUid(uid)) {
+ String msg = String.format(
+ "uid %s cannot finish session.",
+ uid);
+ throw new SecurityException(msg);
+ }
+
final int userId = UserHandle.getUserId(uid);
if (!canUserModifyAccounts(userId, uid)) {
sendErrorResponse(response,
@@ -2717,6 +2733,16 @@
if (account == null) {
throw new IllegalArgumentException("account is null");
}
+
+ final int uid = Binder.getCallingUid();
+ // Only allow system to start session
+ if (!isSystemUid(uid)) {
+ String msg = String.format(
+ "uid %s cannot start update credentials session.",
+ uid);
+ throw new SecurityException(msg);
+ }
+
int userId = UserHandle.getCallingUserId();
long identityToken = clearCallingIdentity();
try {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 312e309..c112843 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -4753,8 +4753,7 @@
}
void addConfigOverride(ActivityRecord r, TaskRecord task) {
- final Rect bounds = task.getLaunchBounds();
- task.updateOverrideConfiguration(bounds);
+ final Rect bounds = task.updateOverrideConfigurationFromLaunchBounds();
mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
(r.info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0, r.userId, r.info.configChanges,
@@ -4810,10 +4809,9 @@
}
private void setAppTask(ActivityRecord r, TaskRecord task) {
- final Rect bounds = task.getLaunchBounds();
- task.updateOverrideConfiguration(bounds);
+ final Rect bounds = task.updateOverrideConfigurationFromLaunchBounds();
mWindowManager.setAppTask(
- r.appToken, task.taskId, mStackId, task.getLaunchBounds(), task.mOverrideConfig);
+ r.appToken, task.taskId, mStackId, bounds, task.mOverrideConfig);
mWindowManager.setTaskResizeable(task.taskId, task.mResizeable);
r.taskConfigOverride = task.mOverrideConfig;
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index c634e0e..022b60b 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1673,7 +1673,7 @@
if (task.mResizeable && options != null) {
int stackId = options.getLaunchStackId();
if (canUseActivityOptionsLaunchBounds(options, stackId)) {
- Rect bounds = options.getLaunchBounds();
+ final Rect bounds = TaskRecord.validateBounds(options.getLaunchBounds());
task.updateOverrideConfiguration(bounds);
if (stackId == INVALID_STACK_ID) {
stackId = task.getLaunchStackId();
@@ -1841,6 +1841,7 @@
// can have the right fullscreen state.
bounds = null;
}
+ bounds = TaskRecord.validateBounds(bounds);
mTmpBounds.clear();
mTmpConfigs.clear();
@@ -1857,8 +1858,8 @@
fitWithinBounds(tempRect2, bounds);
task.updateOverrideConfiguration(tempRect2);
} else {
- task.updateOverrideConfiguration(tempTaskBounds != null
- ? tempTaskBounds : bounds);
+ task.updateOverrideConfiguration(
+ tempTaskBounds != null ? tempTaskBounds : bounds);
}
}
@@ -1973,6 +1974,7 @@
// Nothing to do here...
return true;
}
+ bounds = TaskRecord.validateBounds(bounds);
if (!mWindowManager.isValidTaskId(task.taskId)) {
// Task doesn't exist in window manager yet (e.g. was restored from recents).
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index cfa4433..6fa8950 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -1739,7 +1739,7 @@
if (options != null && (r.isResizeable() || (inTask != null && inTask.mResizeable))) {
if (mSupervisor.canUseActivityOptionsLaunchBounds(
options, options.getLaunchStackId())) {
- newBounds = options.getLaunchBounds();
+ newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
}
}
return newBounds;
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index ae987e6..f7e30c0 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -16,6 +16,7 @@
package com.android.server.am;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
@@ -1310,6 +1311,20 @@
return !mOverrideConfig.equals(oldConfig) ? mOverrideConfig : null;
}
+ Rect updateOverrideConfigurationFromLaunchBounds() {
+ final Rect bounds = validateBounds(getLaunchBounds());
+ updateOverrideConfiguration(bounds);
+ return bounds;
+ }
+
+ static Rect validateBounds(Rect bounds) {
+ if (bounds != null && bounds.isEmpty()) {
+ Slog.wtf(TAG, "Received strange task bounds: " + bounds, new Throwable());
+ return null;
+ }
+ return bounds;
+ }
+
private void reportMultiWindowModeChange() {
for (int i = mActivities.size() - 1; i >= 0; i--) {
final ActivityRecord r = mActivities.get(i);
@@ -1386,17 +1401,20 @@
/** Returns the bounds that should be used to launch this task. */
Rect getLaunchBounds() {
- final int stackId = stack.mStackId;
-
// If we're over lockscreen, forget about stack bounds and use fullscreen.
if (mService.mLockScreenShown == LOCK_SCREEN_SHOWN) {
return null;
}
- if (stack == null
- || stackId == HOME_STACK_ID
- || stackId == FULLSCREEN_WORKSPACE_STACK_ID) {
- return (mResizeable && stack != null) ? stack.mBounds : null;
+ if (stack == null) {
+ return null;
+ }
+
+ final int stackId = stack.mStackId;
+ if (stackId == HOME_STACK_ID
+ || stackId == FULLSCREEN_WORKSPACE_STACK_ID
+ || (stackId == DOCKED_STACK_ID && !mResizeable)) {
+ return mResizeable ? stack.mBounds : null;
} else if (!StackId.persistTaskBounds(stackId)) {
return stack.mBounds;
}
diff --git a/services/core/java/com/android/server/display/ColorFade.java b/services/core/java/com/android/server/display/ColorFade.java
index 835ba17..a16fcd2 100644
--- a/services/core/java/com/android/server/display/ColorFade.java
+++ b/services/core/java/com/android/server/display/ColorFade.java
@@ -587,16 +587,16 @@
Slog.e(TAG, "Unable to create surface.", ex);
return false;
}
+
+ mSurfaceControl.setLayerStack(mDisplayLayerStack);
+ mSurfaceControl.setSize(mDisplayWidth, mDisplayHeight);
+ mSurface = new Surface();
+ mSurface.copyFrom(mSurfaceControl);
+
+ mSurfaceLayout = new NaturalSurfaceLayout(mDisplayManagerInternal,
+ mDisplayId, mSurfaceControl);
+ mSurfaceLayout.onDisplayTransaction();
}
-
- mSurfaceControl.setLayerStack(mDisplayLayerStack);
- mSurfaceControl.setSize(mDisplayWidth, mDisplayHeight);
- mSurface = new Surface();
- mSurface.copyFrom(mSurfaceControl);
-
- mSurfaceLayout = new NaturalSurfaceLayout(mDisplayManagerInternal,
- mDisplayId, mSurfaceControl);
- mSurfaceLayout.onDisplayTransaction();
} finally {
SurfaceControl.closeTransaction();
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 433d887..b74b0f2 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -673,6 +673,9 @@
slowChange = false;
}
mAppliedDimming = true;
+ } else if (mAppliedDimming) {
+ slowChange = false;
+ mAppliedDimming = false;
}
// If low power mode is enabled, cut the brightness level by half
@@ -685,6 +688,9 @@
slowChange = false;
}
mAppliedLowPower = true;
+ } else if (mAppliedLowPower) {
+ slowChange = false;
+ mAppliedLowPower = false;
}
// Animate the screen brightness when the screen is on or dozing.
diff --git a/services/core/java/com/android/server/media/MediaResourceMonitorService.java b/services/core/java/com/android/server/media/MediaResourceMonitorService.java
new file mode 100644
index 0000000..50dd607
--- /dev/null
+++ b/services/core/java/com/android/server/media/MediaResourceMonitorService.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2016 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.server.media;
+
+import android.app.ActivityManager;
+import android.app.ActivityManagerNative;
+import android.content.Context;
+import android.content.Intent;
+import android.media.IMediaResourceMonitor;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Log;
+import android.util.Slog;
+import com.android.server.SystemService;
+
+import java.util.List;
+
+/** This class provides a system service that monitors media resource usage. */
+public class MediaResourceMonitorService extends SystemService {
+ private static final String TAG = "MediaResourceMonitor";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ private static final String SERVICE_NAME = "media_resource_monitor";
+
+ /*
+ * Resource types. Should be in sync with:
+ * frameworks/av/media/libmedia/MediaResource.cpp
+ */
+ private static final String RESOURCE_AUDIO_CODEC = "audio-codec";
+ private static final String RESOURCE_VIDEO_CODEC = "video-codec";
+
+ private final MediaResourceMonitorImpl mMediaResourceMonitorImpl;
+
+ public MediaResourceMonitorService(Context context) {
+ super(context);
+ mMediaResourceMonitorImpl = new MediaResourceMonitorImpl();
+ }
+
+ @Override
+ public void onStart() {
+ publishBinderService(SERVICE_NAME, mMediaResourceMonitorImpl);
+ }
+
+ class MediaResourceMonitorImpl extends IMediaResourceMonitor.Stub {
+ @Override
+ public void notifyResourceGranted(int pid, String type, String subType, long value)
+ throws RemoteException {
+ if (DEBUG) {
+ Slog.d(TAG, "notifyResourceGranted(pid=" + pid + ", type=" + type + ", subType="
+ + subType + ", value=" + value + ")");
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ String pkgNames[] = getPackageNamesFromPid(pid);
+ Integer resourceType = null;
+ if (RESOURCE_AUDIO_CODEC.equals(subType)) {
+ resourceType = Intent.EXTRA_MEDIA_RESOURCE_TYPE_AUDIO_CODEC;
+ } else if (RESOURCE_VIDEO_CODEC.equals(subType)) {
+ resourceType = Intent.EXTRA_MEDIA_RESOURCE_TYPE_VIDEO_CODEC;
+ }
+ if (pkgNames != null && resourceType != null) {
+ Intent intent = new Intent(Intent.ACTION_MEDIA_RESOURCE_GRANTED);
+ intent.putExtra(Intent.EXTRA_PACKAGES, pkgNames);
+ intent.putExtra(Intent.EXTRA_MEDIA_RESOURCE_TYPE, resourceType);
+ getContext().sendBroadcastAsUser(intent,
+ new UserHandle(ActivityManager.getCurrentUser()),
+ android.Manifest.permission.RECEIVE_MEDIA_RESOURCE_USAGE);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ private String[] getPackageNamesFromPid(int pid) {
+ try {
+ for (ActivityManager.RunningAppProcessInfo proc :
+ ActivityManagerNative.getDefault().getRunningAppProcesses()) {
+ if (proc.pid == pid) {
+ return proc.pkgList;
+ }
+ }
+ } catch (RemoteException e) {
+ Slog.w(TAG, "ActivityManager.getRunningAppProcesses() failed");
+ }
+ return null;
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index e75780f..27d6e03 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -18,7 +18,6 @@
import android.app.ActivityManager.StackId;
import android.content.res.Configuration;
-import android.content.res.Resources;
import android.graphics.Rect;
import android.os.Debug;
import android.util.EventLog;
@@ -89,6 +88,7 @@
/** Detach this stack from its display when animation completes. */
boolean mDeferDetach;
+ private boolean mUpdateBoundsAfterRotation = false;
TaskStack(WindowManagerService service, int stackId) {
mService = service;
@@ -239,6 +239,7 @@
}
void updateDisplayInfo(Rect bounds) {
+ mUpdateBoundsAfterRotation = false;
if (mDisplayContent != null) {
for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
mTasks.get(taskNdx).updateDisplayInfo(mDisplayContent);
@@ -248,6 +249,7 @@
} else if (mFullscreen) {
setBounds(null);
} else {
+ mUpdateBoundsAfterRotation = true;
mTmpRect2.set(mBounds);
final int newRotation = mDisplayContent.getDisplayInfo().rotation;
if (mRotation == newRotation) {
@@ -265,6 +267,10 @@
* yet.
*/
void updateBoundsAfterRotation() {
+ if (!mUpdateBoundsAfterRotation) {
+ return;
+ }
+ mUpdateBoundsAfterRotation = false;
final int newRotation = getDisplayInfo().rotation;
mDisplayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
if (mStackId == DOCKED_STACK_ID) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 058fa67..b09c12b 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2284,10 +2284,12 @@
void transformFromScreenToSurfaceSpace(Rect rect) {
if (mHScale >= 0) {
- rect.right = rect.left + (int)((rect.right - rect.left) / mHScale);
+ rect.left = (int) (rect.left / mHScale);
+ rect.right = (int) (rect.right / mHScale);
}
if (mVScale >= 0) {
- rect.bottom = rect.top + (int)((rect.bottom - rect.top) / mVScale);
+ rect.top = (int) (rect.top / mVScale);
+ rect.bottom = (int) (rect.bottom / mVScale);
}
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 287b39c..79786d3 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -67,6 +67,7 @@
import com.android.server.lights.LightsService;
import com.android.server.media.MediaRouterService;
import com.android.server.media.MediaSessionService;
+import com.android.server.media.MediaResourceMonitorService;
import com.android.server.media.projection.MediaProjectionManagerService;
import com.android.server.net.NetworkPolicyManagerService;
import com.android.server.net.NetworkStatsService;
@@ -1025,6 +1026,10 @@
mSystemServiceManager.startService(TvInputManagerService.class);
}
+ if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)) {
+ mSystemServiceManager.startService(MediaResourceMonitorService.class);
+ }
+
if (!disableNonCoreServices) {
traceBeginAndSlog("StartMediaRouterService");
try {