Merge "Fix VR current component changes being ignored."
diff --git a/api/current.txt b/api/current.txt
index 62365cc..35000a6 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -410,6 +410,7 @@
field public static final int colorControlHighlight = 16843820; // 0x101042c
field public static final int colorControlNormal = 16843817; // 0x1010429
field public static final int colorEdgeEffect = 16843982; // 0x10104ce
+ field public static final int colorError = 16844100; // 0x1010544
field public static final int colorFocusedHighlight = 16843663; // 0x101038f
field public static final int colorForeground = 16842800; // 0x1010030
field public static final int colorForegroundInverse = 16843270; // 0x1010206
@@ -1316,7 +1317,6 @@
field public static final int textCheckMarkInverse = 16842823; // 0x1010047
field public static final int textColor = 16842904; // 0x1010098
field public static final int textColorAlertDialogListItem = 16843526; // 0x1010306
- field public static final int textColorError = 16844100; // 0x1010544
field public static final int textColorHighlight = 16842905; // 0x1010099
field public static final int textColorHighlightInverse = 16843599; // 0x101034f
field public static final int textColorHint = 16842906; // 0x101009a
@@ -9041,6 +9041,7 @@
field public static final java.lang.String ACTION_CALL = "android.intent.action.CALL";
field public static final java.lang.String ACTION_CALL_BUTTON = "android.intent.action.CALL_BUTTON";
field public static final java.lang.String ACTION_CAMERA_BUTTON = "android.intent.action.CAMERA_BUTTON";
+ field public static final java.lang.String ACTION_CARRIER_SETUP = "android.intent.action.CARRIER_SETUP";
field public static final java.lang.String ACTION_CHOOSER = "android.intent.action.CHOOSER";
field public static final java.lang.String ACTION_CLEAR_PACKAGE = "android.intent.action.CLEAR_PACKAGE";
field public static final java.lang.String ACTION_CLOSE_SYSTEM_DIALOGS = "android.intent.action.CLOSE_SYSTEM_DIALOGS";
diff --git a/api/removed.txt b/api/removed.txt
index e467811..9baeebc 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -169,10 +169,6 @@
method public android.graphics.drawable.Drawable getBadgedDrawableForUser(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
method public android.graphics.drawable.Drawable getBadgedIconForUser(android.graphics.drawable.Drawable, android.os.UserHandle);
method public java.lang.CharSequence getBadgedLabelForUser(java.lang.CharSequence, android.os.UserHandle);
- method public deprecated boolean isUserRunningAndLocked();
- method public deprecated boolean isUserRunningAndLocked(android.os.UserHandle);
- method public deprecated boolean isUserRunningAndUnlocked();
- method public deprecated boolean isUserRunningAndUnlocked(android.os.UserHandle);
}
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 8626f1b..59dd315 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -523,6 +523,7 @@
field public static final int colorControlHighlight = 16843820; // 0x101042c
field public static final int colorControlNormal = 16843817; // 0x1010429
field public static final int colorEdgeEffect = 16843982; // 0x10104ce
+ field public static final int colorError = 16844100; // 0x1010544
field public static final int colorFocusedHighlight = 16843663; // 0x101038f
field public static final int colorForeground = 16842800; // 0x1010030
field public static final int colorForegroundInverse = 16843270; // 0x1010206
@@ -1433,7 +1434,6 @@
field public static final int textCheckMarkInverse = 16842823; // 0x1010047
field public static final int textColor = 16842904; // 0x1010098
field public static final int textColorAlertDialogListItem = 16843526; // 0x1010306
- field public static final int textColorError = 16844100; // 0x1010544
field public static final int textColorHighlight = 16842905; // 0x1010099
field public static final int textColorHighlightInverse = 16843599; // 0x101034f
field public static final int textColorHint = 16842906; // 0x101009a
@@ -9515,6 +9515,7 @@
field public static final java.lang.String ACTION_CALL = "android.intent.action.CALL";
field public static final java.lang.String ACTION_CALL_BUTTON = "android.intent.action.CALL_BUTTON";
field public static final java.lang.String ACTION_CAMERA_BUTTON = "android.intent.action.CAMERA_BUTTON";
+ field public static final java.lang.String ACTION_CARRIER_SETUP = "android.intent.action.CARRIER_SETUP";
field public static final java.lang.String ACTION_CHOOSER = "android.intent.action.CHOOSER";
field public static final java.lang.String ACTION_CLEAR_PACKAGE = "android.intent.action.CLEAR_PACKAGE";
field public static final java.lang.String ACTION_CLOSE_SYSTEM_DIALOGS = "android.intent.action.CLOSE_SYSTEM_DIALOGS";
@@ -25876,6 +25877,12 @@
method public static final boolean isChannelUriForTunerInput(android.net.Uri);
method public static final boolean isProgramUri(android.net.Uri);
field public static final java.lang.String AUTHORITY = "android.media.tv";
+ field public static final java.lang.String EXTRA_COLUMN_NAME = "android.media.tv.extra.COLUMN_NAME";
+ field public static final java.lang.String EXTRA_EXISTING_COLUMN_NAMES = "android.media.tv.extra.EXISTING_COLUMN_NAMES";
+ field public static final java.lang.String EXTRA_DATA_TYPE = "android.media.tv.extra.DATA_TYPE";
+ field public static final java.lang.String EXTRA_DEFAULT_VALUE = "android.media.tv.extra.DEFAULT_VALUE";
+ field public static final java.lang.String METHOD_ADD_COLUMN = "add_column";
+ field public static final java.lang.String METHOD_GET_COLUMNS = "get_columns";
}
public static abstract interface TvContract.BaseProgramColumns implements android.media.tv.TvContract.BaseTvColumns {
@@ -27124,7 +27131,8 @@
}
public abstract class NetworkRecommendationProvider {
- ctor public NetworkRecommendationProvider(android.os.Handler);
+ ctor public deprecated NetworkRecommendationProvider(android.os.Handler);
+ ctor public NetworkRecommendationProvider(android.content.Context, java.util.concurrent.Executor);
method public final android.os.IBinder getBinder();
method public abstract void onRequestRecommendation(android.net.RecommendationRequest, android.net.NetworkRecommendationProvider.ResultCallback);
method public abstract void onRequestScores(android.net.NetworkKey[]);
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 6773112..4642992 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -163,10 +163,6 @@
method public android.graphics.drawable.Drawable getBadgedDrawableForUser(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
method public android.graphics.drawable.Drawable getBadgedIconForUser(android.graphics.drawable.Drawable, android.os.UserHandle);
method public java.lang.CharSequence getBadgedLabelForUser(java.lang.CharSequence, android.os.UserHandle);
- method public deprecated boolean isUserRunningAndLocked();
- method public deprecated boolean isUserRunningAndLocked(android.os.UserHandle);
- method public deprecated boolean isUserRunningAndUnlocked();
- method public deprecated boolean isUserRunningAndUnlocked(android.os.UserHandle);
}
}
diff --git a/api/test-current.txt b/api/test-current.txt
index 44386be..12c2cc8 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -410,6 +410,7 @@
field public static final int colorControlHighlight = 16843820; // 0x101042c
field public static final int colorControlNormal = 16843817; // 0x1010429
field public static final int colorEdgeEffect = 16843982; // 0x10104ce
+ field public static final int colorError = 16844100; // 0x1010544
field public static final int colorFocusedHighlight = 16843663; // 0x101038f
field public static final int colorForeground = 16842800; // 0x1010030
field public static final int colorForegroundInverse = 16843270; // 0x1010206
@@ -1316,7 +1317,6 @@
field public static final int textCheckMarkInverse = 16842823; // 0x1010047
field public static final int textColor = 16842904; // 0x1010098
field public static final int textColorAlertDialogListItem = 16843526; // 0x1010306
- field public static final int textColorError = 16844100; // 0x1010544
field public static final int textColorHighlight = 16842905; // 0x1010099
field public static final int textColorHighlightInverse = 16843599; // 0x101034f
field public static final int textColorHint = 16842906; // 0x101009a
@@ -9070,6 +9070,7 @@
field public static final java.lang.String ACTION_CALL = "android.intent.action.CALL";
field public static final java.lang.String ACTION_CALL_BUTTON = "android.intent.action.CALL_BUTTON";
field public static final java.lang.String ACTION_CAMERA_BUTTON = "android.intent.action.CAMERA_BUTTON";
+ field public static final java.lang.String ACTION_CARRIER_SETUP = "android.intent.action.CARRIER_SETUP";
field public static final java.lang.String ACTION_CHOOSER = "android.intent.action.CHOOSER";
field public static final java.lang.String ACTION_CLEAR_PACKAGE = "android.intent.action.CLEAR_PACKAGE";
field public static final java.lang.String ACTION_CLOSE_SYSTEM_DIALOGS = "android.intent.action.CLOSE_SYSTEM_DIALOGS";
diff --git a/api/test-removed.txt b/api/test-removed.txt
index e467811..9baeebc 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -169,10 +169,6 @@
method public android.graphics.drawable.Drawable getBadgedDrawableForUser(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
method public android.graphics.drawable.Drawable getBadgedIconForUser(android.graphics.drawable.Drawable, android.os.UserHandle);
method public java.lang.CharSequence getBadgedLabelForUser(java.lang.CharSequence, android.os.UserHandle);
- method public deprecated boolean isUserRunningAndLocked();
- method public deprecated boolean isUserRunningAndLocked(android.os.UserHandle);
- method public deprecated boolean isUserRunningAndUnlocked();
- method public deprecated boolean isUserRunningAndUnlocked(android.os.UserHandle);
}
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 812daf8..64fc44b 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -2702,11 +2702,11 @@
}
/**
- * Specifies the time at which this notification should be canceled, if it is not already
- * canceled.
+ * Specifies a duration in milliseconds after which this notification should be canceled,
+ * if it is not already canceled.
*/
- public Builder setTimeout(long when) {
- mN.mTimeout = when;
+ public Builder setTimeout(long durationMs) {
+ mN.mTimeout = durationMs;
return this;
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 9cb3dd6..6585793 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -3346,6 +3346,17 @@
public static final int KEYGUARD_DISABLE_FEATURES_ALL = 0x7fffffff;
/**
+ * Keyguard features that when set on a managed profile that doesn't have its own challenge will
+ * affect the profile's parent user. These can also be set on the managed profile's parent
+ * {@link DevicePolicyManager} instance.
+ *
+ * @hide
+ */
+ public static final int PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER =
+ DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS
+ | DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT;
+
+ /**
* Called by an application that is administering the device to request that the storage system
* be encrypted.
* <p>
@@ -7697,7 +7708,34 @@
/**
* Called by a device owner to control the network logging feature.
*
- * <p> Network logs contain DNS lookup and connect() library call events.
+ * <p> Network logs contain DNS lookup and connect() library call events. The following library
+ * functions are recorded while network logging is active:
+ * <ul>
+ * <li>{@code getaddrinfo()}</li>
+ * <li>{@code gethostbyname()}</li>
+ * <li>{@code connect()}</li>
+ * </ul>
+ *
+ * <p> Network logging is a low-overhead tool for forensics but it is not guaranteed to use
+ * full system call logging; event reporting is enabled by default for all processes but not
+ * strongly enforced.
+ * Events from applications using alternative implementations of libc, making direct kernel
+ * calls, or deliberately obfuscating traffic may not be recorded.
+ *
+ * <p> Some common network events may not be reported. For example:
+ * <ul>
+ * <li>Applications may hardcode IP addresses to reduce the number of DNS lookups, or use
+ * an alternative system for name resolution, and so avoid calling
+ * {@code getaddrinfo()} or {@code gethostbyname}.</li>
+ * <li>Applications may use datagram sockets for performance reasons, for example
+ * for a game client. Calling {@code connect()} is unnecessary for this kind of
+ * socket, so it will not trigger a network event.</li>
+ * </ul>
+ *
+ * <p> It is possible to directly intercept layer 3 traffic leaving the device using an
+ * always-on VPN service.
+ * See {@link #setAlwaysOnVpnPackage(ComponentName, String, boolean)}
+ * and {@link android.net.VpnService} for details.
*
* <p><strong>Note:</strong> The device owner won't be able to retrieve network logs if there
* are unaffiliated secondary users or profiles on the device, regardless of whether the
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 4480b41..687d590 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -500,6 +500,7 @@
public ContentResolver(Context context) {
mContext = context != null ? context : ActivityThread.currentApplication();
mPackageName = mContext.getOpPackageName();
+ mTargetSdkVersion = mContext.getApplicationInfo().targetSdkVersion;
}
/** @hide */
@@ -1868,13 +1869,18 @@
/**
* Register an observer class that gets callbacks when data identified by a
* given content URI changes.
+ * <p>
+ * Starting in {@link android.os.Build.VERSION_CODES#O}, all content
+ * notifications must be backed by a valid {@link ContentProvider}.
*
- * @param uri The URI to watch for changes. This can be a specific row URI, or a base URI
- * for a whole class of content.
- * @param notifyForDescendants When false, the observer will be notified whenever a
- * change occurs to the exact URI specified by <code>uri</code> or to one of the
- * URI's ancestors in the path hierarchy. When true, the observer will also be notified
- * whenever a change occurs to the URI's descendants in the path hierarchy.
+ * @param uri The URI to watch for changes. This can be a specific row URI,
+ * or a base URI for a whole class of content.
+ * @param notifyForDescendants When false, the observer will be notified
+ * whenever a change occurs to the exact URI specified by
+ * <code>uri</code> or to one of the URI's ancestors in the path
+ * hierarchy. When true, the observer will also be notified
+ * whenever a change occurs to the URI's descendants in the path
+ * hierarchy.
* @param observer The object that receives callbacks when changes occur.
* @see #unregisterContentObserver
*/
@@ -1894,7 +1900,7 @@
ContentObserver observer, @UserIdInt int userHandle) {
try {
getContentService().registerContentObserver(uri, notifyForDescendents,
- observer.getContentObserver(), userHandle);
+ observer.getContentObserver(), userHandle, mTargetSdkVersion);
} catch (RemoteException e) {
}
}
@@ -1918,16 +1924,22 @@
}
/**
- * Notify registered observers that a row was updated and attempt to sync changes
- * to the network.
- * To register, call {@link #registerContentObserver(android.net.Uri , boolean, android.database.ContentObserver) registerContentObserver()}.
- * By default, CursorAdapter objects will get this notification.
+ * Notify registered observers that a row was updated and attempt to sync
+ * changes to the network.
+ * <p>
+ * To observe events sent through this call, use
+ * {@link #registerContentObserver(Uri, boolean, ContentObserver)}.
+ * <p>
+ * Starting in {@link android.os.Build.VERSION_CODES#O}, all content
+ * notifications must be backed by a valid {@link ContentProvider}.
*
* @param uri The uri of the content that was changed.
- * @param observer The observer that originated the change, may be <code>null</null>.
- * The observer that originated the change will only receive the notification if it
- * has requested to receive self-change notifications by implementing
- * {@link ContentObserver#deliverSelfNotifications()} to return true.
+ * @param observer The observer that originated the change, may be
+ * <code>null</null>. The observer that originated the change
+ * will only receive the notification if it has requested to
+ * receive self-change notifications by implementing
+ * {@link ContentObserver#deliverSelfNotifications()} to return
+ * true.
*/
public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer) {
notifyChange(uri, observer, true /* sync to network */);
@@ -1935,17 +1947,25 @@
/**
* Notify registered observers that a row was updated.
- * To register, call {@link #registerContentObserver(android.net.Uri , boolean, android.database.ContentObserver) registerContentObserver()}.
- * By default, CursorAdapter objects will get this notification.
- * If syncToNetwork is true, this will attempt to schedule a local sync using the sync
- * adapter that's registered for the authority of the provided uri. No account will be
- * passed to the sync adapter, so all matching accounts will be synchronized.
+ * <p>
+ * To observe events sent through this call, use
+ * {@link #registerContentObserver(Uri, boolean, ContentObserver)}.
+ * <p>
+ * If syncToNetwork is true, this will attempt to schedule a local sync
+ * using the sync adapter that's registered for the authority of the
+ * provided uri. No account will be passed to the sync adapter, so all
+ * matching accounts will be synchronized.
+ * <p>
+ * Starting in {@link android.os.Build.VERSION_CODES#O}, all content
+ * notifications must be backed by a valid {@link ContentProvider}.
*
* @param uri The uri of the content that was changed.
- * @param observer The observer that originated the change, may be <code>null</null>.
- * The observer that originated the change will only receive the notification if it
- * has requested to receive self-change notifications by implementing
- * {@link ContentObserver#deliverSelfNotifications()} to return true.
+ * @param observer The observer that originated the change, may be
+ * <code>null</null>. The observer that originated the change
+ * will only receive the notification if it has requested to
+ * receive self-change notifications by implementing
+ * {@link ContentObserver#deliverSelfNotifications()} to return
+ * true.
* @param syncToNetwork If true, same as {@link #NOTIFY_SYNC_TO_NETWORK}.
* @see #requestSync(android.accounts.Account, String, android.os.Bundle)
*/
@@ -1961,17 +1981,25 @@
/**
* Notify registered observers that a row was updated.
- * To register, call {@link #registerContentObserver(android.net.Uri, boolean, android.database.ContentObserver) registerContentObserver()}.
- * By default, CursorAdapter objects will get this notification.
- * If syncToNetwork is true, this will attempt to schedule a local sync using the sync
- * adapter that's registered for the authority of the provided uri. No account will be
- * passed to the sync adapter, so all matching accounts will be synchronized.
+ * <p>
+ * To observe events sent through this call, use
+ * {@link #registerContentObserver(Uri, boolean, ContentObserver)}.
+ * <p>
+ * If syncToNetwork is true, this will attempt to schedule a local sync
+ * using the sync adapter that's registered for the authority of the
+ * provided uri. No account will be passed to the sync adapter, so all
+ * matching accounts will be synchronized.
+ * <p>
+ * Starting in {@link android.os.Build.VERSION_CODES#O}, all content
+ * notifications must be backed by a valid {@link ContentProvider}.
*
* @param uri The uri of the content that was changed.
- * @param observer The observer that originated the change, may be <code>null</null>.
- * The observer that originated the change will only receive the notification if it
- * has requested to receive self-change notifications by implementing
- * {@link ContentObserver#deliverSelfNotifications()} to return true.
+ * @param observer The observer that originated the change, may be
+ * <code>null</null>. The observer that originated the change
+ * will only receive the notification if it has requested to
+ * receive self-change notifications by implementing
+ * {@link ContentObserver#deliverSelfNotifications()} to return
+ * true.
* @param flags Additional flags: {@link #NOTIFY_SYNC_TO_NETWORK}.
* @see #requestSync(android.accounts.Account, String, android.os.Bundle)
*/
@@ -1997,7 +2025,7 @@
uri, observer == null ? null : observer.getContentObserver(),
observer != null && observer.deliverSelfNotifications(),
syncToNetwork ? NOTIFY_SYNC_TO_NETWORK : 0,
- userHandle);
+ userHandle, mTargetSdkVersion);
} catch (RemoteException e) {
}
}
@@ -2013,7 +2041,7 @@
getContentService().notifyChange(
uri, observer == null ? null : observer.getContentObserver(),
observer != null && observer.deliverSelfNotifications(), flags,
- userHandle);
+ userHandle, mTargetSdkVersion);
} catch (RemoteException e) {
}
}
@@ -2932,6 +2960,7 @@
private final Context mContext;
final String mPackageName;
+ final int mTargetSdkVersion;
private static final String TAG = "ContentResolver";
diff --git a/core/java/android/content/IContentService.aidl b/core/java/android/content/IContentService.aidl
index 3446e03..c500116 100644
--- a/core/java/android/content/IContentService.aidl
+++ b/core/java/android/content/IContentService.aidl
@@ -42,7 +42,7 @@
* USER_CURRENT are properly handled.
*/
void registerContentObserver(in Uri uri, boolean notifyForDescendants,
- IContentObserver observer, int userHandle);
+ IContentObserver observer, int userHandle, int targetSdkVersion);
/**
* Notify observers of a particular user's view of the provider.
@@ -53,7 +53,7 @@
*/
void notifyChange(in Uri uri, IContentObserver observer,
boolean observerWantsSelfNotifications, int flags,
- int userHandle);
+ int userHandle, int targetSdkVersion);
void requestSync(in Account account, String authority, in Bundle extras);
/**
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 28068c5..870db217 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1115,6 +1115,15 @@
public static final String ACTION_SIM_ACTIVATION_REQUEST =
"android.intent.action.SIM_ACTIVATION_REQUEST";
/**
+ * Activity Action: Main entry point for carrier setup apps.
+ * <p>Carrier apps that provide an implementation for this action may be invoked to configure
+ * carrier service and typically require
+ * {@link android.telephony.TelephonyManager#hasCarrierPrivileges() carrier privileges} to
+ * fulfill their duties.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_CARRIER_SETUP = "android.intent.action.CARRIER_SETUP";
+ /**
* Activity Action: Send a message to someone specified by the data.
* <p>Input: {@link #getData} is URI describing the target.
* <p>Output: nothing.
@@ -9260,6 +9269,13 @@
mClipData.prepareToLeaveProcess(leavingPackage, getFlags());
}
+ if (mExtras != null && !mExtras.isParcelled()) {
+ final Object intent = mExtras.get(Intent.EXTRA_INTENT);
+ if (intent instanceof Intent) {
+ ((Intent) intent).prepareToLeaveProcess(leavingPackage);
+ }
+ }
+
if (mAction != null && mData != null && StrictMode.vmFileUriExposureEnabled()
&& leavingPackage) {
switch (mAction) {
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 5733982..6646402 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -624,8 +624,10 @@
* should be installed as forward locked, i.e. only the app itself should
* have access to its code and non-resource assets.
*
+ * @deprecated new installs into ASEC containers are no longer supported.
* @hide
*/
+ @Deprecated
public static final int INSTALL_FORWARD_LOCK = 0x00000001;
/**
@@ -648,8 +650,11 @@
* Flag parameter for {@link #installPackage} to indicate that this package
* must be installed to an ASEC on a {@link VolumeInfo#TYPE_PUBLIC}.
*
+ * @deprecated new installs into ASEC containers are no longer supported;
+ * use adoptable storage instead.
* @hide
*/
+ @Deprecated
public static final int INSTALL_EXTERNAL = 0x00000008;
/**
diff --git a/core/java/android/net/INetworkScoreService.aidl b/core/java/android/net/INetworkScoreService.aidl
index f249daf..362ea9d 100644
--- a/core/java/android/net/INetworkScoreService.aidl
+++ b/core/java/android/net/INetworkScoreService.aidl
@@ -18,7 +18,7 @@
import android.net.INetworkScoreCache;
import android.net.NetworkKey;
-import android.net.NetworkScorerAppManager;
+import android.net.NetworkScorerAppData;
import android.net.RecommendationRequest;
import android.net.RecommendationResult;
import android.net.ScoredNetwork;
@@ -135,11 +135,11 @@
/**
* Returns metadata about the active scorer or <code>null</code> if there is no active scorer.
*/
- NetworkScorerAppManager.NetworkScorerAppData getActiveScorer();
+ NetworkScorerAppData getActiveScorer();
/**
* Returns the list of available scorer apps. The list will be empty if there are
* no valid scorers.
*/
- List<NetworkScorerAppManager.NetworkScorerAppData> getAllValidScorers();
+ List<NetworkScorerAppData> getAllValidScorers();
}
diff --git a/core/java/android/net/NetworkRecommendationProvider.java b/core/java/android/net/NetworkRecommendationProvider.java
index 8395864..271b0a7 100644
--- a/core/java/android/net/NetworkRecommendationProvider.java
+++ b/core/java/android/net/NetworkRecommendationProvider.java
@@ -1,6 +1,8 @@
package android.net;
+import android.Manifest.permission;
import android.annotation.SystemApi;
+import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
@@ -10,8 +12,10 @@
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
import java.util.Objects;
+import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
/**
@@ -32,6 +36,7 @@
/**
* Constructs a new instance.
* @param handler indicates which thread to use when handling requests. Cannot be {@code null}.
+ * @deprecated use {@link #NetworkRecommendationProvider(Context, Executor)}
*/
public NetworkRecommendationProvider(Handler handler) {
if (handler == null) {
@@ -41,6 +46,17 @@
}
/**
+ * Constructs a new instance.
+ * @param context the current context instance. Cannot be {@code null}.
+ * @param executor used to execute the incoming requests. Cannot be {@code null}.
+ */
+ public NetworkRecommendationProvider(Context context, Executor executor) {
+ Preconditions.checkNotNull(context);
+ Preconditions.checkNotNull(executor);
+ mService = new ServiceWrapper(context, executor);
+ }
+
+ /**
* Invoked when a recommendation has been requested.
*
* @param request a {@link RecommendationRequest} instance containing additional
@@ -130,17 +146,28 @@
* A wrapper around INetworkRecommendationProvider that dispatches to the provided Handler.
*/
private final class ServiceWrapper extends INetworkRecommendationProvider.Stub {
+ private final Context mContext;
+ private final Executor mExecutor;
private final Handler mHandler;
ServiceWrapper(Handler handler) {
mHandler = handler;
+ mExecutor = null;
+ mContext = null;
+ }
+
+ ServiceWrapper(Context context, Executor executor) {
+ mContext = context;
+ mExecutor = executor;
+ mHandler = null;
}
@Override
public void requestRecommendation(final RecommendationRequest request,
final IRemoteCallback callback, final int sequence) throws RemoteException {
+ enforceCallingPermission();
if (VERBOSE) Log.v(TAG, "requestRecommendation(seq=" + sequence + ")");
- mHandler.post(new Runnable() {
+ execute(new Runnable() {
@Override
public void run() {
if (VERBOSE) {
@@ -154,8 +181,9 @@
@Override
public void requestScores(final NetworkKey[] networks) throws RemoteException {
+ enforceCallingPermission();
if (networks != null && networks.length > 0) {
- mHandler.post(new Runnable() {
+ execute(new Runnable() {
@Override
public void run() {
onRequestScores(networks);
@@ -163,5 +191,20 @@
});
}
}
+
+ private void execute(Runnable command) {
+ if (mExecutor != null) {
+ mExecutor.execute(command);
+ } else {
+ mHandler.post(command);
+ }
+ }
+
+ private void enforceCallingPermission() {
+ if (mContext != null) {
+ mContext.enforceCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES,
+ "Permission denied.");
+ }
+ }
}
}
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index edfaee4..815d480 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -18,7 +18,6 @@
import static android.net.NetworkRecommendationProvider.EXTRA_RECOMMENDATION_RESULT;
-import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -26,7 +25,6 @@
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.content.Context;
-import android.net.NetworkScorerAppManager.NetworkScorerAppData;
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteCallback;
diff --git a/core/java/android/net/NetworkScorerAppManager.aidl b/core/java/android/net/NetworkScorerAppData.aidl
similarity index 91%
rename from core/java/android/net/NetworkScorerAppManager.aidl
rename to core/java/android/net/NetworkScorerAppData.aidl
index d968343..ee7f1d1 100644
--- a/core/java/android/net/NetworkScorerAppManager.aidl
+++ b/core/java/android/net/NetworkScorerAppData.aidl
@@ -16,4 +16,4 @@
package android.net;
-parcelable NetworkScorerAppManager.NetworkScorerAppData;
+parcelable NetworkScorerAppData;
diff --git a/core/java/android/net/NetworkScorerAppData.java b/core/java/android/net/NetworkScorerAppData.java
new file mode 100644
index 0000000..fca0a2e
--- /dev/null
+++ b/core/java/android/net/NetworkScorerAppData.java
@@ -0,0 +1,99 @@
+package android.net;
+
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Holds metadata about a discovered network scorer/recommendation application.
+ *
+ * @hide
+ */
+public final class NetworkScorerAppData implements Parcelable {
+ /** UID of the scorer app. */
+ public final int packageUid;
+ private final ComponentName mRecommendationService;
+ /**
+ * The {@link ComponentName} of the Activity to start before enabling the "connect to open
+ * wifi networks automatically" feature.
+ */
+ private final ComponentName mEnableUseOpenWifiActivity;
+
+ public NetworkScorerAppData(int packageUid, ComponentName recommendationServiceComp,
+ ComponentName enableUseOpenWifiActivity) {
+ this.packageUid = packageUid;
+ this.mRecommendationService = recommendationServiceComp;
+ this.mEnableUseOpenWifiActivity = enableUseOpenWifiActivity;
+ }
+
+ protected NetworkScorerAppData(Parcel in) {
+ packageUid = in.readInt();
+ mRecommendationService = ComponentName.readFromParcel(in);
+ mEnableUseOpenWifiActivity = ComponentName.readFromParcel(in);
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(packageUid);
+ ComponentName.writeToParcel(mRecommendationService, dest);
+ ComponentName.writeToParcel(mEnableUseOpenWifiActivity, dest);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Creator<NetworkScorerAppData> CREATOR =
+ new Creator<NetworkScorerAppData>() {
+ @Override
+ public NetworkScorerAppData createFromParcel(Parcel in) {
+ return new NetworkScorerAppData(in);
+ }
+
+ @Override
+ public NetworkScorerAppData[] newArray(int size) {
+ return new NetworkScorerAppData[size];
+ }
+ };
+
+ public String getRecommendationServicePackageName() {
+ return mRecommendationService.getPackageName();
+ }
+
+ public ComponentName getRecommendationServiceComponent() {
+ return mRecommendationService;
+ }
+
+ @Nullable
+ public ComponentName getEnableUseOpenWifiActivity() {
+ return mEnableUseOpenWifiActivity;
+ }
+
+ @Override
+ public String toString() {
+ return "NetworkScorerAppData{" +
+ "packageUid=" + packageUid +
+ ", mRecommendationService=" + mRecommendationService +
+ ", mEnableUseOpenWifiActivity=" + mEnableUseOpenWifiActivity +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ NetworkScorerAppData that = (NetworkScorerAppData) o;
+ return packageUid == that.packageUid &&
+ Objects.equals(mRecommendationService, that.mRecommendationService) &&
+ Objects.equals(mEnableUseOpenWifiActivity, that.mEnableUseOpenWifiActivity);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(packageUid, mRecommendationService, mEnableUseOpenWifiActivity);
+ }
+}
diff --git a/core/java/android/net/NetworkScorerAppManager.java b/core/java/android/net/NetworkScorerAppManager.java
deleted file mode 100644
index bbc1c79..0000000
--- a/core/java/android/net/NetworkScorerAppManager.java
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * 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.net;
-
-import android.Manifest.permission;
-import android.annotation.Nullable;
-import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.content.pm.ServiceInfo;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.internal.R;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * Internal class for discovering and managing the network scorer/recommendation application.
- *
- * @hide
- */
-public class NetworkScorerAppManager {
- private static final String TAG = "NetworkScorerAppManager";
- private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
- private final Context mContext;
-
- public NetworkScorerAppManager(Context context) {
- mContext = context;
- }
-
- /**
- * Holds metadata about a discovered network scorer/recommendation application.
- */
- public static final class NetworkScorerAppData implements Parcelable {
- /** UID of the scorer app. */
- public final int packageUid;
- private final ComponentName mRecommendationService;
- /**
- * The {@link ComponentName} of the Activity to start before enabling the "connect to open
- * wifi networks automatically" feature.
- */
- private final ComponentName mEnableUseOpenWifiActivity;
-
- public NetworkScorerAppData(int packageUid, ComponentName recommendationServiceComp,
- ComponentName enableUseOpenWifiActivity) {
- this.packageUid = packageUid;
- this.mRecommendationService = recommendationServiceComp;
- this.mEnableUseOpenWifiActivity = enableUseOpenWifiActivity;
- }
-
- protected NetworkScorerAppData(Parcel in) {
- packageUid = in.readInt();
- mRecommendationService = ComponentName.readFromParcel(in);
- mEnableUseOpenWifiActivity = ComponentName.readFromParcel(in);
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(packageUid);
- ComponentName.writeToParcel(mRecommendationService, dest);
- ComponentName.writeToParcel(mEnableUseOpenWifiActivity, dest);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Creator<NetworkScorerAppData> CREATOR =
- new Creator<NetworkScorerAppData>() {
- @Override
- public NetworkScorerAppData createFromParcel(Parcel in) {
- return new NetworkScorerAppData(in);
- }
-
- @Override
- public NetworkScorerAppData[] newArray(int size) {
- return new NetworkScorerAppData[size];
- }
- };
-
- public String getRecommendationServicePackageName() {
- return mRecommendationService.getPackageName();
- }
-
- public ComponentName getRecommendationServiceComponent() {
- return mRecommendationService;
- }
-
- @Nullable public ComponentName getEnableUseOpenWifiActivity() {
- return mEnableUseOpenWifiActivity;
- }
-
- @Override
- public String toString() {
- return "NetworkScorerAppData{" +
- "packageUid=" + packageUid +
- ", mRecommendationService=" + mRecommendationService +
- ", mEnableUseOpenWifiActivity=" + mEnableUseOpenWifiActivity +
- '}';
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- NetworkScorerAppData that = (NetworkScorerAppData) o;
- return packageUid == that.packageUid &&
- Objects.equals(mRecommendationService, that.mRecommendationService) &&
- Objects.equals(mEnableUseOpenWifiActivity, that.mEnableUseOpenWifiActivity);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(packageUid, mRecommendationService, mEnableUseOpenWifiActivity);
- }
- }
-
- /**
- * Returns the list of available scorer apps. The list will be empty if there are
- * no valid scorers.
- */
- public List<NetworkScorerAppData> getAllValidScorers() {
- return Collections.emptyList();
- }
-
- /**
- * @return A {@link NetworkScorerAppData} instance containing information about the
- * best configured network recommendation provider installed or {@code null}
- * if none of the configured packages can recommend networks.
- *
- * <p>A network recommendation provider is any application which:
- * <ul>
- * <li>Is listed in the <code>config_networkRecommendationPackageNames</code> config.
- * <li>Declares the {@link android.Manifest.permission#SCORE_NETWORKS} permission.
- * <li>Includes a Service for {@link NetworkScoreManager#ACTION_RECOMMEND_NETWORKS}.
- * </ul>
- */
- public NetworkScorerAppData getNetworkRecommendationProviderData() {
- // Network recommendation apps can only run as the primary user right now.
- // http://b/23422763
- if (UserHandle.getCallingUserId() != UserHandle.USER_SYSTEM) {
- return null;
- }
-
- final List<String> potentialPkgs = getPotentialRecommendationProviderPackages();
- if (potentialPkgs.isEmpty()) {
- if (DEBUG) {
- Log.d(TAG, "No Network Recommendation Providers specified.");
- }
- return null;
- }
-
- for (int i = 0; i < potentialPkgs.size(); i++) {
- final String potentialPkg = potentialPkgs.get(i);
-
- // Look for the recommendation service class and required receiver.
- final ServiceInfo serviceInfo = findRecommendationService(potentialPkg);
- if (serviceInfo != null) {
- final ComponentName serviceComponentName =
- new ComponentName(potentialPkg, serviceInfo.name);
- final ComponentName useOpenWifiNetworksActivity =
- findUseOpenWifiNetworksActivity(serviceInfo);
- return new NetworkScorerAppData(serviceInfo.applicationInfo.uid,
- serviceComponentName, useOpenWifiNetworksActivity);
- } else {
- if (DEBUG) {
- Log.d(TAG, potentialPkg + " does not have the required components, skipping.");
- }
- }
- }
-
- // None of the configured packages are valid.
- return null;
- }
-
- @Nullable private ComponentName findUseOpenWifiNetworksActivity(ServiceInfo serviceInfo) {
- if (serviceInfo.metaData == null) {
- if (DEBUG) {
- Log.d(TAG, "No metadata found on recommendation service.");
- }
- return null;
- }
- final String useOpenWifiPackage = serviceInfo.metaData
- .getString(NetworkScoreManager.USE_OPEN_WIFI_PACKAGE_META_DATA);
- if (TextUtils.isEmpty(useOpenWifiPackage)) {
- if (DEBUG) {
- Log.d(TAG, "No use_open_wifi_package metadata found.");
- }
- return null;
- }
- final Intent enableUseOpenWifiIntent = new Intent(NetworkScoreManager.ACTION_CUSTOM_ENABLE)
- .setPackage(useOpenWifiPackage);
- final ResolveInfo resolveActivityInfo = mContext.getPackageManager()
- .resolveActivity(enableUseOpenWifiIntent, 0 /* flags */);
- if (VERBOSE) {
- Log.d(TAG, "Resolved " + enableUseOpenWifiIntent + " to " + serviceInfo);
- }
-
- if (resolveActivityInfo != null && resolveActivityInfo.activityInfo != null) {
- return resolveActivityInfo.activityInfo.getComponentName();
- }
-
- return null;
- }
-
- /**
- * @return A priority order list of package names that have been granted the
- * permission needed for them to act as a network recommendation provider.
- * The packages in the returned list may not contain the other required
- * network recommendation provider components so additional checks are required
- * before making a package the network recommendation provider.
- */
- public List<String> getPotentialRecommendationProviderPackages() {
- final String[] packageArray = mContext.getResources().getStringArray(
- R.array.config_networkRecommendationPackageNames);
- if (packageArray == null || packageArray.length == 0) {
- if (DEBUG) {
- Log.d(TAG, "No Network Recommendation Providers specified.");
- }
- return Collections.emptyList();
- }
-
- if (VERBOSE) {
- Log.d(TAG, "Configured packages: " + TextUtils.join(", ", packageArray));
- }
-
- List<String> packages = new ArrayList<>();
- final PackageManager pm = mContext.getPackageManager();
- for (String potentialPkg : packageArray) {
- if (pm.checkPermission(permission.SCORE_NETWORKS, potentialPkg)
- == PackageManager.PERMISSION_GRANTED) {
- packages.add(potentialPkg);
- } else {
- if (DEBUG) {
- Log.d(TAG, potentialPkg + " has not been granted " + permission.SCORE_NETWORKS
- + ", skipping.");
- }
- }
- }
-
- return packages;
- }
-
- @Nullable private ServiceInfo findRecommendationService(String packageName) {
- final PackageManager pm = mContext.getPackageManager();
- final int resolveFlags = PackageManager.GET_META_DATA;
- final Intent serviceIntent = new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS);
- serviceIntent.setPackage(packageName);
- final ResolveInfo resolveServiceInfo =
- pm.resolveService(serviceIntent, resolveFlags);
-
- if (VERBOSE) {
- Log.d(TAG, "Resolved " + serviceIntent + " to " + resolveServiceInfo);
- }
-
- if (resolveServiceInfo != null && resolveServiceInfo.serviceInfo != null) {
- return resolveServiceInfo.serviceInfo;
- }
-
- if (VERBOSE) {
- Log.v(TAG, packageName + " does not have a service for " + serviceIntent);
- }
- return null;
- }
-
- /**
- * Get the application to use for scoring networks.
- *
- * @return the scorer app info or null if scoring is disabled (including if no scorer was ever
- * selected) or if the previously-set scorer is no longer a valid scorer app (e.g. because
- * it was disabled or uninstalled).
- */
- @Nullable
- public NetworkScorerAppData getActiveScorer() {
- if (isNetworkRecommendationsDisabled()) {
- // If recommendations are disabled then there can't be an active scorer.
- return null;
- }
-
- // Otherwise return the recommendation provider (which may be null).
- return getNetworkRecommendationProviderData();
- }
-
- /**
- * Set the specified package as the default scorer application.
- *
- * <p>The caller must have permission to write to {@link android.provider.Settings.Global}.
- *
- * @param packageName the packageName of the new scorer to use. If null, scoring will be
- * disabled. Otherwise, the scorer will only be set if it is a valid scorer application.
- * @return true if the scorer was changed, or false if the package is not a valid scorer or
- * a valid network recommendation provider exists.
- * @deprecated Scorers are now selected from a configured list.
- */
- @Deprecated
- public boolean setActiveScorer(String packageName) {
- return false;
- }
-
- private boolean isNetworkRecommendationsDisabled() {
- final ContentResolver cr = mContext.getContentResolver();
- // A value of 1 indicates enabled.
- return Settings.Global.getInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0) != 1;
- }
-}
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index d299672..63d3e7a 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -18,8 +18,10 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.os.LooperProto;
import android.util.Log;
import android.util.Printer;
+import android.util.proto.ProtoOutputStream;
/**
* Class used to run a message loop for a thread. Threads by default do
@@ -289,6 +291,16 @@
mQueue.dump(pw, prefix + " ");
}
+ /** @hide */
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long looperToken = proto.start(fieldId);
+ proto.write(LooperProto.THREAD_NAME, mThread.getName());
+ proto.write(LooperProto.THREAD_ID, mThread.getId());
+ proto.write(LooperProto.IDENTITY_HASH_CODE, System.identityHashCode(this));
+ mQueue.writeToProto(proto, LooperProto.QUEUE);
+ proto.end(looperToken);
+ }
+
@Override
public String toString() {
return "Looper (" + mThread.getName() + ", tid " + mThread.getId()
diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java
index 8c75847..d066db1 100644
--- a/core/java/android/os/Message.java
+++ b/core/java/android/os/Message.java
@@ -16,13 +16,15 @@
package android.os;
+import android.os.MessageProto;
import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
/**
- *
+ *
* Defines a message containing a description and arbitrary data object that can be
* sent to a {@link Handler}. This object contains two extra int fields and an
- * extra object field that allow you to not do allocations in many cases.
+ * extra object field that allow you to not do allocations in many cases.
*
* <p class="note">While the constructor of Message is public, the best way to get
* one of these is to call {@link #obtain Message.obtain()} or one of the
@@ -31,7 +33,7 @@
*/
public final class Message implements Parcelable {
/**
- * User-defined message code so that the recipient can identify
+ * User-defined message code so that the recipient can identify
* what this message is about. Each {@link Handler} has its own name-space
* for message codes, so you do not need to worry about yours conflicting
* with other handlers.
@@ -43,7 +45,7 @@
* {@link #setData(Bundle) setData()} if you only need to store a
* few integer values.
*/
- public int arg1;
+ public int arg1;
/**
* arg1 and arg2 are lower-cost alternatives to using
@@ -58,7 +60,7 @@
* be non-null if it contains a Parcelable of a framework class (not one
* implemented by the application). For other data transfer use
* {@link #setData}.
- *
+ *
* <p>Note that Parcelable objects here are not supported prior to
* the {@link android.os.Build.VERSION_CODES#FROYO} release.
*/
@@ -97,13 +99,13 @@
/*package*/ int flags;
/*package*/ long when;
-
+
/*package*/ Bundle data;
-
+
/*package*/ Handler target;
-
+
/*package*/ Runnable callback;
-
+
// sometimes we store linked lists of these things
/*package*/ Message next;
@@ -216,9 +218,9 @@
}
/**
- * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>,
+ * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>,
* <em>arg1</em>, and <em>arg2</em> members.
- *
+ *
* @param h The <em>target</em> value to set.
* @param what The <em>what</em> value to set.
* @param arg1 The <em>arg1</em> value to set.
@@ -236,9 +238,9 @@
}
/**
- * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>,
+ * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>,
* <em>arg1</em>, <em>arg2</em>, and <em>obj</em> members.
- *
+ *
* @param h The <em>target</em> value to set.
* @param what The <em>what</em> value to set.
* @param arg1 The <em>arg1</em> value to set.
@@ -246,7 +248,7 @@
* @param obj The <em>obj</em> value to set.
* @return A Message object from the global pool.
*/
- public static Message obtain(Handler h, int what,
+ public static Message obtain(Handler h, int what,
int arg1, int arg2, Object obj) {
Message m = obtain();
m.target = h;
@@ -339,7 +341,7 @@
public long getWhen() {
return when;
}
-
+
public void setTarget(Handler target) {
this.target = target;
}
@@ -367,8 +369,8 @@
public Runnable getCallback() {
return callback;
}
-
- /**
+
+ /**
* Obtains a Bundle of arbitrary data associated with this
* event, lazily creating it if necessary. Set this value by calling
* {@link #setData(Bundle)}. Note that when transferring data across
@@ -383,11 +385,11 @@
if (data == null) {
data = new Bundle();
}
-
+
return data;
}
- /**
+ /**
* Like getData(), but does not lazily create the Bundle. A null
* is returned if the Bundle does not already exist. See
* {@link #getData} for further information on this.
@@ -401,7 +403,7 @@
/**
* Sets a Bundle of arbitrary data values. Use arg1 and arg2 members
* as a lower cost way to send a few simple integer values, if you can.
- * @see #getData()
+ * @see #getData()
* @see #peekData()
*/
public void setData(Bundle data) {
@@ -520,6 +522,37 @@
return b.toString();
}
+ void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long messageToken = proto.start(fieldId);
+ proto.write(MessageProto.WHEN, when);
+
+ if (target != null) {
+ if (callback != null) {
+ proto.write(MessageProto.CALLBACK, callback.getClass().getName());
+ } else {
+ proto.write(MessageProto.WHAT, what);
+ }
+
+ if (arg1 != 0) {
+ proto.write(MessageProto.ARG1, arg1);
+ }
+
+ if (arg2 != 0) {
+ proto.write(MessageProto.ARG2, arg2);
+ }
+
+ if (obj != null) {
+ proto.write(MessageProto.OBJ, obj.toString());
+ }
+
+ proto.write(MessageProto.TARGET, target.getClass().getName());
+ } else {
+ proto.write(MessageProto.BARRIER, arg1);
+ }
+
+ proto.end(messageToken);
+ }
+
public static final Parcelable.Creator<Message> CREATOR
= new Parcelable.Creator<Message>() {
public Message createFromParcel(Parcel source) {
@@ -527,12 +560,12 @@
msg.readFromParcel(source);
return msg;
}
-
+
public Message[] newArray(int size) {
return new Message[size];
}
};
-
+
public int describeContents() {
return 0;
}
diff --git a/core/java/android/os/MessageQueue.java b/core/java/android/os/MessageQueue.java
index 4f2e968..2a8c52e 100644
--- a/core/java/android/os/MessageQueue.java
+++ b/core/java/android/os/MessageQueue.java
@@ -18,9 +18,11 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.os.MessageQueueProto;
import android.util.Log;
import android.util.Printer;
import android.util.SparseArray;
+import android.util.proto.ProtoOutputStream;
import java.io.FileDescriptor;
import java.lang.annotation.Retention;
@@ -31,7 +33,7 @@
* Low-level class holding the list of messages to be dispatched by a
* {@link Looper}. Messages are not added directly to a MessageQueue,
* but rather through {@link Handler} objects associated with the Looper.
- *
+ *
* <p>You can retrieve the MessageQueue for the current thread with
* {@link Looper#myQueue() Looper.myQueue()}.
*/
@@ -770,6 +772,18 @@
}
}
+ void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long messageQueueToken = proto.start(fieldId);
+ synchronized (this) {
+ for (Message msg = mMessages; msg != null; msg = msg.next) {
+ msg.writeToProto(proto, MessageQueueProto.MESSAGES);
+ }
+ proto.write(MessageQueueProto.IS_POLLING_LOCKED, isPollingLocked());
+ proto.write(MessageQueueProto.IS_QUITTING, mQuitting);
+ }
+ proto.end(messageQueueToken);
+ }
+
/**
* Callback interface for discovering when a thread is going to block
* waiting for more messages.
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 21c70f9..13a495e 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1097,40 +1097,6 @@
}
}
- /** @removed */
- @Deprecated
- public boolean isUserRunningAndLocked() {
- return isUserRunningAndLocked(Process.myUserHandle());
- }
-
- /** @removed */
- @Deprecated
- public boolean isUserRunningAndLocked(UserHandle user) {
- try {
- return ActivityManager.getService().isUserRunning(
- user.getIdentifier(), ActivityManager.FLAG_AND_LOCKED);
- } catch (RemoteException re) {
- throw re.rethrowFromSystemServer();
- }
- }
-
- /** @removed */
- @Deprecated
- public boolean isUserRunningAndUnlocked() {
- return isUserRunningAndUnlocked(Process.myUserHandle());
- }
-
- /** @removed */
- @Deprecated
- public boolean isUserRunningAndUnlocked(UserHandle user) {
- try {
- return ActivityManager.getService().isUserRunning(
- user.getIdentifier(), ActivityManager.FLAG_AND_UNLOCKED);
- } catch (RemoteException re) {
- throw re.rethrowFromSystemServer();
- }
- }
-
/**
* Return whether the calling user is running in an "unlocked" state.
* <p>
diff --git a/core/java/android/os/WorkSource.java b/core/java/android/os/WorkSource.java
index f8da87a..ecec448 100644
--- a/core/java/android/os/WorkSource.java
+++ b/core/java/android/os/WorkSource.java
@@ -1,6 +1,8 @@
package android.os;
+import android.os.WorkSourceProto;
import android.util.Log;
+import android.util.proto.ProtoOutputStream;
import java.util.Arrays;
@@ -296,7 +298,7 @@
break;
}
if (mUids[i] == uid) {
- int diff = mNames[i].compareTo(name);
+ int diff = mNames[i].compareTo(name);
if (diff > 0) {
break;
}
@@ -692,6 +694,20 @@
return result.toString();
}
+ /** @hide */
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long workSourceToken = proto.start(fieldId);
+ for (int i = 0; i < mNum; i++) {
+ final long contentProto = proto.start(WorkSourceProto.WORK_SOURCE_CONTENTS);
+ proto.write(WorkSourceProto.WorkSourceContentProto.UID, mUids[i]);
+ if (mNames != null) {
+ proto.write(WorkSourceProto.WorkSourceContentProto.NAME, mNames[i]);
+ }
+ proto.end(contentProto);
+ }
+ proto.end(workSourceToken);
+ }
+
public static final Parcelable.Creator<WorkSource> CREATOR
= new Parcelable.Creator<WorkSource>() {
public WorkSource createFromParcel(Parcel in) {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 40de928..b55a349 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6905,6 +6905,12 @@
public static final String PACKAGE_VERIFIER_STATE = "package_verifier_state";
/**
+ * Specifies additional package name for broadcasting the CMAS messages.
+ * @hide
+ */
+ public static final String CMAS_ADDITIONAL_BROADCAST_PKG = "cmas_additional_broadcast_pkg";
+
+ /**
* This are the settings to be backed up.
*
* NOTE: Settings are backed up and restored in the order they appear
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 5f7ff67..8a83b7a 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -547,20 +547,20 @@
* Inform the notification manager about snoozing a specific notification.
* <p>
* Use this if your listener has a user interface that allows the user to snooze a notification
- * until a given time. It should be called after the user snoozes a single notification using
+ * for a time. It should be called after the user snoozes a single notification using
* your UI; upon being informed, the notification manager will actually remove the notification
* and you will get an {@link #onNotificationRemoved(StatusBarNotification)} callback. When the
* snoozing period expires, you will get a
* {@link #onNotificationPosted(StatusBarNotification, RankingMap)} callback for the
* notification.
* @param key The key of the notification to snooze
- * @param snoozeUntil A time in the future, in milliseconds.
+ * @param durationMs A duration to snooze the notification for, in milliseconds.
*/
- public final void snoozeNotification(String key, long snoozeUntil) {
+ public final void snoozeNotification(String key, long durationMs) {
if (!isBound()) return;
try {
getNotificationInterface().snoozeNotificationUntilFromListener(
- mWrapper, key, snoozeUntil);
+ mWrapper, key, durationMs);
} catch (android.os.RemoteException ex) {
Log.v(TAG, "Unable to contact notification manager", ex);
}
diff --git a/core/java/android/view/FocusFinder.java b/core/java/android/view/FocusFinder.java
index 7fde8a6..ad06141 100644
--- a/core/java/android/view/FocusFinder.java
+++ b/core/java/android/view/FocusFinder.java
@@ -117,7 +117,7 @@
public View findNextKeyboardNavigationCluster(
@NonNull View root,
@Nullable View currentCluster,
- int direction) {
+ @View.FocusDirection int direction) {
View next = null;
final ArrayList<View> clusters = mTempList;
@@ -206,7 +206,7 @@
View root,
View currentCluster,
List<View> clusters,
- int direction) {
+ @View.FocusDirection int direction) {
final int count = clusters.size();
switch (direction) {
@@ -732,27 +732,17 @@
getRect(first, mFirstRect);
getRect(second, mSecondRect);
- if (mFirstRect.top < mSecondRect.top) {
- return -1;
- } else if (mFirstRect.top > mSecondRect.top) {
- return 1;
- } else if (mFirstRect.left < mSecondRect.left) {
- return mIsLayoutRtl ? 1 : -1;
- } else if (mFirstRect.left > mSecondRect.left) {
- return mIsLayoutRtl ? -1 : 1;
- } else if (mFirstRect.bottom < mSecondRect.bottom) {
- return -1;
- } else if (mFirstRect.bottom > mSecondRect.bottom) {
- return 1;
- } else if (mFirstRect.right < mSecondRect.right) {
- return mIsLayoutRtl ? 1 : -1;
- } else if (mFirstRect.right > mSecondRect.right) {
- return mIsLayoutRtl ? -1 : 1;
+ boolean overlapsVertically = (mFirstRect.top < mSecondRect.top
+ && mFirstRect.bottom > mSecondRect.top)
+ || (mFirstRect.top > mSecondRect.top
+ && mFirstRect.top < mSecondRect.bottom);
+ boolean alignedVertically = (mFirstRect.left > mSecondRect.left)
+ == (mFirstRect.right < mSecondRect.right);
+ if (overlapsVertically && !alignedVertically) {
+ int rtl = mIsLayoutRtl ? -1 : 1;
+ return rtl * (mFirstRect.left - mSecondRect.left);
} else {
- // The view are distinct but completely coincident so we consider
- // them equal for our purposes. Since the sort is stable, this
- // means that the views will retain their layout order relative to one another.
- return 0;
+ return mFirstRect.top - mSecondRect.top;
}
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 66c394f..a880842 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -9433,7 +9433,8 @@
* @return The nearest keyboard navigation cluster in the specified direction, or null if none
* can be found
*/
- public View keyboardNavigationClusterSearch(View currentCluster, int direction) {
+ public View keyboardNavigationClusterSearch(View currentCluster,
+ @FocusDirection int direction) {
if (isKeyboardNavigationCluster()) {
currentCluster = this;
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 595e7a1..b79f22f 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -72,6 +72,7 @@
import android.util.TypedValue;
import android.view.Surface.OutOfResourcesException;
import android.view.View.AttachInfo;
+import android.view.View.FocusDirection;
import android.view.View.MeasureSpec;
import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
import android.view.accessibility.AccessibilityEvent;
@@ -5975,7 +5976,8 @@
* {@inheritDoc}
*/
@Override
- public View keyboardNavigationClusterSearch(View currentCluster, int direction) {
+ public View keyboardNavigationClusterSearch(View currentCluster,
+ @FocusDirection int direction) {
checkThread();
return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
mView, currentCluster, direction);
diff --git a/core/java/com/android/internal/util/StateMachine.java b/core/java/com/android/internal/util/StateMachine.java
index be10608df..d67cef3 100644
--- a/core/java/com/android/internal/util/StateMachine.java
+++ b/core/java/com/android/internal/util/StateMachine.java
@@ -23,6 +23,8 @@
import android.text.TextUtils;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -1495,7 +1497,7 @@
}
/**
- * @return number of log records
+ * @return the number of log records currently readable
*/
public final int getLogRecSize() {
// mSmHandler can be null if the state machine has quit.
@@ -1505,6 +1507,17 @@
}
/**
+ * @return the number of log records we can store
+ */
+ @VisibleForTesting
+ public final int getLogRecMaxSize() {
+ // mSmHandler can be null if the state machine has quit.
+ SmHandler smh = mSmHandler;
+ if (smh == null) return 0;
+ return smh.mLogRecords.mMaxSize;
+ }
+
+ /**
* @return the total number of records processed
*/
public final int getLogRecCount() {
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index ae2e0ac..cc1c65e 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -278,7 +278,8 @@
public LockPatternView(Context context, AttributeSet attrs) {
super(context, attrs);
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LockPatternView);
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LockPatternView,
+ R.attr.lockPatternStyle, R.style.Widget_LockPatternView);
final String aspect = a.getString(R.styleable.LockPatternView_aspect);
@@ -298,12 +299,9 @@
mPathPaint.setAntiAlias(true);
mPathPaint.setDither(true);
- mRegularColor = context.getColor(R.color.lock_pattern_view_regular_color);
- mErrorColor = context.getColor(R.color.lock_pattern_view_error_color);
- mSuccessColor = context.getColor(R.color.lock_pattern_view_success_color);
- mRegularColor = a.getColor(R.styleable.LockPatternView_regularColor, mRegularColor);
- mErrorColor = a.getColor(R.styleable.LockPatternView_errorColor, mErrorColor);
- mSuccessColor = a.getColor(R.styleable.LockPatternView_successColor, mSuccessColor);
+ mRegularColor = a.getColor(R.styleable.LockPatternView_regularColor, 0);
+ mErrorColor = a.getColor(R.styleable.LockPatternView_errorColor, 0);
+ mSuccessColor = a.getColor(R.styleable.LockPatternView_successColor, 0);
int pathColor = a.getColor(R.styleable.LockPatternView_pathColor, mRegularColor);
mPathPaint.setColor(pathColor);
diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
index e84cc27..e224b17 100644
--- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java
+++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
@@ -748,6 +748,10 @@
final int widthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY);
final int heightSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY);
final int widthPadding = getPaddingLeft() + getPaddingRight();
+
+ // Currently we allot more height than is really needed so that the entirety of the
+ // sheet may be pulled up.
+ // TODO: Restrict the height here to be the right value.
int heightUsed = getPaddingTop() + getPaddingBottom();
// Measure always-show children first.
@@ -757,7 +761,7 @@
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (lp.alwaysShow && child.getVisibility() != GONE) {
measureChildWithMargins(child, widthSpec, widthPadding, heightSpec, heightUsed);
- heightUsed += getHeightUsed(child);
+ heightUsed += child.getMeasuredHeight();
}
}
@@ -769,7 +773,7 @@
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (!lp.alwaysShow && child.getVisibility() != GONE) {
measureChildWithMargins(child, widthSpec, widthPadding, heightSpec, heightUsed);
- heightUsed += getHeightUsed(child);
+ heightUsed += child.getMeasuredHeight();
}
}
@@ -785,36 +789,6 @@
setMeasuredDimension(sourceWidth, heightSize);
}
- private int getHeightUsed(View child) {
- // This method exists because we're taking a fast path at measuring ListViews that
- // lets us get away with not doing the more expensive wrap_content measurement which
- // imposes double child view measurement costs. If we're looking at a ListView, we can
- // check against the lowest child view plus padding and margin instead of the actual
- // measured height of the ListView. This lets the ListView hang off the edge when
- // all of the content would fit on-screen.
-
- int heightUsed = child.getMeasuredHeight();
- if (child instanceof AbsListView) {
- final AbsListView lv = (AbsListView) child;
- final int lvPaddingBottom = lv.getPaddingBottom();
-
- int lowest = 0;
- for (int i = 0, N = lv.getChildCount(); i < N; i++) {
- final int bottom = lv.getChildAt(i).getBottom() + lvPaddingBottom;
- if (bottom > lowest) {
- lowest = bottom;
- }
- }
-
- if (lowest < heightUsed) {
- heightUsed = lowest;
- }
- }
-
- final LayoutParams lp = (LayoutParams) child.getLayoutParams();
- return lp.topMargin + heightUsed + lp.bottomMargin;
- }
-
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int width = getWidth();
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index eaf9e91..4322105 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -1021,17 +1021,13 @@
env->ReleaseStringCritical(fileName, str);
}
- int fd = open(fileName8.string(), O_CREAT | O_WRONLY | O_NOFOLLOW, 0666); /* -rw-rw-rw- */
+ int fd = open(fileName8.string(), O_CREAT | O_WRONLY | O_NOFOLLOW | O_CLOEXEC | O_APPEND, 0666);
if (fd < 0) {
fprintf(stderr, "Can't open %s: %s\n", fileName8.string(), strerror(errno));
return;
}
- if (lseek(fd, 0, SEEK_END) < 0) {
- fprintf(stderr, "lseek: %s\n", strerror(errno));
- } else {
- dump_backtrace_to_file_timeout(pid, fd, timeoutSecs);
- }
+ dump_backtrace_to_file_timeout(pid, fd, timeoutSecs);
close(fd);
}
diff --git a/core/proto/android/os/looper.proto b/core/proto/android/os/looper.proto
new file mode 100644
index 0000000..9fcc781
--- /dev/null
+++ b/core/proto/android/os/looper.proto
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+syntax = "proto3";
+
+package android.os;
+
+option java_multiple_files = true;
+
+import "frameworks/base/core/proto/android/os/messagequeue.proto";
+
+message LooperProto {
+ string thread_name = 1;
+ int64 thread_id = 2;
+ int32 identity_hash_code = 3;
+ android.os.MessageQueueProto queue = 4;
+}
diff --git a/core/proto/android/os/message.proto b/core/proto/android/os/message.proto
new file mode 100644
index 0000000..604935d
--- /dev/null
+++ b/core/proto/android/os/message.proto
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+syntax = "proto3";
+
+package android.os;
+
+option java_multiple_files = true;
+
+message MessageProto {
+ int64 when = 1;
+ // Name of callback class.
+ string callback = 2;
+ // User-defined message code so that the recipient can identify what this
+ // message is about.
+ int32 what = 3;
+ int32 arg1 = 4;
+ int32 arg2 = 5;
+ // String representation of an arbitrary object to send to the recipient.
+ string obj = 6;
+ // Name of target class.
+ string target = 7;
+ int32 barrier = 8;
+}
diff --git a/core/proto/android/os/messagequeue.proto b/core/proto/android/os/messagequeue.proto
new file mode 100644
index 0000000..9bff13e
--- /dev/null
+++ b/core/proto/android/os/messagequeue.proto
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+syntax = "proto3";
+
+package android.os;
+
+option java_multiple_files = true;
+
+import "frameworks/base/core/proto/android/os/message.proto";
+
+message MessageQueueProto {
+ repeated android.os.MessageProto messages = 1;
+ bool is_polling_locked = 2;
+ bool is_quitting = 3;
+}
diff --git a/core/proto/android/os/worksource.proto b/core/proto/android/os/worksource.proto
new file mode 100644
index 0000000..c2aa5cb
--- /dev/null
+++ b/core/proto/android/os/worksource.proto
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+syntax = "proto3";
+
+package android.os;
+
+option java_multiple_files = true;
+
+message WorkSourceProto {
+ message WorkSourceContentProto {
+ int32 uid = 1;
+ string name = 2;
+ }
+
+ repeated WorkSourceContentProto work_source_contents = 1;
+}
\ No newline at end of file
diff --git a/core/proto/android/service/package.proto b/core/proto/android/service/package.proto
new file mode 100644
index 0000000..326b0eb
--- /dev/null
+++ b/core/proto/android/service/package.proto
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+syntax = "proto3";
+
+package android.service.pm;
+
+option java_multiple_files = true;
+option java_outer_classname = "PackageServiceProto";
+
+message PackageServiceDumpProto {
+ message PackageShortProto {
+ // Name of package. e.g. "com.android.providers.telephony".
+ string name = 1;
+ // UID for this package as assigned by Android OS.
+ int32 uid = 2;
+ }
+ message SharedLibraryProto {
+ string name = 1;
+ // True if library path is not null (jar), false otherwise (apk)
+ bool is_jar = 2;
+ // Should be filled if is_jar is true
+ string path = 3;
+ // Should be filled if is_jar is false
+ string apk = 4;
+ }
+ message FeatureProto {
+ string name = 1;
+ int32 version = 2;
+ }
+ message SharedUserProto {
+ int32 user_id = 1;
+ string name = 2;
+ }
+
+ // Installed packages.
+ PackageShortProto required_verifier_package = 1;
+ PackageShortProto verifier_package = 2;
+ repeated SharedLibraryProto shared_libraries = 3;
+ repeated FeatureProto features = 4;
+ repeated PackageProto packages = 5;
+ repeated SharedUserProto shared_users = 6;
+ // Messages from the settings problem file
+ repeated string messages = 7;
+}
+
+message PackageProto {
+ message SplitProto {
+ string name = 1;
+ int32 revision_code = 2;
+ }
+ message UserInfoProto {
+ enum InstallType {
+ NOT_INSTALLED_FOR_USER = 0;
+ FULL_APP_INSTALL = 1;
+ INSTANT_APP_INSTALL = 2;
+ }
+ // Enum values gotten from PackageManger.java
+ enum EnabledState {
+ // This component or application is in its default enabled state
+ // (as specified in its manifest).
+ COMPONENT_ENABLED_STATE_DEFAULT = 0;
+ // This component or application has been explictily enabled, regardless
+ // of what it has specified in its manifest.
+ COMPONENT_ENABLED_STATE_ENABLED = 1;
+ // This component or application has been explicitly disabled, regardless of
+ // what it has specified in its manifest.
+ COMPONENT_ENABLED_STATE_DISABLED = 2;
+ // The user has explicitly disabled the application, regardless of what it has
+ // specified in its manifest.
+ COMPONENT_ENABLED_STATE_DISABLED_USER = 3;
+ // This application should be considered, until the point where the user actually
+ // wants to use it.
+ COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED = 4;
+ }
+
+ int32 id = 1;
+ InstallType install_type = 2;
+ // Is the app restricted by owner / admin
+ bool is_hidden = 3;
+ bool is_suspended = 4;
+ bool is_stopped = 5;
+ bool is_launched = 6;
+ EnabledState enabled_state = 7;
+ string last_disabled_app_caller = 8;
+ }
+
+ // Name of package. e.g. "com.android.providers.telephony".
+ string name = 1;
+ // UID for this package as assigned by Android OS.
+ int32 uid = 2;
+ // Package's reported version.
+ int32 version_code = 3;
+ // Package's reported version string (what's displayed to the user).
+ string version_string = 4;
+ // UTC timestamp of install
+ int64 install_time_ms = 5;
+ // Millisecond UTC timestamp of latest update adjusted to Google's server clock.
+ int64 update_time_ms = 6;
+ // From "dumpsys package" - name of package which installed this one.
+ // Typically "" if system app or "com.android.vending" if Play Store.
+ string installer_name = 7;
+ // Split APKs.
+ repeated SplitProto splits = 8;
+ // Per-user package info.
+ repeated UserInfoProto users = 9;
+}
diff --git a/core/proto/android/service/power.proto b/core/proto/android/service/power.proto
new file mode 100644
index 0000000..1830dbf
--- /dev/null
+++ b/core/proto/android/service/power.proto
@@ -0,0 +1,408 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+syntax = "proto3";
+
+package android.service.power;
+
+option java_multiple_files = true;
+option java_outer_classname = "PowerServiceProto";
+
+import "frameworks/base/core/proto/android/os/looper.proto";
+import "frameworks/base/core/proto/android/os/worksource.proto";
+import "frameworks/base/core/proto/android/service/wirelesschargerdetector.proto";
+
+message PowerServiceDumpProto {
+ message ConstantsProto {
+ bool is_no_cached_wake_locks = 1;
+ }
+ message ActiveWakeLocksProto {
+ bool is_cpu = 1;
+ bool is_screen_bright = 2;
+ bool is_screen_dim = 3;
+ bool is_button_bright = 4;
+ bool is_proximity_screen_off = 5;
+ // only set if already awake
+ bool is_stay_awake = 6;
+ bool is_doze = 7;
+ bool is_draw = 8;
+ }
+ message UserActivityProto {
+ bool is_screen_bright = 1;
+ bool is_screen_dim = 2;
+ bool is_screen_dream = 3;
+ }
+ message UidProto {
+ // Enum values gotten from ActivityManager.java
+ enum ProcessState {
+ // Process is a persistent system process.
+ PROCESS_STATE_PERSISTENT = 0;
+ // Process is a persistent system process and is doing UI.
+ PROCESS_STATE_PERSISTENT_UI = 1;
+ // Process is hosting the current top activities. Note that this
+ // covers all activities that are visible to the user.
+ PROCESS_STATE_TOP = 2;
+ // Process is hosting a foreground service due to a system binding.
+ PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 3;
+ // Process is hosting a foreground service.
+ PROCESS_STATE_FOREGROUND_SERVICE = 4;
+ // Same as {@link #PROCESS_STATE_TOP} but while device is sleeping.
+ PROCESS_STATE_TOP_SLEEPING = 5;
+ // Process is important to the user, and something they are aware of.
+ PROCESS_STATE_IMPORTANT_FOREGROUND = 6;
+ // Process is important to the user, but not something they are aware of.
+ PROCESS_STATE_IMPORTANT_BACKGROUND = 7;
+ // Process is in the background running a backup/restore operation.
+ PROCESS_STATE_BACKUP = 8;
+ // Process is in the background, but it can't restore its state so
+ // we want to try to avoid killing it.
+ PROCESS_STATE_HEAVY_WEIGHT = 9;
+ // Process is in the background running a service.
+ PROCESS_STATE_SERVICE = 10;
+ // Process is in the background running a receiver.
+ PROCESS_STATE_RECEIVER = 11;
+ // Process is in the background but hosts the home activity.
+ PROCESS_STATE_HOME = 12;
+ // Process is in the background but hosts the last shown activity.
+ PROCESS_STATE_LAST_ACTIVITY = 13;
+ // Process is being cached for later use and contains activities.
+ PROCESS_STATE_CACHED_ACTIVITY = 14;
+ // Process is being cached for later use and is a client of another
+ // cached process that contains activities.
+ PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 15;
+ // Process is being cached for later use and is empty.
+ PROCESS_STATE_CACHED_EMPTY = 16;
+ // Process does not exist.
+ PROCESS_STATE_NONEXISTENT = 17;
+ }
+ int32 uid = 1;
+ string uid_string = 2;
+ bool is_active = 3;
+ int32 num_wake_locks = 4;
+ bool is_process_state_unknown = 5;
+ ProcessState process_state = 6;
+ }
+
+ // Enum values gotten from PowerManagerInternal.java
+ enum Wakefulness {
+ WAKEFULNESS_ASLEEP = 0;
+ WAKEFULNESS_AWAKE = 1;
+ WAKEFULNESS_DREAMING = 2;
+ WAKEFULNESS_DOZING = 3;
+ WAKEFULNESS_UNKNOWN = 4;
+ }
+ // Enum values gotten from BatteryManager.java
+ enum PlugType {
+ PLUG_TYPE_NONE = 0;
+ PLUG_TYPE_PLUGGED_AC = 1;
+ PLUG_TYPE_PLUGGED_USB = 2;
+ PLUG_TYPE_PLUGGED_WIRELESS = 4;
+ }
+ // Enum values gotten from Intent.java
+ enum DockState {
+ DOCK_STATE_UNDOCKED = 0;
+ DOCK_STATE_DESK = 1;
+ DOCK_STATE_CAR = 2;
+ DOCK_STATE_LE_DESK = 3;
+ DOCK_STATE_HE_DESK = 4;
+ }
+
+ ConstantsProto constants = 1;
+ // A bitfield that indicates what parts of the power state have
+ // changed and need to be recalculated.
+ int32 dirty = 2;
+ // Indicates whether the device is awake or asleep or somewhere in between.
+ Wakefulness wakefulness = 3;
+ bool is_wakefulness_changing = 4;
+ // True if the device is plugged into a power source.
+ bool is_powered = 5;
+ // The current plug type
+ PlugType plug_type = 6;
+ // The current battery level percentage.
+ int32 battery_level = 7;
+ // The battery level percentage at the time the dream started.
+ int32 battery_level_when_dream_started = 8;
+ // The current dock state.
+ DockState dock_state = 9;
+ // True if the device should stay on.
+ bool is_stay_on = 10;
+ // True if the proximity sensor reads a positive result.
+ bool is_proximity_positive = 11;
+ // True if boot completed occurred. We keep the screen on until this happens.
+ bool is_boot_completed = 12;
+ // True if systemReady() has been called.
+ bool is_system_ready = 13;
+ // True if auto-suspend mode is enabled.
+ bool is_hal_auto_suspend_mode_enabled = 14;
+ // True if interactive mode is enabled.
+ bool is_hal_auto_interactive_mode_enabled = 15;
+ // Summarizes the state of all active wakelocks.
+ ActiveWakeLocksProto active_wake_locks = 16;
+ // Have we scheduled a message to check for long wake locks? This is when
+ // we will check. (In milliseconds timestamp)
+ int64 notify_long_scheduled_ms = 17;
+ // Last time we checked for long wake locks. (In milliseconds timestamp)
+ int64 notify_long_dispatched_ms = 18;
+ // The time we decided to do next long check. (In milliseconds timestamp)
+ int64 notify_long_next_check_ms = 19;
+ // Summarizes the effect of the user activity timer.
+ UserActivityProto user_activity = 20;
+ // If true, instructs the display controller to wait for the proximity
+ // sensor to go negative before turning the screen on.
+ bool is_request_wait_for_negative_proximity = 21;
+ // True if MSG_SANDMAN has been scheduled.
+ bool is_sandman_scheduled = 22;
+ // True if the sandman has just been summoned for the first time since entering
+ // the dreaming or dozing state. Indicates whether a new dream should begin.
+ bool is_sandman_summoned = 23;
+ // If true, the device is in low power mode.
+ bool is_low_power_mode_enabled = 24;
+ // True if the battery level is currently considered low.
+ bool is_battery_level_low = 25;
+ // True if we are currently in light device idle mode.
+ bool is_light_device_idle_mode = 26;
+ // True if we are currently in device idle mode.
+ bool is_device_idle_mode = 27;
+ // Set of app ids that we will always respect the wake locks for.
+ repeated int32 device_idle_whitelist = 28;
+ // Set of app ids that are temporarily allowed to acquire wakelocks due to
+ // high-pri message
+ repeated int32 device_idle_temp_whitelist = 29;
+ // Timestamp of the last time the device was awoken.
+ int64 last_wake_time_ms = 30;
+ // Timestamp of the last time the device was put to sleep.
+ int64 last_sleep_time_ms = 31;
+ // Timestamp of the last call to user activity.
+ int64 last_user_activity_time_ms = 32;
+ int64 last_user_activity_time_no_change_lights_ms = 33;
+ // Timestamp of last interactive power hint.
+ int64 last_interactive_power_hint_time_ms = 34;
+ // Timestamp of the last screen brightness boost.
+ int64 last_screen_brightness_boost_time_ms = 35;
+ // True if screen brightness boost is in progress.
+ bool is_screen_brightness_boost_in_progress = 36;
+ // True if the display power state has been fully applied, which means the
+ // display is actually on or actually off or whatever was requested.
+ bool is_display_ready = 37;
+ // True if the wake lock suspend blocker has been acquired.
+ bool is_holding_wake_lock_suspend_blocker = 38;
+ // The suspend blocker used to keep the CPU alive when the display is on, the
+ // display is getting ready or there is user activity (in which case the
+ // display must be on).
+ bool is_holding_display_suspend_blocker = 39;
+ // Settings and configuration
+ PowerServiceSettingsAndConfigurationDumpProto settings_and_configuration = 40;
+ // Sleep timeout in ms
+ sint32 sleep_timeout_ms = 41;
+ // Screen off timeout in ms
+ int32 screen_off_timeout_ms = 42;
+ // Screen dim duration in ms
+ int32 screen_dim_duration_ms = 43;
+ // We are currently in the middle of a batch change of uids.
+ bool are_uids_changing = 44;
+ // Some uids have actually changed while mUidsChanging was true.
+ bool are_uids_changed = 45;
+ // List of UIDs and their states
+ repeated UidProto uids = 46;
+ android.os.LooperProto looper = 47;
+ // List of all wake locks acquired by applications.
+ repeated WakeLockProto wake_locks = 48;
+ // List of all suspend blockers.
+ repeated SuspendBlockerProto suspend_blockers = 49;
+ WirelessChargerDetectorProto wireless_charger_detector = 50;
+}
+
+message SuspendBlockerProto {
+ string name = 1;
+ int32 reference_count = 2;
+}
+
+message WakeLockProto {
+ message WakeLockFlagsProto {
+ // Turn the screen on when the wake lock is acquired.
+ bool is_acquire_causes_wakeup = 1;
+ // When this wake lock is released, poke the user activity timer
+ // so the screen stays on for a little longer.
+ bool is_on_after_release = 2;
+ }
+
+ // Enum values gotten from PowerManager.java
+ enum LockLevel {
+ WAKE_LOCK_INVALID = 0;
+ // Ensures that the CPU is running.
+ PARTIAL_WAKE_LOCK = 1;
+ // Ensures that the screen is on (but may be dimmed).
+ SCREEN_DIM_WAKE_LOCK = 6;
+ // Ensures that the screen is on at full brightness.
+ SCREEN_BRIGHT_WAKE_LOCK = 10;
+ // Ensures that the screen and keyboard backlight are on at full brightness.
+ FULL_WAKE_LOCK = 26;
+ // Turns the screen off when the proximity sensor activates.
+ PROXIMITY_SCREEN_OFF_WAKE_LOCK = 32;
+ // Put the screen in a low power state and allow the CPU to suspend
+ // if no other wake locks are held.
+ DOZE_WAKE_LOCK = 64;
+ // Keep the device awake enough to allow drawing to occur.
+ DRAW_WAKE_LOCK = 128;
+ }
+
+ LockLevel lock_level = 1;
+ string tag = 2;
+ WakeLockFlagsProto flags = 3;
+ bool is_disabled = 4;
+ // Acquire time in ms
+ int64 acq_ms = 5;
+ bool is_notified_long = 6;
+ // Owner UID
+ int32 uid = 7;
+ // Owner PID
+ int32 pid = 8;
+ android.os.WorkSourceProto work_source = 9;
+}
+
+message PowerServiceSettingsAndConfigurationDumpProto {
+ message StayOnWhilePluggedInProto {
+ bool is_stay_on_while_plugged_in_ac = 1;
+ bool is_stay_on_while_plugged_in_usb = 2;
+ bool is_stay_on_while_plugged_in_wireless = 3;
+ }
+ message ScreenBrightnessSettingLimitsProto {
+ int32 setting_minimum = 1;
+ int32 setting_maximum = 2;
+ int32 setting_default = 3;
+ int32 setting_for_vr_default = 4;
+ }
+
+ // Enum values gotten from Settings.java
+ enum ScreenBrightnessMode {
+ SCREEN_BRIGHTNESS_MODE_MANUAL = 0;
+ SCREEN_BRIGHTNESS_MODE_AUTOMATIC = 1;
+ }
+ // Enum values gotten from Display.java
+ enum DisplayState {
+ DISPLAY_STATE_UNKNOWN = 0;
+ DISPLAY_STATE_OFF = 1;
+ DISPLAY_STATE_ON = 2;
+ DISPLAY_STATE_DOZE = 3;
+ DISPLAY_STATE_DOZE_SUSPEND = 4;
+ DISPLAY_STATE_VR = 5;
+ }
+
+
+ // True to decouple auto-suspend mode from the display state.
+ bool is_decouple_hal_auto_suspend_mode_from_display_config = 1;
+ // True to decouple interactive mode from the display state.
+ bool is_decouple_hal_interactive_mode_from_display_config = 2;
+ // True if the device should wake up when plugged or unplugged.
+ bool is_wake_up_when_plugged_or_unplugged_config = 3;
+ // True if the device should wake up when plugged or unplugged in theater mode.
+ bool is_wake_up_when_plugged_or_unplugged_in_theater_mode_config = 4;
+ // True if theater mode is enabled
+ bool is_theater_mode_enabled = 5;
+ // True if the device should suspend when the screen is off due to proximity.
+ bool is_suspend_when_screen_off_due_to_proximity_config = 6;
+ // True if dreams are supported on this device.
+ bool are_dreams_supported_config = 7;
+ // Default value for dreams enabled
+ bool are_dreams_enabled_by_default_config = 8;
+ // Default value for dreams activate-on-sleep
+ bool are_dreams_activated_on_sleep_by_default_config = 9;
+ // Default value for dreams activate-on-dock
+ bool are_dreams_activated_on_dock_by_default_config = 10;
+ // True if dreams can run while not plugged in.
+ bool are_dreams_enabled_on_battery_config = 11;
+ // Minimum battery level to allow dreaming when powered.
+ // Use -1 to disable this safety feature.
+ sint32 dreams_battery_level_minimum_when_powered_config = 12;
+ // Minimum battery level to allow dreaming when not powered.
+ // Use -1 to disable this safety feature.
+ sint32 dreams_battery_level_minimum_when_not_powered_config = 13;
+ // If the battery level drops by this percentage and the user activity
+ // timeout has expired, then assume the device is receiving insufficient
+ // current to charge effectively and terminate the dream. Use -1 to disable
+ // this safety feature.
+ sint32 dreams_battery_level_drain_cutoff_config = 14;
+ // True if dreams are enabled by the user.
+ bool are_dreams_enabled_setting = 15;
+ // True if dreams should be activated on sleep.
+ bool are_dreams_activate_on_sleep_setting = 16;
+ // True if dreams should be activated on dock.
+ bool are_dreams_activate_on_dock_setting = 17;
+ // True if doze should not be started until after the screen off transition.
+ bool is_doze_after_screen_off_config = 18;
+ // If true, the device is in low power mode.
+ bool is_low_power_mode_setting = 19;
+ // Current state of whether the settings are allowing auto low power mode.
+ bool is_auto_low_power_mode_configured = 20;
+ // The user turned off low power mode below the trigger level
+ bool is_auto_low_power_mode_snoozing = 21;
+ // The minimum screen off timeout, in milliseconds.
+ int32 minimum_screen_off_timeout_config_ms = 22;
+ // The screen dim duration, in milliseconds.
+ int32 maximum_screen_dim_duration_config_ms = 23;
+ // The maximum screen dim time expressed as a ratio relative to the screen off timeout.
+ float maximum_screen_dim_ratio_config = 24;
+ // The screen off timeout setting value in milliseconds.
+ int32 screen_off_timeout_setting_ms = 25;
+ // The sleep timeout setting value in milliseconds.
+ sint32 sleep_timeout_setting_ms = 26;
+ // The maximum allowable screen off timeout according to the device administration policy.
+ int32 maximum_screen_off_timeout_from_device_admin_ms = 27;
+ bool is_maximum_screen_off_timeout_from_device_admin_enforced_locked = 28;
+ // The stay on while plugged in setting.
+ // A set of battery conditions under which to make the screen stay on.
+ StayOnWhilePluggedInProto stay_on_while_plugged_in = 29;
+ // The screen brightness setting, from 0 to 255.
+ // Use -1 if no value has been set.
+ sint32 screen_brightness_setting = 30;
+ // The screen auto-brightness adjustment setting, from -1 to 1.
+ // Use 0 if there is no adjustment.
+ float screen_auto_brightness_adjustment_setting = 31;
+ // The screen brightness mode.
+ ScreenBrightnessMode screen_brightness_mode_setting = 32;
+ // The screen brightness setting override from the window manager
+ // to allow the current foreground activity to override the brightness.
+ // Use -1 to disable.
+ sint32 screen_brightness_override_from_window_manager = 33;
+ // The user activity timeout override from the window manager
+ // to allow the current foreground activity to override the user activity
+ // timeout. Use -1 to disable.
+ sint64 user_activity_timeout_override_from_window_manager_ms = 34;
+ // The window manager has determined the user to be inactive via other means.
+ // Set this to false to disable.
+ bool is_user_inactive_override_from_window_manager = 35;
+ // The screen brightness setting override from the settings application
+ // to temporarily adjust the brightness until next updated,
+ // Use -1 to disable.
+ sint32 temporary_screen_brightness_setting_override = 36;
+ // The screen brightness adjustment setting override from the settings
+ // application to temporarily adjust the auto-brightness adjustment factor
+ // until next updated, in the range -1..1.
+ // Use NaN to disable.
+ float temporary_screen_auto_brightness_adjustment_setting_override = 37;
+ // The screen state to use while dozing.
+ DisplayState doze_screen_state_override_from_dream_manager = 38;
+ // The screen brightness to use while dozing.
+ float dozed_screen_brightness_override_from_dream_manager = 39;
+ // Screen brightness settings limits.
+ ScreenBrightnessSettingLimitsProto screen_brightness_setting_limits = 40;
+ // The screen brightness setting, from 0 to 255, to be used while in VR Mode.
+ int32 screen_brightness_for_vr_setting = 41;
+ // True if double tap to wake is enabled
+ bool is_double_tap_wake_enabled = 42;
+ // True if we are currently in VR Mode.
+ bool is_vr_mode_enabled = 43;
+}
diff --git a/core/proto/android/service/wirelesschargerdetector.proto b/core/proto/android/service/wirelesschargerdetector.proto
new file mode 100644
index 0000000..7ba7c17
--- /dev/null
+++ b/core/proto/android/service/wirelesschargerdetector.proto
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+syntax = "proto3";
+
+package android.service.power;
+
+option java_multiple_files = true;
+
+message WirelessChargerDetectorProto {
+ message VectorProto {
+ float x = 1;
+ float y = 2;
+ float z = 3;
+ }
+
+ // Previously observed wireless power state.
+ bool is_powered_wirelessly = 1;
+ // True if the device is thought to be at rest on a wireless charger.
+ bool is_at_rest = 2;
+ // The gravity vector most recently observed while at rest.
+ VectorProto rest = 3;
+ // True if detection is in progress.
+ bool is_detection_in_progress = 4;
+ // The time when detection was last performed.
+ int64 detection_start_time_ms = 5;
+ // True if the rest position should be updated if at rest.
+ bool is_must_update_rest_position = 6;
+ // The total number of samples collected.
+ int32 total_samples = 7;
+ // The number of samples collected that showed evidence of not being at rest.
+ int32 moving_samples = 8;
+ // The value of the first sample that was collected.
+ VectorProto first_sample = 9;
+ // The value of the last sample that was collected.
+ VectorProto last_sample = 10;
+}
\ No newline at end of file
diff --git a/core/res/res/layout/app_permission_item_money.xml b/core/res/res/layout/app_permission_item_money.xml
index 2056285..764c883 100644
--- a/core/res/res/layout/app_permission_item_money.xml
+++ b/core/res/res/layout/app_permission_item_money.xml
@@ -57,14 +57,14 @@
android:layout_alignParentStart="true"
android:layout_alignBottom="@+id/perm_money_label"
android:scaleType="fitCenter"
- android:tint="@color/perms_costs_money"
+ android:tint="?android:attr/colorError"
android:tintMode="src_in"
android:src="@android:drawable/ic_coins_s" />
<TextView
android:id="@+id/perm_money_label"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textSize="16sp"
- android:textColor="@color/perms_costs_money"
+ android:textColor="?android:attr/colorError"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="@id/perm_money_icon"
diff --git a/core/res/res/layout/time_picker_text_input_material.xml b/core/res/res/layout/time_picker_text_input_material.xml
index f17b80e..632a4c1 100644
--- a/core/res/res/layout/time_picker_text_input_material.xml
+++ b/core/res/res/layout/time_picker_text_input_material.xml
@@ -77,7 +77,7 @@
android:layout_height="wrap_content"
android:layout_below="@id/input_hour"
android:layout_alignStart="@id/input_hour"
- android:textColor="?attr/textColorError"
+ android:textColor="?attr/colorError"
android:text="@string/time_picker_input_error" />
</RelativeLayout>
<Spinner
@@ -87,4 +87,4 @@
android:layout_alignBaseline="@id/input_block"
android:layout_alignParentEnd="true"/>
-</merge>
\ No newline at end of file
+</merge>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 8031f19..f55538f 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -66,6 +66,9 @@
<attr name="primaryContentAlpha" format="float" />
<!-- The alpha applied to the foreground color to create the secondary text color. -->
<attr name="secondaryContentAlpha" format="float" />
+ <!-- Color used for error states and things that need to be drawn to
+ the users attention.. -->
+ <attr name="colorError" format="reference|color" />
<!-- Default background dim amount when a menu, dialog, or something similar pops up. -->
<attr name="backgroundDimAmount" format="float" />
<!-- Control whether dimming behind the window is enabled. The default
@@ -135,9 +138,6 @@
<!-- Color of list item text in alert dialogs. -->
<attr name="textColorAlertDialogListItem" format="reference|color" />
- <!-- Text color for errors. -->
- <attr name="textColorError" format="reference|color" />
-
<!-- Search widget more corpus result item background. -->
<attr name="searchWidgetCorpusItemBackground" format="reference|color" />
@@ -8531,4 +8531,6 @@
<attr name="reverseLayout" format="boolean" />
<attr name="stackFromEnd" format="boolean" />
</declare-styleable>
+
+ <attr name="lockPatternStyle" format="reference" />
</resources>
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index b28c6f2..6015ed5 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -75,8 +75,6 @@
<drawable name="input_method_fullscreen_background">#fff9f9f9</drawable>
<color name="input_method_navigation_guard">#ff000000</color>
- <color name="system_error">#fff4511e</color> <!-- deep orange 600 -->
-
<!-- For date picker widget -->
<drawable name="selected_day_background">#ff0092f4</drawable>
@@ -88,7 +86,6 @@
<color name="perms_dangerous_grp_color">#33b5e5</color>
<color name="perms_dangerous_perm_color">#33b5e5</color>
<color name="shadow">#cc222222</color>
- <color name="perms_costs_money">#fff4511e</color>
<!-- For search-related UIs -->
<color name="search_url_text_normal">#7fa87f</color>
@@ -121,7 +118,6 @@
<!-- LockPatternView -->
<color name="lock_pattern_view_regular_color">#ffffffff</color>
<color name="lock_pattern_view_success_color">#ffffffff</color>
- <color name="lock_pattern_view_error_color">@color/system_error</color>
<!-- FaceLock -->
<color name="facelock_spotlight_mask">#CC000000</color>
@@ -156,7 +152,6 @@
<color name="accessibility_focus_highlight">#bf39b500</color>
<color name="system_notification_accent_color">#ff607D8B</color>
- <color name="battery_saver_mode_color">#fff4511e</color><!-- deep orange 600 -->
<!-- Default user icon colors -->
<color name="user_icon_1">#ff00bcd4</color><!-- cyan 500 -->
diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml
index 0a24565..e0cc5b5 100644
--- a/core/res/res/values/colors_material.xml
+++ b/core/res/res/values/colors_material.xml
@@ -46,6 +46,7 @@
<color name="button_material_dark">#ff5a595b</color>
<color name="button_material_light">#ffd6d7d7</color>
+ <color name="error_color_material">#F4511E</color>
<color name="switch_thumb_normal_material_dark">#ffbdbdbd</color>
<color name="switch_thumb_normal_material_light">#fff1f1f1</color>
@@ -65,9 +66,6 @@
<!-- 70% white -->
<color name="secondary_text_default_material_dark">#b3ffffff</color>
- <color name="error_text_material_light">@color/material_red_A700</color>
- <color name="error_text_material_dark">@color/material_red_A100</color>
-
<item name="hint_alpha_material_dark" format="float" type="dimen">0.50</item>
<item name="hint_alpha_material_light" format="float" type="dimen">0.38</item>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index d233e24..35aff80 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2748,8 +2748,8 @@
<!-- Flag indicates that whether non-system apps can be installed on internal storage. -->
<bool name="config_allow3rdPartyAppOnInternal">true</bool>
- <!-- Component name of the default cell broadcast receiver -->
- <string name="config_defaultCellBroadcastReceiverComponent" translatable="false">com.android.cellbroadcastreceiver/.PrivilegedCellBroadcastReceiver</string>
+ <!-- Package name of the default cell broadcast receiver -->
+ <string name="config_defaultCellBroadcastReceiverPkg" translatable="false">com.android.cellbroadcastreceiver</string>
<!-- Specifies the path that is used by AdaptiveIconDrawable class to crop launcher icons. -->
<string name="config_icon_mask" translatable="false">"M50,0L100,0 100,100 0,100 0,0z"</string>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 78549b5..e5660b5 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2780,7 +2780,7 @@
<public name="targetProcess" />
<public name="nextClusterForward" />
<public name="__removed1" />
- <public name="textColorError" />
+ <public name="colorError" />
<public name="focusedByDefault" />
<public name="appCategory" />
<public name="autoSizeMaxTextSize" />
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index faf451b..25873d2 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1475,4 +1475,10 @@
<item name="padding">16dp</item>
</style>
+ <style name="Widget.LockPatternView">
+ <item name="regularColor">@color/lock_pattern_view_regular_color</item>
+ <item name="errorColor">?attr/colorError</item>
+ <item name="successColor">@color/lock_pattern_view_success_color</item>
+ </style>
+
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e7d3ec9..49216d9 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1195,7 +1195,6 @@
<java-symbol type="drawable" name="btn_check_off" />
<java-symbol type="color" name="lock_pattern_view_regular_color" />
<java-symbol type="color" name="lock_pattern_view_success_color" />
- <java-symbol type="color" name="lock_pattern_view_error_color" />
<java-symbol type="dimen" name="lock_pattern_dot_line_width" />
<java-symbol type="dimen" name="lock_pattern_dot_size" />
<java-symbol type="dimen" name="lock_pattern_dot_size_activated" />
@@ -2310,7 +2309,6 @@
<java-symbol type="layout" name="select_dialog_singlechoice_material" />
<java-symbol type="layout" name="select_dialog_multichoice_material" />
<java-symbol type="array" name="no_ems_support_sim_operators" />
- <java-symbol type="color" name="battery_saver_mode_color" />
<java-symbol type="color" name="system_notification_accent_color" />
<java-symbol type="dimen" name="text_handle_min_size" />
<java-symbol type="id" name="transitionTransform" />
@@ -2798,7 +2796,7 @@
<java-symbol type="drawable" name="lockscreen_selected" />
<java-symbol type="string" name="notification_header_divider_symbol_with_spaces" />
- <java-symbol type="string" name="config_defaultCellBroadcastReceiverComponent" />
+ <java-symbol type="string" name="config_defaultCellBroadcastReceiverPkg" />
<java-symbol type="color" name="notification_primary_text_color_light" />
<java-symbol type="color" name="notification_primary_text_color_dark" />
@@ -2853,7 +2851,7 @@
<!-- android.service.trust -->
<java-symbol type="bool" name="config_allowEscrowTokenForTrustAgent"/>
-
+
<!-- Time picker -->
<java-symbol type="id" name="toggle_mode"/>
<java-symbol type="id" name="input_mode"/>
@@ -2880,6 +2878,8 @@
<java-symbol type="string" name="alert_windows_notification_message" />
<java-symbol type="string" name="alert_windows_notification_turn_off_action" />
<java-symbol type="drawable" name="alert_window_layer" />
+ <java-symbol type="style" name="Widget.LockPatternView" />
+ <java-symbol type="attr" name="lockPatternStyle" />
<!-- Colon separated list of package names that should be granted Notification Listener access -->
<java-symbol type="string" name="config_defaultListenerAccessPackages" />
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index e357678..d100c63 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -63,6 +63,7 @@
<item name="colorControlHighlight">@color/legacy_button_pressed</item>
<item name="colorButtonNormal">@color/legacy_button_normal</item>
<item name="colorEdgeEffect">?attr/colorPrimary</item>
+ <item name="colorError">@color/red</item>
<item name="disabledAlpha">0.5</item>
<item name="backgroundDimAmount">0.6</item>
@@ -93,7 +94,6 @@
<item name="textColorLink">@color/link_text_dark</item>
<item name="textColorLinkInverse">@color/link_text_light</item>
<item name="textColorAlertDialogListItem">@color/primary_text_light_disable_only</item>
- <item name="textColorError">@color/red</item>
<item name="textAppearanceLarge">@style/TextAppearance.Large</item>
<item name="textAppearanceMedium">@style/TextAppearance.Medium</item>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 400fb47..008c817 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -51,6 +51,7 @@
<item name="primaryContentAlpha">@dimen/primary_content_alpha_material_dark</item>
<item name="secondaryContentAlpha">@dimen/secondary_content_alpha_material_dark</item>
<item name="backgroundDimAmount">0.6</item>
+ <item name="colorError">@color/error_color_material</item>
<!-- Text styles -->
<item name="textAppearance">@style/TextAppearance.Material</item>
@@ -73,7 +74,6 @@
<item name="textColorLinkInverse">?attr/colorAccent</item>
<item name="textColorSearchUrl">@color/search_url_text_material_dark</item>
<item name="textColorAlertDialogListItem">@color/primary_text_material_dark</item>
- <item name="textColorError">@color/error_text_material_dark</item>
<item name="textAppearanceLarge">@style/TextAppearance.Material.Large</item>
<item name="textAppearanceLargeInverse">@style/TextAppearance.Material.Large.Inverse</item>
@@ -441,7 +441,6 @@
<item name="textColorLinkInverse">?attr/colorAccent</item>
<item name="textColorSearchUrl">@color/search_url_text_material_light</item>
<item name="textColorAlertDialogListItem">@color/primary_text_material_light</item>
- <item name="textColorError">@color/error_text_material_light</item>
<item name="textAppearanceLarge">@style/TextAppearance.Material.Large</item>
<item name="textAppearanceLargeInverse">@style/TextAppearance.Material.Large.Inverse</item>
@@ -823,7 +822,6 @@
<item name="textColorHighlightInverse">@color/highlighted_text_material</item>
<item name="textColorSearchUrl">@color/search_url_text_material_light</item>
<item name="textColorAlertDialogListItem">@color/primary_text_material_light</item>
- <item name="textColorError">@color/error_text_material_light</item>
<item name="textCheckMark">@drawable/indicator_check_mark_light</item>
<item name="textCheckMarkInverse">@drawable/indicator_check_mark_dark</item>
@@ -856,7 +854,6 @@
<item name="textColorHighlightInverse">@color/highlighted_text_material</item>
<item name="textColorSearchUrl">@color/search_url_text_material_dark</item>
<item name="textColorAlertDialogListItem">@color/primary_text_material_dark</item>
- <item name="textColorError">@color/error_text_material_dark</item>
<item name="textCheckMark">@drawable/indicator_check_mark_dark</item>
<item name="textCheckMarkInverse">@drawable/indicator_check_mark_light</item>
diff --git a/core/tests/coretests/src/android/net/NetworkRecommendationProviderTest.java b/core/tests/coretests/src/android/net/NetworkRecommendationProviderTest.java
index bdc0200..497bc5c 100644
--- a/core/tests/coretests/src/android/net/NetworkRecommendationProviderTest.java
+++ b/core/tests/coretests/src/android/net/NetworkRecommendationProviderTest.java
@@ -3,61 +3,62 @@
import static android.net.NetworkRecommendationProvider.EXTRA_RECOMMENDATION_RESULT;
import static android.net.NetworkRecommendationProvider.EXTRA_SEQUENCE;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertSame;
+import static junit.framework.Assert.fail;
+import static junit.framework.TestCase.assertEquals;
+
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+
+import android.Manifest.permission;
import android.content.Context;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.HandlerThread;
import android.os.IRemoteCallback;
-import android.test.InstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* Unit test for the {@link NetworkRecommendationProvider}.
*/
-public class NetworkRecommendationProviderTest extends InstrumentationTestCase {
+@RunWith(AndroidJUnit4.class)
+public class NetworkRecommendationProviderTest {
@Mock private IRemoteCallback mMockRemoteCallback;
+ @Mock private Context mContext;
private NetworkRecProvider mRecProvider;
- private Handler mHandler;
private INetworkRecommendationProvider mStub;
private CountDownLatch mRecRequestLatch;
private CountDownLatch mScoreRequestLatch;
private NetworkKey[] mTestNetworkKeys;
- @Override
+ @Before
public void setUp() throws Exception {
- super.setUp();
-
- // Configuration needed to make mockito/dexcache work.
- final Context context = getInstrumentation().getTargetContext();
- System.setProperty("dexmaker.dexcache",
- context.getCacheDir().getPath());
- ClassLoader newClassLoader = getInstrumentation().getClass().getClassLoader();
- Thread.currentThread().setContextClassLoader(newClassLoader);
-
MockitoAnnotations.initMocks(this);
- HandlerThread thread = new HandlerThread("NetworkRecommendationProviderTest");
- thread.start();
+ Executor executor = Executors.newSingleThreadExecutor();
mRecRequestLatch = new CountDownLatch(1);
mScoreRequestLatch = new CountDownLatch(1);
- mHandler = new Handler(thread.getLooper());
- mRecProvider = new NetworkRecProvider(mHandler, mRecRequestLatch, mScoreRequestLatch);
+ mRecProvider = new NetworkRecProvider(mContext, executor, mRecRequestLatch,
+ mScoreRequestLatch);
mStub = INetworkRecommendationProvider.Stub.asInterface(mRecProvider.getBinder());
mTestNetworkKeys = new NetworkKey[2];
mTestNetworkKeys[0] = new NetworkKey(new WifiKey("\"ssid_01\"", "00:00:00:00:00:11"));
mTestNetworkKeys[1] = new NetworkKey(new WifiKey("\"ssid_02\"", "00:00:00:00:00:22"));
}
- @MediumTest
+ @Test
public void testRecommendationRequestReceived() throws Exception {
final RecommendationRequest request = new RecommendationRequest.Builder().build();
final int sequence = 100;
@@ -71,7 +72,23 @@
assertEquals(expectedResultCallback, mRecProvider.mCapturedCallback);
}
- @SmallTest
+ @Test
+ public void testRecommendationRequest_permissionsEnforced() throws Exception {
+ final RecommendationRequest request = new RecommendationRequest.Builder().build();
+ final int sequence = 100;
+ Mockito.doThrow(new SecurityException())
+ .when(mContext)
+ .enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES), anyString());
+
+ try {
+ mStub.requestRecommendation(request, mMockRemoteCallback, sequence);
+ fail("SecurityException expected.");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ @Test
public void testResultCallbackOnResult() throws Exception {
final int sequence = 100;
final NetworkRecommendationProvider.ResultCallback callback =
@@ -87,7 +104,7 @@
assertSame(result, capturedBundle.getParcelable(EXTRA_RECOMMENDATION_RESULT));
}
- @SmallTest
+ @Test
public void testResultCallbackOnResult_runTwice_throwsException() throws Exception {
final int sequence = 100;
final NetworkRecommendationProvider.ResultCallback callback =
@@ -104,7 +121,7 @@
}
}
- @MediumTest
+ @Test
public void testScoreRequestReceived() throws Exception {
mStub.requestScores(mTestNetworkKeys);
@@ -114,7 +131,7 @@
assertSame(mTestNetworkKeys, mRecProvider.mCapturedNetworks);
}
- @MediumTest
+ @Test
public void testScoreRequest_nullInput() throws Exception {
mStub.requestScores(null);
@@ -122,7 +139,7 @@
assertFalse(mScoreRequestLatch.await(200, TimeUnit.MILLISECONDS));
}
- @MediumTest
+ @Test
public void testScoreRequest_emptyInput() throws Exception {
mStub.requestScores(new NetworkKey[0]);
@@ -130,6 +147,20 @@
assertFalse(mScoreRequestLatch.await(200, TimeUnit.MILLISECONDS));
}
+ @Test
+ public void testScoreRequest_permissionsEnforced() throws Exception {
+ Mockito.doThrow(new SecurityException())
+ .when(mContext)
+ .enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES), anyString());
+
+ try {
+ mStub.requestScores(mTestNetworkKeys);
+ fail("SecurityException expected.");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
private static class NetworkRecProvider extends NetworkRecommendationProvider {
private final CountDownLatch mRecRequestLatch;
private final CountDownLatch mScoreRequestLatch;
@@ -137,9 +168,9 @@
ResultCallback mCapturedCallback;
NetworkKey[] mCapturedNetworks;
- NetworkRecProvider(Handler handler, CountDownLatch recRequestLatch,
+ NetworkRecProvider(Context context, Executor executor, CountDownLatch recRequestLatch,
CountDownLatch networkRequestLatch) {
- super(handler);
+ super(context, executor);
mRecRequestLatch = recRequestLatch;
mScoreRequestLatch = networkRequestLatch;
}
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index da6a294..b718263 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -393,6 +393,7 @@
Settings.Secure.BACKUP_TRANSPORT,
Settings.Secure.BLUETOOTH_HCI_LOG,
Settings.Secure.CARRIER_APPS_HANDLED,
+ Settings.Secure.CMAS_ADDITIONAL_BROADCAST_PKG,
Settings.Secure.COMPLETED_CATEGORY_PREFIX,
Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS,
Settings.Secure.DEFAULT_INPUT_METHOD,
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index fc31f32..8f341a8 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -113,5 +113,6 @@
// for reporting callback completion
void locationCallbackFinished(ILocationListener listener);
-
+ // used by gts tests to verify throttling whitelist
+ String[] getBackgroundThrottlingWhitelist();
}
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index 6d8296a..1b53d72 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -25,6 +25,7 @@
import android.content.ContentUris;
import android.content.Intent;
import android.net.Uri;
+import android.os.Bundle;
import android.os.IBinder;
import android.provider.BaseColumns;
import android.text.TextUtils;
@@ -72,6 +73,98 @@
private static final String PATH_PASSTHROUGH = "passthrough";
/**
+ * The method name to get existing columns in the given table of the specified content provider.
+ *
+ * <p>The method caller must provide the following parameter:
+ * <ul>
+ * <li>{@code arg}: The content URI of the target table as a {@link String}.</li>
+ * </ul>
+
+ * <p>On success, the returned {@link android.os.Bundle} will include existing column names
+ * with the key {@link #EXTRA_EXISTING_COLUMN_NAMES}. Otherwise, the return value will be {@code null}.
+ *
+ * @see ContentResolver#call(Uri, String, String, Bundle)
+ * @see #EXTRA_EXISTING_COLUMN_NAMES
+ * @hide
+ */
+ @SystemApi
+ public static final String METHOD_GET_COLUMNS = "get_columns";
+
+ /**
+ * The method name to add a new column in the given table of the specified content provider.
+ *
+ * <p>The method caller must provide the following parameter:
+ * <ul>
+ * <li>{@code arg}: The content URI of the target table as a {@link String}.</li>
+ * <li>{@code extra}: Name, data type, and default value of the new column in a Bundle:
+ * <ul>
+ * <li>{@link #EXTRA_COLUMN_NAME} the column name as a {@link String}.</li>
+ * <li>{@link #EXTRA_DATA_TYPE} the data type as a {@link String}.</li>
+ * <li>{@link #EXTRA_DEFAULT_VALUE} the default value as a {@link String}.
+ * (optional)</li>
+ * </ul>
+ * </li>
+ * </ul>
+ *
+ * <p>On success, the returned {@link android.os.Bundle} will include current colum names after
+ * the addition operation with the key {@link #EXTRA_EXISTING_COLUMN_NAMES}. Otherwise, the
+ * return value will be {@code null}.
+ *
+ * @see ContentResolver#call(Uri, String, String, Bundle)
+ * @see #EXTRA_COLUMN_NAME
+ * @see #EXTRA_DATA_TYPE
+ * @see #EXTRA_DEFAULT_VALUE
+ * @see #EXTRA_EXISTING_COLUMN_NAMES
+ * @hide
+ */
+ @SystemApi
+ public static final String METHOD_ADD_COLUMN = "add_column";
+
+ /**
+ * The key for a returned {@link Bundle} value containing existing column names in the given
+ * table as an {@link ArrayList} of {@link String}.
+ *
+ * @see #METHOD_GET_COLUMNS
+ * @see #METHOD_ADD_COLUMN
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_EXISTING_COLUMN_NAMES =
+ "android.media.tv.extra.EXISTING_COLUMN_NAMES";
+
+ /**
+ * The key for a {@link Bundle} parameter containing the new column name to be added in the
+ * given table as a non-empty {@link CharSequence}.
+ *
+ * @see #METHOD_ADD_COLUMN
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_COLUMN_NAME = "android.media.tv.extra.COLUMN_NAME";
+
+ /**
+ * The key for a {@link Bundle} parameter containing the data type of the new column to be added
+ * in the given table as a non-empty {@link CharSequence}, which should be one of the following
+ * values: {@code "TEXT"}, {@code "INTEGER"}, {@code "REAL"}, or {@code "BLOB"}.
+ *
+ * @see #METHOD_ADD_COLUMN
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_DATA_TYPE = "android.media.tv.extra.DATA_TYPE";
+
+ /**
+ * The key for a {@link Bundle} parameter containing the default value of the new column to be
+ * added in the given table as a {@link CharSequence}, which represents a valid default value
+ * according to the data type provided with {@link #EXTRA_DATA_TYPE}.
+ *
+ * @see #METHOD_ADD_COLUMN
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_DEFAULT_VALUE = "android.media.tv.extra.DEFAULT_VALUE";
+
+ /**
* An optional query, update or delete URI parameter that allows the caller to specify TV input
* ID to filter channels.
* @hide
diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
index d207c35..9ff22c7 100644
--- a/packages/SettingsLib/res/values/arrays.xml
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -538,7 +538,7 @@
<item>100</item>
</array>
<array name="batterymeter_color_values">
- <item>@*android:color/battery_saver_mode_color</item>
+ <item>?android:attr/colorError</item>
<item>@android:color/white</item>
</array>
<array name="batterymeter_bolt_points">
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
index 99d7f1e..49fc2ea 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
@@ -16,6 +16,11 @@
package com.android.settingslib;
+import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE;
+import static android.app.admin.DevicePolicyManager.PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.AppGlobals;
import android.app.admin.DevicePolicyManager;
@@ -29,6 +34,7 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
+import android.support.annotation.VisibleForTesting;
import android.text.Spanned;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
@@ -108,47 +114,68 @@
}
/**
- * Checks if keyguard features are disabled by policy.
+ * Checks whether keyguard features are disabled by policy.
*
- * @param keyguardFeatures Could be any of keyguard features that can be
+ * @param context {@link Context} for the calling user.
+ *
+ * @param keyguardFeatures Any one of keyguard features that can be
* disabled by {@link android.app.admin.DevicePolicyManager#setKeyguardDisabledFeatures}.
+ *
+ * @param userId User to check enforced admin status for.
+ *
* @return EnforcedAdmin Object containing the enforced admin component and admin user details,
* or {@code null} If the notification features are not disabled. If the restriction is set by
* multiple admins, then the admin component will be set to {@code null} and userId to
* {@link UserHandle#USER_NULL}.
*/
public static EnforcedAdmin checkIfKeyguardFeaturesDisabled(Context context,
- int keyguardFeatures, int userId) {
- final LockSettingCheck check =
- (DevicePolicyManager dpm, ComponentName admin, @UserIdInt int checkUser) ->
- (dpm.getKeyguardDisabledFeatures(admin, checkUser) & keyguardFeatures) != 0;
+ int keyguardFeatures, final @UserIdInt int userId) {
+ final LockSettingCheck check = (dpm, admin, checkUser) -> {
+ int effectiveFeatures = dpm.getKeyguardDisabledFeatures(admin, checkUser);
+ if (checkUser != userId) {
+ effectiveFeatures &= PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER;
+ }
+ return (effectiveFeatures & keyguardFeatures) != KEYGUARD_DISABLE_FEATURES_NONE;
+ };
+ if (UserManager.get(context).getUserInfo(userId).isManagedProfile()) {
+ DevicePolicyManager dpm =
+ (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
+ return findEnforcedAdmin(dpm.getActiveAdminsAsUser(userId), dpm, userId, check);
+ }
+ return checkForLockSetting(context, userId, check);
+ }
- final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
- Context.DEVICE_POLICY_SERVICE);
- if (dpm == null) {
+ /**
+ * Filter a set of device admins based on a predicate {@code check}. This is equivalent to
+ * {@code admins.stream().filter(check).map(x → new EnforcedAdmin(admin, userId)} except it's
+ * returning a zero/one/many-type thing.
+ *
+ * @param admins set of candidate device admins identified by {@link ComponentName}.
+ * @param userId user to create the resultant {@link EnforcedAdmin} as.
+ * @param check filter predicate.
+ *
+ * @return {@code null} if none of the {@param admins} match.
+ * An {@link EnforcedAdmin} if exactly one of the admins matches.
+ * Otherwise, {@link EnforcedAdmin#MULTIPLE_ENFORCED_ADMIN} for multiple matches.
+ */
+ @Nullable
+ private static EnforcedAdmin findEnforcedAdmin(@Nullable List<ComponentName> admins,
+ @NonNull DevicePolicyManager dpm, @UserIdInt int userId,
+ @NonNull LockSettingCheck check) {
+ if (admins == null) {
return null;
}
-
- final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
- if (um.getUserInfo(userId).isManagedProfile()) {
- final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userId);
- if (admins == null) {
- return null;
- }
- EnforcedAdmin enforcedAdmin = null;
- for (ComponentName admin : admins) {
- if (check.isEnforcing(dpm, admin, userId)) {
- if (enforcedAdmin == null) {
- enforcedAdmin = new EnforcedAdmin(admin, userId);
- } else {
- return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
- }
+ EnforcedAdmin enforcedAdmin = null;
+ for (ComponentName admin : admins) {
+ if (check.isEnforcing(dpm, admin, userId)) {
+ if (enforcedAdmin == null) {
+ enforcedAdmin = new EnforcedAdmin(admin, userId);
+ } else {
+ return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
}
}
- return enforcedAdmin;
- } else {
- return checkForLockSetting(context, userId, check);
}
+ return enforcedAdmin;
}
public static EnforcedAdmin checkIfUninstallBlocked(Context context,
@@ -361,7 +388,7 @@
}
LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
- if (lockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
+ if (sProxy.isSeparateProfileChallengeEnabled(lockPatternUtils, userId)) {
// userId is managed profile and has a separate challenge, only consider
// the admins in that user.
final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userId);
@@ -428,7 +455,7 @@
if (userInfo.isManagedProfile()) {
// If userInfo.id is a managed profile, we also need to look at
// the policies set on the parent.
- final DevicePolicyManager parentDpm = dpm.getParentProfileInstance(userInfo);
+ DevicePolicyManager parentDpm = sProxy.getParentProfileInstance(dpm, userInfo);
if (parentDpm.getMaximumTimeToLock(admin, userInfo.id) > 0) {
if (enforcedAdmin == null) {
enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
@@ -448,8 +475,9 @@
/**
* Checks whether any of the user's profiles enforce the lock setting. A managed profile is only
- * included if it does not have a separate challenege but the settings for it's parent (i.e. the
- * user being checked) are always included.
+ * included if it does not have a separate challenge.
+ *
+ * The user identified by {@param userId} is always included.
*/
private static EnforcedAdmin checkForLockSetting(
Context context, @UserIdInt int userId, LockSettingCheck check) {
@@ -468,7 +496,7 @@
continue;
}
final boolean isSeparateProfileChallengeEnabled =
- lockPatternUtils.isSeparateProfileChallengeEnabled(userInfo.id);
+ sProxy.isSeparateProfileChallengeEnabled(lockPatternUtils, userInfo.id);
for (ComponentName admin : admins) {
if (!isSeparateProfileChallengeEnabled) {
if (check.isEnforcing(dpm, admin, userInfo.id)) {
@@ -487,7 +515,7 @@
if (userInfo.isManagedProfile()) {
// If userInfo.id is a managed profile, we also need to look at
// the policies set on the parent.
- final DevicePolicyManager parentDpm = dpm.getParentProfileInstance(userInfo);
+ DevicePolicyManager parentDpm = sProxy.getParentProfileInstance(dpm, userInfo);
if (check.isEnforcing(parentDpm, admin, userInfo.id)) {
if (enforcedAdmin == null) {
enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
@@ -733,4 +761,23 @@
other.userId = userId;
}
}
+
+ /**
+ * Static {@link LockPatternUtils} and {@link DevicePolicyManager} wrapper for testing purposes.
+ * {@link LockPatternUtils} is an internal API not supported by robolectric.
+ * {@link DevicePolicyManager} has a {@code getProfileParent} not yet suppored by robolectric.
+ */
+ @VisibleForTesting
+ static Proxy sProxy = new Proxy();
+
+ @VisibleForTesting
+ static class Proxy {
+ public boolean isSeparateProfileChallengeEnabled(LockPatternUtils utils, int userHandle) {
+ return utils.isSeparateProfileChallengeEnabled(userHandle);
+ }
+
+ public DevicePolicyManager getParentProfileInstance(DevicePolicyManager dpm, UserInfo ui) {
+ return dpm.getParentProfileInstance(ui);
+ }
+ }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index 7a4514a..7e7b391 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -184,10 +184,7 @@
@ColorInt
public static int getColorError(Context context) {
- TypedArray ta = context.obtainStyledAttributes(new int[]{android.R.attr.textColorError});
- @ColorInt int colorError = ta.getColor(0, 0);
- ta.recycle();
- return colorError;
+ return getColorAttr(context, android.R.attr.colorError);
}
@ColorInt
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
index fd2e7ca..6764a6b 100755
--- a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
@@ -29,7 +29,8 @@
import android.graphics.RectF;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
-import android.provider.Settings;
+import android.util.TypedValue;
+
import com.android.settingslib.R;
import com.android.settingslib.Utils;
@@ -97,9 +98,13 @@
final int N = levels.length();
mColors = new int[2 * N];
- for (int i = 0; i < N; i++) {
+ for (int i=0; i < N; i++) {
mColors[2 * i] = levels.getInt(i, 0);
- mColors[2 * i + 1] = colors.getColor(i, 0);
+ if (colors.getType(i) == TypedValue.TYPE_ATTRIBUTE) {
+ mColors[2 * i + 1] = Utils.getColorAttr(context, colors.getResourceId(i, 0));
+ } else {
+ mColors[2 * i + 1] = colors.getColor(i, 0);
+ }
}
levels.recycle();
colors.recycle();
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
index 2958740..c506358 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
@@ -16,6 +16,17 @@
package com.android.settingslib;
+import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE;
+import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT;
+import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT;
+import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS;
+import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.when;
+
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
@@ -25,18 +36,13 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;
import java.util.Arrays;
-import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT;
-import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT;
-import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.when;
-
@RunWith(SettingLibRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class RestrictedLockUtilsTest {
@@ -47,8 +53,11 @@
private DevicePolicyManager mDevicePolicyManager;
@Mock
private UserManager mUserManager;
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private RestrictedLockUtils.Proxy mProxy;
private static final int mUserId = 194;
+ private static final int mProfileId = 160;
private static final ComponentName mAdmin1 = new ComponentName("admin1", "admin1class");
private static final ComponentName mAdmin2 = new ComponentName("admin2", "admin2class");
@@ -60,12 +69,13 @@
.thenReturn(mDevicePolicyManager);
when(mContext.getSystemService(Context.USER_SERVICE))
.thenReturn(mUserManager);
+
+ RestrictedLockUtils.sProxy = mProxy;
}
@Test
public void checkIfKeyguardFeaturesDisabled_noEnforcedAdminForManagedProfile() {
- setUpManagedProfile(mUserId);
- setUpActiveAdmins(mUserId, new ComponentName[] {mAdmin1, mAdmin2});
+ setUpManagedProfile(mUserId, new ComponentName[] {mAdmin1, mAdmin2});
final EnforcedAdmin enforcedAdmin = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
mContext, KEYGUARD_DISABLE_FINGERPRINT, mUserId);
@@ -75,8 +85,7 @@
@Test
public void checkIfKeyguardFeaturesDisabled_oneEnforcedAdminForManagedProfile() {
- setUpManagedProfile(mUserId);
- setUpActiveAdmins(mUserId, new ComponentName[] {mAdmin1, mAdmin2});
+ setUpManagedProfile(mUserId, new ComponentName[] {mAdmin1, mAdmin2});
when(mDevicePolicyManager.getKeyguardDisabledFeatures(mAdmin1, mUserId))
.thenReturn(KEYGUARD_DISABLE_FINGERPRINT);
@@ -89,8 +98,7 @@
@Test
public void checkIfKeyguardFeaturesDisabled_multipleEnforcedAdminForManagedProfile() {
- setUpManagedProfile(mUserId);
- setUpActiveAdmins(mUserId, new ComponentName[] {mAdmin1, mAdmin2});
+ setUpManagedProfile(mUserId, new ComponentName[] {mAdmin1, mAdmin2});
when(mDevicePolicyManager.getKeyguardDisabledFeatures(mAdmin1, mUserId))
.thenReturn(KEYGUARD_DISABLE_REMOTE_INPUT);
@@ -103,9 +111,129 @@
assertThat(enforcedAdmin).isEqualTo(EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN);
}
- private UserInfo setUpManagedProfile(int userId) {
- final UserInfo userInfo = new UserInfo(userId, "myuser", UserInfo.FLAG_MANAGED_PROFILE);
+ @Test
+ public void checkIfKeyguardFeaturesAreDisabled_doesMatchAllowedFeature_unifiedManagedProfile() {
+ UserInfo userInfo = setUpUser(mUserId, new ComponentName[] {mAdmin1});
+ UserInfo profileInfo = setUpManagedProfile(mProfileId, new ComponentName[] {mAdmin2});
+ when(mUserManager.getProfiles(mUserId)).thenReturn(Arrays.asList(new UserInfo[] {
+ userInfo, profileInfo}));
+
+ when(mDevicePolicyManager.getKeyguardDisabledFeatures(mAdmin1, mUserId))
+ .thenReturn(KEYGUARD_DISABLE_FEATURES_NONE);
+ when(mDevicePolicyManager.getKeyguardDisabledFeatures(mAdmin2, mProfileId))
+ .thenReturn(KEYGUARD_DISABLE_FINGERPRINT);
+
+ // Querying the parent should return the policy, since it affects the parent.
+ EnforcedAdmin parent = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+ mContext, KEYGUARD_DISABLE_FINGERPRINT, mUserId);
+ assertThat(parent).isEqualTo(new EnforcedAdmin(mAdmin2, mProfileId));
+
+ // Querying the child should return that too.
+ EnforcedAdmin profile = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+ mContext, KEYGUARD_DISABLE_FINGERPRINT, mProfileId);
+ assertThat(profile).isEqualTo(new EnforcedAdmin(mAdmin2, mProfileId));
+
+ // Querying for some unrelated feature should return nothing. Nothing!
+ assertThat(RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+ mContext, KEYGUARD_DISABLE_REMOTE_INPUT, mUserId)).isNull();
+ assertThat(RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+ mContext, KEYGUARD_DISABLE_REMOTE_INPUT, mProfileId)).isNull();
+ }
+
+ @Test
+ public void checkIfKeyguardFeaturesAreDisabled_notMatchOtherFeatures_unifiedManagedProfile() {
+ UserInfo userInfo = setUpUser(mUserId, new ComponentName[] {mAdmin1});
+ UserInfo profileInfo = setUpManagedProfile(mProfileId, new ComponentName[] {mAdmin2});
+ when(mUserManager.getProfiles(mUserId)).thenReturn(Arrays.asList(new UserInfo[] {
+ userInfo, profileInfo}));
+
+ when(mDevicePolicyManager.getKeyguardDisabledFeatures(mAdmin1, mUserId))
+ .thenReturn(KEYGUARD_DISABLE_FEATURES_NONE);
+ when(mDevicePolicyManager.getKeyguardDisabledFeatures(mAdmin2, mProfileId))
+ .thenReturn(KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
+
+ // Querying the parent should not return the policy, because it's not a policy that should
+ // affect parents even when the lock screen is unified.
+ EnforcedAdmin primary = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+ mContext, KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS, mUserId);
+ assertThat(primary).isNull();
+
+ // Querying the child should still return the policy.
+ EnforcedAdmin profile = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+ mContext, KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS, mProfileId);
+ assertThat(profile).isEqualTo(new EnforcedAdmin(mAdmin2, mProfileId));
+ }
+
+ @Test
+ public void checkIfKeyguardFeaturesAreDisabled_onlyMatchesProfile_separateManagedProfile() {
+ UserInfo userInfo = setUpUser(mUserId, new ComponentName[] {mAdmin1});
+ UserInfo profileInfo = setUpManagedProfile(mProfileId, new ComponentName[] {mAdmin2});
+ when(mUserManager.getProfiles(mUserId)).thenReturn(Arrays.asList(new UserInfo[] {
+ userInfo, profileInfo}));
+
+ when(mDevicePolicyManager.getKeyguardDisabledFeatures(mAdmin1, mUserId))
+ .thenReturn(KEYGUARD_DISABLE_FEATURES_NONE);
+ when(mDevicePolicyManager.getKeyguardDisabledFeatures(mAdmin2, mProfileId))
+ .thenReturn(KEYGUARD_DISABLE_FINGERPRINT);
+
+ // Crucially for this test, isSeparateWorkChallengeEnabled => true.
+ doReturn(true).when(mProxy).isSeparateProfileChallengeEnabled(any(), eq(mProfileId));
+
+ // Querying the parent should not return the policy, even though it's shared by default,
+ // because the parent doesn't share a lock screen with the profile any more.
+ EnforcedAdmin parent = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+ mContext, KEYGUARD_DISABLE_FINGERPRINT, mUserId);
+ assertThat(parent).isNull();
+
+ // Querying the child should still return the policy.
+ EnforcedAdmin profile = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+ mContext, KEYGUARD_DISABLE_FINGERPRINT, mProfileId);
+ assertThat(profile).isEqualTo(new EnforcedAdmin(mAdmin2, mProfileId));
+ }
+
+ /**
+ * This test works great. The real world implementation is sketchy though.
+ * <p>
+ * DevicePolicyManager.getParentProfileInstance(UserInfo) does not do what it looks like it does
+ * (which would be to get an instance for the parent of the user that's passed in to it.)
+ * <p>
+ * Instead it just always returns a parent instance for the current user.
+ * <p>
+ * Still, the test works.
+ */
+ @Test
+ public void checkIfKeyguardFeaturesAreDisabled_onlyMatchesParent_profileParentPolicy() {
+ UserInfo userInfo = setUpUser(mUserId, new ComponentName[] {mAdmin1});
+ UserInfo profileInfo = setUpManagedProfile(mProfileId, new ComponentName[] {mAdmin2});
+ when(mUserManager.getProfiles(mUserId)).thenReturn(Arrays.asList(new UserInfo[] {
+ userInfo, profileInfo}));
+
+ when(mProxy.getParentProfileInstance(any(DevicePolicyManager.class), any())
+ .getKeyguardDisabledFeatures(mAdmin2, mProfileId))
+ .thenReturn(KEYGUARD_DISABLE_FINGERPRINT);
+
+ // Parent should get the policy.
+ EnforcedAdmin parent = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+ mContext, KEYGUARD_DISABLE_FINGERPRINT, mUserId);
+ assertThat(parent).isEqualTo(new EnforcedAdmin(mAdmin2, mProfileId));
+
+ // Profile should not get the policy.
+ EnforcedAdmin profile = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+ mContext, KEYGUARD_DISABLE_FINGERPRINT, mProfileId);
+ assertThat(profile).isNull();
+ }
+
+ private UserInfo setUpUser(int userId, ComponentName[] admins) {
+ UserInfo userInfo = new UserInfo(userId, "primary", 0);
when(mUserManager.getUserInfo(userId)).thenReturn(userInfo);
+ setUpActiveAdmins(userId, admins);
+ return userInfo;
+ }
+
+ private UserInfo setUpManagedProfile(int userId, ComponentName[] admins) {
+ UserInfo userInfo = new UserInfo(userId, "profile", UserInfo.FLAG_MANAGED_PROFILE);
+ when(mUserManager.getUserInfo(userId)).thenReturn(userInfo);
+ setUpActiveAdmins(userId, admins);
return userInfo;
}
diff --git a/packages/SystemUI/res/drawable/ic_fingerprint_error.xml b/packages/SystemUI/res/drawable/ic_fingerprint_error.xml
index 11e83a1..a7fb1a1 100644
--- a/packages/SystemUI/res/drawable/ic_fingerprint_error.xml
+++ b/packages/SystemUI/res/drawable/ic_fingerprint_error.xml
@@ -19,12 +19,12 @@
android:viewportWidth="32.0"
android:viewportHeight="32.0">
<path
- android:fillColor="@color/system_warning_color"
+ android:fillColor="?android:attr/colorError"
android:pathData="M15.99,2.5C8.53,2.5 2.5,8.54 2.5,16.0s6.03,13.5 13.49,13.5S29.5,23.46 29.5,16.0S23.45,2.5 15.99,2.5zM16.0,26.8c-5.97,0.0 -10.8,-4.83 -10.8,-10.8S10.03,5.2 16.0,5.2S26.8,10.03 26.8,16.0S21.97,26.8 16.0,26.8z"/>
<path
- android:fillColor="@color/system_warning_color"
+ android:fillColor="?android:attr/colorError"
android:pathData="M14.65,20.05l2.7,0.0l0.0,2.7l-2.7,0.0z"/>
<path
- android:fillColor="@color/system_warning_color"
+ android:fillColor="?android:attr/colorError"
android:pathData="M14.65,9.25l2.7,0.0l0.0,8.1l-2.7,0.0z"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/lockscreen_fingerprint_error_state_to_fp.xml b/packages/SystemUI/res/drawable/lockscreen_fingerprint_error_state_to_fp.xml
index e207cb3..3af2f7f 100644
--- a/packages/SystemUI/res/drawable/lockscreen_fingerprint_error_state_to_fp.xml
+++ b/packages/SystemUI/res/drawable/lockscreen_fingerprint_error_state_to_fp.xml
@@ -98,11 +98,11 @@
<path
android:name="path_2"
android:pathData="M 1.35900878906,6.76104736328 c 0.0,0.0 -2.69998168945,0.0 -2.69998168945,0.0 c 0.0,0.0 0.0,-2.69995117188 0.0,-2.69995117188 c 0.0,0.0 2.69998168945,0.0 2.69998168945,0.0 c 0.0,0.0 0.0,2.69995117188 0.0,2.69995117188 Z"
- android:fillColor="@*android:color/system_error" />
+ android:fillColor="?android:attr/colorError" />
<path
android:name="path_1"
android:pathData="M 1.35363769531,1.36633300781 c 0.0,0.0 -2.69998168945,0.0 -2.69998168945,0.0 c 0.0,0.0 0.0,-8.09997558594 0.0,-8.09997558594 c 0.0,0.0 2.69998168945,0.0 2.69998168945,0.0 c 0.0,0.0 0.0,8.09997558594 0.0,8.09997558594 Z"
- android:fillColor="@*android:color/system_error" />
+ android:fillColor="?android:attr/colorError" />
</group>
</group>
<group
@@ -117,7 +117,7 @@
<path
android:name="path_3"
android:pathData="M 0.0101470947266,10.8087768555 c -5.96701049805,0.0 -10.8000183105,-4.8330078125 -10.8000183105,-10.8000488281 c 0.0,-5.96691894531 4.8330078125,-10.7999267578 10.8000183105,-10.7999267578 c 5.96697998047,0.0 10.799987793,4.8330078125 10.799987793,10.7999267578 c 0.0,5.96704101562 -4.8330078125,10.8000488281 -10.799987793,10.8000488281 Z"
- android:strokeColor="@*android:color/system_error"
+ android:strokeColor="?android:attr/colorError"
android:strokeWidth="2"
android:trimPathStart="0"
android:trimPathEnd="1" />
diff --git a/packages/SystemUI/res/drawable/lockscreen_fingerprint_fp_to_error_state.xml b/packages/SystemUI/res/drawable/lockscreen_fingerprint_fp_to_error_state.xml
index 2b4babc..a577afc 100644
--- a/packages/SystemUI/res/drawable/lockscreen_fingerprint_fp_to_error_state.xml
+++ b/packages/SystemUI/res/drawable/lockscreen_fingerprint_fp_to_error_state.xml
@@ -96,7 +96,7 @@
<path
android:name="ridge_5_path_0"
android:pathData="M -25.3591003418,-24.4138946533 c -0.569000244141,0.106399536133 -1.12660217285,0.140594482422 -1.45460510254,0.140594482422 c -1.29689025879,0.0 -2.53239440918,-0.343307495117 -3.62019348145,-1.12400817871 c -1.67700195312,-1.20349121094 -2.76950073242,-3.17008972168 -2.76950073242,-5.39189147949"
- android:strokeColor="@*android:color/system_error"
+ android:strokeColor="?android:attr/colorError"
android:strokeWidth="1.45"
android:strokeLineCap="round"
android:trimPathEnd="0" />
@@ -106,7 +106,7 @@
<path
android:name="ridge_7_path_0"
android:pathData="M -36.1409912109,-21.7843475342 c -1.00540161133,-1.19300842285 -1.57499694824,-1.9181060791 -2.36520385742,-3.50170898438 c -0.827560424805,-1.65869140625 -1.31352233887,-3.49159240723 -1.31352233887,-5.48489379883 c 0.0,-3.66279602051 2.96932983398,-6.63220214844 6.63221740723,-6.63220214844 c 3.6628112793,0.0 6.63220214844,2.96940612793 6.63220214844,6.63220214844"
- android:strokeColor="@*android:color/system_error"
+ android:strokeColor="?android:attr/colorError"
android:strokeWidth="1.45"
android:strokeLineCap="round"
android:trimPathEnd="0" />
@@ -116,7 +116,7 @@
<path
android:name="ridge_6_path_0"
android:pathData="M -42.1907958984,-25.6756896973 c -0.758117675781,-2.14370727539 -0.896545410156,-3.86891174316 -0.896545410156,-5.12921142578 c 0.0,-1.46069335938 0.249176025391,-2.84799194336 0.814682006836,-4.09748840332 c 1.56153869629,-3.45030212402 5.03434753418,-5.85076904297 9.0679473877,-5.85076904297 c 5.49430847168,0.0 9.94830322266,4.4539642334 9.94830322266,9.94825744629 c 0.0,1.83151245117 -1.48460388184,3.31610107422 -3.31610107422,3.31610107422 c -1.83149719238,0.0 -3.31610107422,-1.48469543457 -3.31610107422,-3.31610107422 c 0.0,-1.83139038086 -1.48458862305,-3.31610107422 -3.31610107422,-3.31610107422 c -1.83149719238,0.0 -3.31610107422,1.48471069336 -3.31610107422,3.31610107422 c 0.0,2.57020568848 0.989517211914,4.88710021973 2.60510253906,6.5865020752 c 1.22210693359,1.28550720215 2.43139648438,2.09950256348 4.47590637207,2.69030761719"
- android:strokeColor="@*android:color/system_error"
+ android:strokeColor="?android:attr/colorError"
android:strokeWidth="1.45"
android:strokeLineCap="round"
android:trimPathEnd="0" />
@@ -126,7 +126,7 @@
<path
android:name="ridge_2_path_0"
android:pathData="M -44.0646514893,-38.1672973633 c 1.19026184082,-1.77430725098 2.67503356934,-3.24531555176 4.55902099609,-4.27278137207 c 1.88395690918,-1.0274810791 4.04466247559,-1.61137390137 6.34175109863,-1.61137390137 c 2.28761291504,0.0 4.43991088867,0.579071044922 6.31831359863,1.59861755371 c 1.8784942627,1.01954650879 3.36059570312,2.4796295166 4.55279541016,4.24153137207"
- android:strokeColor="@*android:color/system_error"
+ android:strokeColor="?android:attr/colorError"
android:strokeWidth="1.45"
android:strokeLineCap="round"
android:trimPathStart="1" />
@@ -138,7 +138,7 @@
<path
android:name="ridge_1_path_0"
android:pathData="M 71.7812347412,97.0507202148 c -2.27149963379,-1.31344604492 -4.71360778809,-2.07006835938 -7.56221008301,-2.07006835938 c -2.84869384766,0.0 -5.23320007324,0.779556274414 -7.34411621094,2.07006835938"
- android:strokeColor="@*android:color/system_error"
+ android:strokeColor="?android:attr/colorError"
android:strokeWidth="1.45"
android:strokeLineCap="round"
android:trimPathEnd="0" />
@@ -157,11 +157,11 @@
<path
android:name="path_2"
android:pathData="M -1.3705291748,4.06730651855 c 0.0,0.0 0.036376953125,-0.0102386474609 0.036376953125,-0.0102386474609 c 0.0,0.0 -0.00682067871094,0.0040283203125 -0.00682067871093,0.0040283203125 c 0.0,0.0 -0.0161437988281,0.00479125976562 -0.0161437988281,0.00479125976563 c 0.0,0.0 -0.0134124755859,0.00141906738281 -0.0134124755859,0.00141906738281 Z"
- android:fillColor="@*android:color/system_error" />
+ android:fillColor="?android:attr/colorError" />
<path
android:name="path_1"
android:pathData="M -1.3737487793,-6.77532958984 c 0.0,0.0 0.00604248046875,0.0166625976562 0.00604248046876,0.0166625976562 c 0.0,0.0 0.0213623046875,0.0250244140625 0.0213623046875,0.0250244140625 c 0.0,0.0 -0.00604248046875,-0.0166625976562 -0.00604248046876,-0.0166625976562 c 0.0,0.0 -0.0213623046875,-0.0250244140625 -0.0213623046875,-0.0250244140625 Z"
- android:fillColor="@*android:color/system_error" />
+ android:fillColor="?android:attr/colorError" />
</group>
</group>
<group
@@ -176,7 +176,7 @@
<path
android:name="path_3"
android:pathData="M 0.0101470947266,10.8087768555 c -5.96701049805,0.0 -10.8000183105,-4.8330078125 -10.8000183105,-10.8000488281 c 0.0,-5.96691894531 4.8330078125,-10.7999267578 10.8000183105,-10.7999267578 c 5.96697998047,0.0 10.799987793,4.8330078125 10.799987793,10.7999267578 c 0.0,5.96704101562 -4.8330078125,10.8000488281 -10.799987793,10.8000488281 Z"
- android:strokeColor="@*android:color/system_error"
+ android:strokeColor="?android:attr/colorError"
android:strokeWidth="2"
android:trimPathStart="1" />
</group>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 407cddf..f461bb3 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -27,7 +27,6 @@
<color name="notification_list_shadow_top">#80000000</color>
<drawable name="heads_up_notification_bg_pressed">#ff33B5E5</drawable>
<color name="qs_batterymeter_frame_color">#FF404040</color>
- <color name="system_warning_color">@*android:color/system_error</color>
<color name="qs_tile_divider">#29ffffff</color><!-- 16% white -->
<color name="qs_subhead">#99FFFFFF</color><!-- 60% white -->
<color name="qs_detail_button">@*android:color/quaternary_device_default_settings</color>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 48b7664..9168256 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -30,7 +30,7 @@
<!-- Recents theme -->
<style name="RecentsTheme.Wallpaper">
- <item name="android:windowBackground">@color/transparent</item>
+ <item name="android:windowBackground">@*android:color/transparent</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:windowShowWallpaper">true</item>
<item name="android:windowDisablePreview">true</item>
@@ -52,7 +52,7 @@
<!-- Theme used for the activity that shows when the system forced an app to be resizable -->
<style name="ForcedResizableTheme" parent="@android:style/Theme.Translucent.NoTitleBar">
<item name="android:windowBackground">@drawable/forced_resizable_background</item>
- <item name="android:statusBarColor">@color/transparent</item>
+ <item name="android:statusBarColor">@*android:color/transparent</item>
<item name="android:windowAnimationStyle">@style/Animation.ForcedResizable</item>
</style>
@@ -70,7 +70,7 @@
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowBackground">@null</item>
<item name="android:colorBackgroundCacheHint">@null</item>
- <item name="android:statusBarColor">@color/transparent</item>
+ <item name="android:statusBarColor">@*android:color/transparent</item>
<item name="android:windowAnimationStyle">@style/Animation.PipPhoneOverlayControl</item>
</style>
@@ -164,7 +164,7 @@
<style name="TextAppearance.QS.Warning">
<item name="android:textSize">14sp</item>
- <item name="android:textColor">@color/system_warning_color</item>
+ <item name="android:textColor">?android:attr/colorError</item>
</style>
<style name="TextAppearance.QS.DetailButton">
@@ -366,7 +366,7 @@
</style>
<style name="TextAppearance.NotificationGuts.SecondaryWarning">
- <item name="android:textColor">@color/system_warning_color</item>
+ <item name="android:textColor">?android:attr/colorError</item>
<item name="android:textSize">12sp</item>
</style>
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index f1e7d53..ac7ab9d 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -47,6 +47,8 @@
import com.android.systemui.statusbar.policy.DataSaverController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
+import com.android.systemui.statusbar.policy.ExtensionController;
+import com.android.systemui.statusbar.policy.ExtensionControllerImpl;
import com.android.systemui.statusbar.policy.FlashlightController;
import com.android.systemui.statusbar.policy.FlashlightControllerImpl;
import com.android.systemui.statusbar.policy.HotspotController;
@@ -233,6 +235,9 @@
mProviders.put(FragmentService.class, () ->
new FragmentService(mContext));
+ mProviders.put(ExtensionController.class, () ->
+ new ExtensionControllerImpl());
+
// Put all dependencies above here so the factory can override them if it wants.
SystemUIFactory.getInstance().injectDependencies(mProviders, mContext);
}
diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginManager.java b/packages/SystemUI/src/com/android/systemui/plugins/PluginManager.java
index 8b4bd7b..0c3e40c 100644
--- a/packages/SystemUI/src/com/android/systemui/plugins/PluginManager.java
+++ b/packages/SystemUI/src/com/android/systemui/plugins/PluginManager.java
@@ -133,14 +133,7 @@
public <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<?> cls,
boolean allowMultiple) {
- ProvidesInterface info = cls.getDeclaredAnnotation(ProvidesInterface.class);
- if (info == null) {
- throw new RuntimeException(cls + " doesn't provide an interface");
- }
- if (TextUtils.isEmpty(info.action())) {
- throw new RuntimeException(cls + " doesn't provide an action");
- }
- addPluginListener(info.action(), listener, cls, allowMultiple);
+ addPluginListener(getAction(cls), listener, cls, allowMultiple);
}
public <T extends Plugin> void addPluginListener(String action, PluginListener<T> listener,
@@ -285,6 +278,17 @@
return new PluginContextWrapper(mContext.createApplicationContext(info, 0), classLoader);
}
+ public static <P> String getAction(Class<P> cls) {
+ ProvidesInterface info = cls.getDeclaredAnnotation(ProvidesInterface.class);
+ if (info == null) {
+ throw new RuntimeException(cls + " doesn't provide an interface");
+ }
+ if (TextUtils.isEmpty(info.action())) {
+ throw new RuntimeException(cls + " doesn't provide an action");
+ }
+ return info.action();
+ }
+
private class AllPluginClassLoader extends ClassLoader {
public AllPluginClassLoader(ClassLoader classLoader) {
super(classLoader);
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index 09ce2ad..daf0622 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -39,6 +39,7 @@
import android.util.Slog;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.settingslib.Utils;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -175,8 +176,7 @@
.setOnlyAlertOnce(true)
.setDeleteIntent(pendingBroadcast(ACTION_DISMISSED_WARNING))
.setVisibility(Notification.VISIBILITY_PUBLIC)
- .setColor(mContext.getColor(
- com.android.internal.R.color.battery_saver_mode_color));
+ .setColor(Utils.getColorAttr(mContext, android.R.attr.colorError));
if (hasBatterySettings()) {
nb.setContentIntent(pendingBroadcast(ACTION_SHOW_BATTERY_SETTINGS));
}
@@ -245,8 +245,7 @@
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setContentIntent(pendingBroadcast(ACTION_CLICKED_TEMP_WARNING))
.setDeleteIntent(pendingBroadcast(ACTION_DISMISSED_TEMP_WARNING))
- .setColor(mContext.getColor(
- com.android.internal.R.color.battery_saver_mode_color));
+ .setColor(Utils.getColorAttr(mContext, android.R.attr.colorError));
SystemUI.overrideNotificationAppName(mContext, nb);
final Notification n = nb.build();
mNoMan.notifyAsUser(TAG_TEMPERATURE, SystemMessage.NOTE_HIGH_TEMP, n, UserHandle.ALL);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
index c7b6aea..9cd79f8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
@@ -91,7 +91,7 @@
formatBytes(info.usageLevel));
bottom = res.getString(R.string.quick_settings_cellular_detail_data_limit,
formatBytes(info.limitLevel));
- usageColor = mContext.getColor(R.color.system_warning_color);
+ usageColor = Utils.getDefaultColor(mContext, android.R.attr.colorError);
}
if (usageColor == 0) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index bc992d8..fb92a67 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -42,6 +42,7 @@
import com.android.internal.app.IBatteryStats;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.settingslib.Utils;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
@@ -365,7 +366,7 @@
if (!updateMonitor.isUnlockingWithFingerprintAllowed()) {
return;
}
- int errorColor = mContext.getResources().getColor(R.color.system_warning_color, null);
+ int errorColor = Utils.getColorError(mContext);
if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
mStatusBarKeyguardViewManager.showBouncerMessage(helpString, errorColor);
} else if (updateMonitor.isDeviceInteractive()
@@ -388,7 +389,7 @@
|| msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
return;
}
- int errorColor = mContext.getResources().getColor(R.color.system_warning_color, null);
+ int errorColor = Utils.getColorError(mContext);
if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
// When swiping up right after receiving a fingerprint error, the bouncer calls
// authenticate leading to the same message being shown again on the bouncer.
@@ -411,8 +412,7 @@
@Override
public void onScreenTurnedOn() {
if (mMessageToShowOnScreenOn != null) {
- int errorColor = mContext.getResources().getColor(R.color.system_warning_color,
- null);
+ int errorColor = Utils.getColorError(mContext);
showTransientIndication(mMessageToShowOnScreenOn, errorColor);
// We want to keep this message around in case the screen was off
mHandler.removeMessages(MSG_HIDE_TRANSIENT);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
index ed71e57..f3c2bc5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
@@ -33,6 +33,7 @@
import android.util.Log;
import android.view.View;
+import com.android.settingslib.Utils;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
@@ -167,7 +168,7 @@
mSemiTransparent = context.getColor(
com.android.internal.R.color.system_bar_background_semi_transparent);
mTransparent = context.getColor(R.color.system_bar_background_transparent);
- mWarning = context.getColor(com.android.internal.R.color.battery_saver_mode_color);
+ mWarning = Utils.getColorAttr(context, android.R.attr.colorError);
}
mGradient = context.getDrawable(gradientResourceId);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 8f63d45..2538bdd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -19,9 +19,10 @@
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
+import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_BUTTON;
import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_UNLOCK;
+import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_RIGHT_BUTTON;
import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_RIGHT_UNLOCK;
-import static com.android.systemui.tuner.LockscreenFragment.getIntentButton;
import android.app.ActivityManager;
import android.app.ActivityOptions;
@@ -79,9 +80,12 @@
import com.android.systemui.statusbar.KeyguardAffordanceView;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.policy.AccessibilityController;
+import com.android.systemui.statusbar.policy.ExtensionController;
+import com.android.systemui.statusbar.policy.ExtensionController.Extension;
import com.android.systemui.statusbar.policy.FlashlightController;
import com.android.systemui.statusbar.policy.PreviewInflater;
import com.android.systemui.tuner.LockscreenFragment;
+import com.android.systemui.tuner.LockscreenFragment.LockButtonFactory;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
@@ -91,8 +95,7 @@
*/
public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickListener,
UnlockMethodCache.OnUnlockMethodChangedListener,
- AccessibilityController.AccessibilityStateChangedCallback, View.OnLongClickListener,
- Tunable {
+ AccessibilityController.AccessibilityStateChangedCallback, View.OnLongClickListener {
final static String TAG = "StatusBar/KeyguardBottomAreaView";
@@ -159,12 +162,10 @@
private Drawable mLeftAssistIcon;
private IntentButton mRightButton = new DefaultRightButton();
- private IntentButton mRightDefault = mRightButton;
- private IntentButton mRightPlugin;
+ private Extension<IntentButton> mRightExtension;
private String mRightButtonStr;
private IntentButton mLeftButton = new DefaultLeftButton();
- private IntentButton mLeftDefault = mLeftButton;
- private IntentButton mLeftPlugin;
+ private Extension<IntentButton> mLeftExtension;
private String mLeftButtonStr;
private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
private boolean mDozing;
@@ -261,21 +262,28 @@
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mAccessibilityController.addStateChangedCallback(this);
- Dependency.get(PluginManager.class).addPluginListener(RIGHT_BUTTON_PLUGIN,
- mRightListener, IntentButtonProvider.class, false /* Only allow one */);
- Dependency.get(PluginManager.class).addPluginListener(LEFT_BUTTON_PLUGIN,
- mLeftListener, IntentButtonProvider.class, false /* Only allow one */);
- Dependency.get(TunerService.class).addTunable(this, LockscreenFragment.LOCKSCREEN_LEFT_BUTTON,
- LockscreenFragment.LOCKSCREEN_RIGHT_BUTTON);
+ mRightExtension = Dependency.get(ExtensionController.class).newExtension(IntentButton.class)
+ .withPlugin(IntentButtonProvider.class, RIGHT_BUTTON_PLUGIN,
+ p -> p.getIntentButton())
+ .withTunerFactory(new LockButtonFactory(mContext, LOCKSCREEN_RIGHT_BUTTON))
+ .withDefault(() -> new DefaultRightButton())
+ .withCallback(button -> setRightButton(button))
+ .build();
+ mLeftExtension = Dependency.get(ExtensionController.class).newExtension(IntentButton.class)
+ .withPlugin(IntentButtonProvider.class, LEFT_BUTTON_PLUGIN,
+ p -> p.getIntentButton())
+ .withTunerFactory(new LockButtonFactory(mContext, LOCKSCREEN_LEFT_BUTTON))
+ .withDefault(() -> new DefaultLeftButton())
+ .withCallback(button -> setLeftButton(button))
+ .build();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mAccessibilityController.removeStateChangedCallback(this);
- Dependency.get(PluginManager.class).removePluginListener(mRightListener);
- Dependency.get(PluginManager.class).removePluginListener(mLeftListener);
- Dependency.get(TunerService.class).removeTunable(this);
+ mRightExtension.destroy();
+ mLeftExtension.destroy();
}
private void initAccessibility() {
@@ -790,63 +798,21 @@
inflateCameraPreview();
}
- @Override
- public void onTuningChanged(String key, String newValue) {
- if (LockscreenFragment.LOCKSCREEN_LEFT_BUTTON.equals(key)) {
- mLeftButtonStr = newValue;
- mLeftIsVoiceAssist = TextUtils.isEmpty(mLeftButtonStr) && mLeftPlugin == null;
- mLeftButton = getIntentButton(mContext, mLeftButtonStr, mLeftPlugin, mLeftDefault);
- updateLeftAffordance();
- } else {
- mRightButtonStr = newValue;
- mRightButton = getIntentButton(mContext, mRightButtonStr, mRightPlugin, mRightDefault);
- updateRightAffordanceIcon();
- updateCameraVisibility();
- inflateCameraPreview();
- }
- }
-
private void setRightButton(IntentButton button) {
- mRightPlugin = button;
- mRightButton = getIntentButton(mContext, mRightButtonStr, mRightPlugin, mRightDefault);
+ mRightButton = button;
updateRightAffordanceIcon();
updateCameraVisibility();
inflateCameraPreview();
}
private void setLeftButton(IntentButton button) {
- mLeftPlugin = button;
- mLeftButton = getIntentButton(mContext, mLeftButtonStr, mLeftPlugin, mLeftDefault);
- mLeftIsVoiceAssist = false;
+ mLeftButton = button;
+ if (!(mLeftButton instanceof DefaultLeftButton)) {
+ mLeftIsVoiceAssist = false;
+ }
updateLeftAffordance();
}
- private final PluginListener<IntentButtonProvider> mRightListener =
- new PluginListener<IntentButtonProvider>() {
- @Override
- public void onPluginConnected(IntentButtonProvider plugin, Context pluginContext) {
- setRightButton(plugin.getIntentButton());
- }
-
- @Override
- public void onPluginDisconnected(IntentButtonProvider plugin) {
- setRightButton(null);
- }
- };
-
- private final PluginListener<IntentButtonProvider> mLeftListener =
- new PluginListener<IntentButtonProvider>() {
- @Override
- public void onPluginConnected(IntentButtonProvider plugin, Context pluginContext) {
- setLeftButton(plugin.getIntentButton());
- }
-
- @Override
- public void onPluginDisconnected(IntentButtonProvider plugin) {
- setLeftButton(null);
- }
- };
-
public void setDozing(boolean dozing, boolean animate) {
mDozing = dozing;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 213b0aa..a6b145e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -5742,9 +5742,8 @@
if (snoozeOption.criterion != null) {
mNotificationListener.snoozeNotification(sbn.getKey(), snoozeOption.criterion.getId());
} else {
- GregorianCalendar snoozeUntil = new GregorianCalendar();
- snoozeUntil.add(Calendar.MINUTE, snoozeOption.snoozeForMinutes);
- mNotificationListener.snoozeNotification(sbn.getKey(), snoozeUntil.getTimeInMillis());
+ mNotificationListener.snoozeNotification(sbn.getKey(),
+ snoozeOption.snoozeForMinutes * 60 * 1000);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionController.java
new file mode 100644
index 0000000..eaf8925
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionController.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2017 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.systemui.statusbar.policy;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.plugins.Plugin;
+
+import java.util.Map;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+/**
+ * Utility class used to select between a plugin, tuner settings, and a default implementation
+ * of an interface.
+ */
+public interface ExtensionController {
+
+ <T> ExtensionBuilder<T> newExtension(Class<T> cls);
+
+ interface Extension<T> {
+ T get();
+ void destroy();
+ }
+
+ interface ExtensionBuilder<T> {
+ ExtensionBuilder<T> withTunerFactory(TunerFactory<T> factory);
+ <P extends T> ExtensionBuilder<T> withPlugin(Class<P> cls);
+ <P extends T> ExtensionBuilder<T> withPlugin(Class<P> cls, String action);
+ <P> ExtensionBuilder<T> withPlugin(Class<P> cls, String action,
+ PluginConverter<T, P> converter);
+ ExtensionBuilder<T> withDefault(Supplier<T> def);
+ ExtensionBuilder<T> withCallback(Consumer<T> callback);
+ Extension build();
+ }
+
+ public interface PluginConverter<T, P> {
+ T getInterfaceFromPlugin(P plugin);
+ }
+
+ public interface TunerFactory<T> {
+ String[] keys();
+ T create(Map<String, String> settings);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java
new file mode 100644
index 0000000..fefbaa3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2017 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.systemui.statusbar.policy;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.plugins.Plugin;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.tuner.TunerService.Tunable;
+
+import android.content.Context;
+import android.util.ArrayMap;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+public class ExtensionControllerImpl implements ExtensionController {
+
+ @Override
+ public <T> ExtensionBuilder<T> newExtension(Class<T> cls) {
+ return new ExtensionBuilder<>();
+ }
+
+ private interface Producer<T> {
+ T get();
+ void destroy();
+ }
+
+ private class ExtensionBuilder<T> implements ExtensionController.ExtensionBuilder<T> {
+
+ private ExtensionImpl<T> mExtension = new ExtensionImpl<>();
+
+ @Override
+ public ExtensionController.ExtensionBuilder<T> withTunerFactory(TunerFactory<T> factory) {
+ mExtension.addTunerFactory(factory, factory.keys());
+ return this;
+ }
+
+ @Override
+ public <P extends T> ExtensionController.ExtensionBuilder<T> withPlugin(Class<P> cls) {
+ return withPlugin(cls, PluginManager.getAction(cls));
+ }
+
+ @Override
+ public <P extends T> ExtensionController.ExtensionBuilder<T> withPlugin(Class<P> cls,
+ String action) {
+ return withPlugin(cls, action, null);
+ }
+
+ @Override
+ public <P> ExtensionController.ExtensionBuilder<T> withPlugin(Class<P> cls,
+ String action, PluginConverter<T, P> converter) {
+ mExtension.addPlugin(action, cls, converter);
+ return this;
+ }
+
+ @Override
+ public ExtensionController.ExtensionBuilder<T> withDefault(Supplier<T> def) {
+ mExtension.addDefault(def);
+ return this;
+ }
+
+ @Override
+ public ExtensionController.ExtensionBuilder<T> withCallback(
+ Consumer<T> callback) {
+ mExtension.mCallbacks.add(callback);
+ return this;
+ }
+
+ @Override
+ public ExtensionController.Extension build() {
+ // Manually sort, plugins first, tuners second, defaults last.
+ Collections.sort(mExtension.mProducers, (o1, o2) -> {
+ if (o1 instanceof ExtensionImpl.PluginItem) {
+ if (o2 instanceof ExtensionImpl.PluginItem) {
+ return 0;
+ } else {
+ return -1;
+ }
+ }
+ if (o1 instanceof ExtensionImpl.TunerItem) {
+ if (o2 instanceof ExtensionImpl.PluginItem) {
+ return 1;
+ } else if (o2 instanceof ExtensionImpl.TunerItem) {
+ return 0;
+ } else {
+ return -1;
+ }
+ }
+ return 0;
+ });
+ mExtension.notifyChanged();
+ return mExtension;
+ }
+ }
+
+ private class ExtensionImpl<T> implements ExtensionController.Extension<T> {
+ private final ArrayList<Producer<T>> mProducers = new ArrayList<>();
+ private final ArrayList<Consumer<T>> mCallbacks = new ArrayList<>();
+ private T mItem;
+
+ @Override
+ public T get() {
+ return mItem;
+ }
+
+ @Override
+ public void destroy() {
+ for (int i = 0; i < mProducers.size(); i++) {
+ mProducers.get(i).destroy();
+ }
+ }
+
+ private void notifyChanged() {
+ for (int i = 0; i < mProducers.size(); i++) {
+ final T item = mProducers.get(i).get();
+ if (item != null) {
+ mItem = item;
+ break;
+ }
+ }
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).accept(mItem);
+ }
+ }
+
+ public void addDefault(Supplier<T> def) {
+ mProducers.add(new Default(def));
+ }
+
+ public <P> void addPlugin(String action, Class<P> cls, PluginConverter<T, P> converter) {
+ mProducers.add(new PluginItem(action, cls, converter));
+ }
+
+ public void addTunerFactory(TunerFactory<T> factory, String[] keys) {
+ mProducers.add(new TunerItem(factory, factory.keys()));
+ }
+
+ private class PluginItem<P extends Plugin> implements Producer<T>, PluginListener<P> {
+ private final PluginConverter<T, P> mConverter;
+ private T mItem;
+
+ public PluginItem(String action, Class<P> cls, PluginConverter<T, P> converter) {
+ mConverter = converter;
+ Dependency.get(PluginManager.class).addPluginListener(action, this, cls);
+ }
+
+ @Override
+ public void onPluginConnected(P plugin, Context pluginContext) {
+ if (mConverter != null) {
+ mItem = mConverter.getInterfaceFromPlugin(plugin);
+ } else {
+ mItem = (T) plugin;
+ }
+ notifyChanged();
+ }
+
+ @Override
+ public void onPluginDisconnected(P plugin) {
+ mItem = null;
+ notifyChanged();
+ }
+
+ @Override
+ public T get() {
+ return mItem;
+ }
+
+ @Override
+ public void destroy() {
+ Dependency.get(PluginManager.class).removePluginListener(this);
+ }
+ }
+
+ private class TunerItem<T> implements Producer<T>, Tunable {
+ private final TunerFactory<T> mFactory;
+ private final ArrayMap<String, String> mSettings = new ArrayMap<>();
+ private T mItem;
+
+ public TunerItem(TunerFactory<T> factory, String... setting) {
+ mFactory = factory;
+ Dependency.get(TunerService.class).addTunable(this, setting);
+ }
+
+ @Override
+ public T get() {
+ return mItem;
+ }
+
+ @Override
+ public void destroy() {
+ Dependency.get(TunerService.class).removeTunable(this);
+ }
+
+ @Override
+ public void onTuningChanged(String key, String newValue) {
+ mSettings.put(key, newValue);
+ mItem = mFactory.create(mSettings);
+ notifyChanged();
+ }
+ }
+
+ private class Default<T> implements Producer<T> {
+ private final Supplier<T> mSupplier;
+
+ public Default(Supplier<T> supplier) {
+ mSupplier = supplier;
+ }
+
+ @Override
+ public T get() {
+ return mSupplier.get();
+ }
+
+ @Override
+ public void destroy() {
+
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java
index 410d3d2..2df1793 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java
@@ -52,11 +52,13 @@
import com.android.systemui.plugins.IntentButtonProvider.IntentButton;
import com.android.systemui.statusbar.ScalingDrawableWrapper;
import com.android.systemui.statusbar.phone.ExpandableIndicator;
+import com.android.systemui.statusbar.policy.ExtensionController.TunerFactory;
import com.android.systemui.tuner.ShortcutParser.Shortcut;
import com.android.systemui.tuner.TunerService.Tunable;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
import java.util.function.Consumer;
public class LockscreenFragment extends PreferenceFragment {
@@ -313,26 +315,39 @@
}
}
- public static IntentButton getIntentButton(Context context, String buttonStr,
- IntentButton plugin, IntentButton def) {
- // Plugin wins.
- if (plugin != null) return plugin;
- // Then tuner options.
- if (!TextUtils.isEmpty(buttonStr)) {
- if (buttonStr.contains("::")) {
- Shortcut shortcut = getShortcutInfo(context, buttonStr);
- if (shortcut != null) {
- return new ShortcutButton(context, shortcut);
- }
- } else if (buttonStr.contains("/")) {
- ActivityInfo info = getActivityinfo(context, buttonStr);
- if (info != null) {
- return new ActivityButton(context, info);
+ public static class LockButtonFactory implements TunerFactory<IntentButton> {
+
+ private final String mKey;
+ private final Context mContext;
+
+ public LockButtonFactory(Context context, String key) {
+ mContext = context;
+ mKey = key;
+ }
+
+ @Override
+ public String[] keys() {
+ return new String[]{mKey};
+ }
+
+ @Override
+ public IntentButton create(Map<String, String> settings) {
+ String buttonStr = settings.get(mKey);
+ if (!TextUtils.isEmpty(buttonStr)) {
+ if (buttonStr.contains("::")) {
+ Shortcut shortcut = getShortcutInfo(mContext, buttonStr);
+ if (shortcut != null) {
+ return new ShortcutButton(mContext, shortcut);
+ }
+ } else if (buttonStr.contains("/")) {
+ ActivityInfo info = getActivityinfo(mContext, buttonStr);
+ if (info != null) {
+ return new ActivityButton(mContext, info);
+ }
}
}
+ return null;
}
- // Then default.
- return def;
}
private static class ShortcutButton implements IntentButton {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
index 6c454e1..c0e7e80 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
@@ -23,7 +23,6 @@
import android.os.MessageQueue;
import android.support.test.InstrumentationRegistry;
import android.util.ArrayMap;
-import android.util.Log;
import com.android.systemui.Dependency.DependencyKey;
import com.android.systemui.utils.TestableContext;
@@ -32,8 +31,6 @@
import org.junit.After;
import org.junit.Before;
-import java.lang.Thread.UncaughtExceptionHandler;
-
/**
* Base class that does System UI specific setup.
*/
@@ -92,8 +89,10 @@
return null;
}
- public <T> void injectMockDependency(Class<T> cls) {
- injectTestDependency(cls, mock(cls));
+ public <T> T injectMockDependency(Class<T> cls) {
+ final T mock = mock(cls);
+ mDependency.injectTestDependency(cls, mock);
+ return mock;
}
public <T> void injectTestDependency(Class<T> cls, T obj) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerTest.java
new file mode 100644
index 0000000..e3a5ef0
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerTest.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2017 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.systemui.statusbar.policy;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.OverlayPlugin;
+import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.statusbar.policy.ExtensionController.Extension;
+import com.android.systemui.statusbar.policy.ExtensionController.TunerFactory;
+import com.android.systemui.tuner.TunerService;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Map;
+import java.util.function.Consumer;
+
+public class ExtensionControllerTest extends SysuiTestCase {
+
+ private PluginManager mPluginManager;
+ private TunerService mTunerService;
+ private ExtensionController mExtensionController;
+
+ @Before
+ public void setup() {
+ mPluginManager = injectMockDependency(PluginManager.class);
+ mTunerService = injectMockDependency(TunerService.class);
+ mExtensionController = Dependency.get(ExtensionController.class);
+ }
+
+ @Test
+ public void testPlugin() {
+ Extension ext = mExtensionController.newExtension(OverlayPlugin.class)
+ .withPlugin(OverlayPlugin.class)
+ .build();
+ verify(mPluginManager).addPluginListener(eq(OverlayPlugin.ACTION), any(),
+ eq(OverlayPlugin.class));
+
+ ext.destroy();
+ verify(mPluginManager).removePluginListener(any());
+ }
+
+ @Test
+ public void testTuner() {
+ String[] keys = new String[] { "key1", "key2" };
+ TunerFactory<Object> factory = new ExtensionController.TunerFactory() {
+ @Override
+ public String[] keys() {
+ return keys;
+ }
+
+ @Override
+ public Object create(Map settings) {
+ return null;
+ }
+ };
+ Extension ext = mExtensionController.newExtension(Object.class)
+ .withTunerFactory(factory)
+ .build();
+ verify(mTunerService).addTunable(any(), eq(keys[0]), eq(keys[1]));
+
+ ext.destroy();
+ verify(mTunerService).removeTunable(any());
+ }
+
+ @Test
+ public void testDefault() {
+ Object o = new Object();
+ Extension ext = mExtensionController.newExtension(Object.class)
+ .withDefault(() -> o)
+ .build();
+ assertEquals(o, ext.get());
+ }
+
+ @Test
+ public void testCallback() {
+ Consumer<Object> callback = mock(Consumer.class);
+ final Object o = new Object();
+ mExtensionController.newExtension(Object.class)
+ .withDefault(() -> o)
+ .withCallback(callback)
+ .build();
+ verify(callback).accept(eq(o));
+ }
+
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeExtensionController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeExtensionController.java
new file mode 100644
index 0000000..c0f5783
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeExtensionController.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2017 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.systemui.utils.leaks;
+
+import static org.mockito.Mockito.mock;
+
+import com.android.systemui.statusbar.policy.ExtensionController;
+
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+public class FakeExtensionController implements ExtensionController {
+
+ private final Tracker mTracker;
+
+ public FakeExtensionController(LeakCheckedTest test) {
+ mTracker = test.getTracker("extension");
+ }
+
+ @Override
+ public <T> ExtensionBuilder<T> newExtension(Class<T> cls) {
+ final Object o = new Object();
+ mTracker.getLeakInfo(o).addAllocation(new Throwable());
+ return new FakeExtensionBuilder(o);
+ }
+
+ private class FakeExtensionBuilder<T> implements ExtensionBuilder<T> {
+ private final Object mAllocation;
+
+ public FakeExtensionBuilder(Object o) {
+ mAllocation = o;
+ }
+
+ @Override
+ public ExtensionBuilder<T> withTunerFactory(TunerFactory<T> factory) {
+ return this;
+ }
+
+ @Override
+ public <P extends T> ExtensionBuilder<T> withPlugin(Class<P> cls) {
+ return this;
+ }
+
+ @Override
+ public <P extends T> ExtensionBuilder<T> withPlugin(Class<P> cls, String action) {
+ return this;
+ }
+
+ @Override
+ public <P> ExtensionBuilder<T> withPlugin(Class<P> cls, String action, PluginConverter<T, P> converter) {
+ return this;
+ }
+
+ @Override
+ public ExtensionBuilder<T> withDefault(Supplier<T> def) {
+ return this;
+ }
+
+ @Override
+ public ExtensionBuilder<T> withCallback(Consumer<T> callback) {
+ return this;
+ }
+
+ @Override
+ public Extension build() {
+ return new FakeExtension(mAllocation);
+ }
+ }
+
+ private class FakeExtension<T> implements Extension<T> {
+ private final Object mAllocation;
+
+ public FakeExtension(Object allocation) {
+ mAllocation = allocation;
+ }
+
+ @Override
+ public T get() {
+ // TODO: Support defaults or things.
+ return null;
+ }
+
+ @Override
+ public void destroy() {
+ mTracker.getLeakInfo(mAllocation).clearAllocations();
+ }
+ }
+}
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 4d2b106..c50623e 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -709,7 +709,7 @@
}
private boolean isUserRunningAndUnlocked(@UserIdInt int userId) {
- return mUserManager.isUserRunning(userId) && StorageManager.isUserKeyUnlocked(userId);
+ return mUserManager.isUserUnlockingOrUnlocked(userId);
}
@Override
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index ef7780c..979096e 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -19,6 +19,7 @@
import android.app.ActivityManager;
import android.annotation.NonNull;
import android.content.pm.PackageManagerInternal;
+import android.util.ArrayMap;
import android.util.ArraySet;
import com.android.internal.content.PackageMonitor;
import com.android.internal.location.ProviderProperties;
@@ -104,6 +105,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Set;
@@ -225,6 +227,12 @@
private final ArraySet<String> mBackgroundThrottlePackageWhitelist = new ArraySet<>();
+ private final ArrayMap<IGnssMeasurementsListener, Identity> mGnssMeasurementsListeners =
+ new ArrayMap<>();
+
+ private final ArrayMap<IGnssNavigationMessageListener, Identity>
+ mGnssNavigationMessageListeners = new ArrayMap<>();
+
// current active user on the device - other users are denied location data
private int mCurrentUserId = UserHandle.USER_SYSTEM;
private int[] mCurrentUserProfiles = new int[] { UserHandle.USER_SYSTEM };
@@ -315,17 +323,17 @@
boolean foreground = isImportanceForeground(importance);
HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size());
synchronized (mLock) {
- for (Map.Entry<String, ArrayList<UpdateRecord>> entry
+ for (Entry<String, ArrayList<UpdateRecord>> entry
: mRecordsByProvider.entrySet()) {
String provider = entry.getKey();
for (UpdateRecord record : entry.getValue()) {
- if (record.mReceiver.mUid == uid
+ if (record.mReceiver.mIdentity.mUid == uid
&& record.mIsForegroundUid != foreground) {
if (D) Log.d(TAG, "request from uid " + uid + " is now "
+ (foreground ? "foreground" : "background)"));
record.mIsForegroundUid = foreground;
- if (!isThrottlingExemptLocked(record.mReceiver)) {
+ if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
affectedProviders.add(provider);
}
}
@@ -334,6 +342,33 @@
for (String provider : affectedProviders) {
applyRequirementsLocked(provider);
}
+
+ for (Entry<IGnssMeasurementsListener, Identity> entry
+ : mGnssMeasurementsListeners.entrySet()) {
+ if (entry.getValue().mUid == uid) {
+ if (D) Log.d(TAG, "gnss measurements listener from uid " + uid
+ + " is now " + (foreground ? "foreground" : "background)"));
+ if (foreground || isThrottlingExemptLocked(entry.getValue())) {
+ mGnssMeasurementsProvider.addListener(entry.getKey());
+ } else {
+ mGnssMeasurementsProvider.removeListener(entry.getKey());
+ }
+ }
+ }
+
+ for (Entry<IGnssNavigationMessageListener, Identity> entry
+ : mGnssNavigationMessageListeners.entrySet()) {
+ if (entry.getValue().mUid == uid) {
+ if (D) Log.d(TAG, "gnss navigation message listener from uid "
+ + uid + " is now "
+ + (foreground ? "foreground" : "background)"));
+ if (foreground || isThrottlingExemptLocked(entry.getValue())) {
+ mGnssNavigationMessageProvider.addListener(entry.getKey());
+ } else {
+ mGnssNavigationMessageProvider.removeListener(entry.getKey());
+ }
+ }
+ }
}
}
@@ -344,7 +379,7 @@
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
updateUserProfiles(mCurrentUserId);
- updateThrottlingWhitelistLocked();
+ updateBackgroundThrottlingWhitelistLocked();
// prepare providers
loadProvidersLocked();
@@ -381,7 +416,7 @@
@Override
public void onChange(boolean selfChange) {
synchronized (mLock) {
- updateThrottlingWhitelistLocked();
+ updateBackgroundThrottlingWhitelistLocked();
updateProvidersLocked();
}
}
@@ -721,14 +756,24 @@
}
}
+ private static final class Identity {
+ final int mUid;
+ final int mPid;
+ final String mPackageName;
+
+ Identity(int uid, int pid, String packageName) {
+ mUid = uid;
+ mPid = pid;
+ mPackageName = packageName;
+ }
+ }
+
/**
* A wrapper class holding either an ILocationListener or a PendingIntent to receive
* location updates.
*/
private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
- final int mUid; // uid of receiver
- final int mPid; // pid of receiver
- final String mPackageName; // package name of receiver
+ final Identity mIdentity;
final int mAllowedResolutionLevel; // resolution level allowed to receiver
final ILocationListener mListener;
@@ -756,9 +801,7 @@
mKey = intent;
}
mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
- mUid = uid;
- mPid = pid;
- mPackageName = packageName;
+ mIdentity = new Identity(uid, pid, packageName);
if (workSource != null && workSource.size() <= 0) {
workSource = null;
}
@@ -770,7 +813,7 @@
// construct/configure wakelock
mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
if (workSource == null) {
- workSource = new WorkSource(mUid, mPackageName);
+ workSource = new WorkSource(mIdentity.mUid, mIdentity.mPackageName);
}
mWakeLock.setWorkSource(workSource);
}
@@ -865,13 +908,14 @@
int op) {
if (!currentlyMonitoring) {
if (allowMonitoring) {
- return mAppOps.startOpNoThrow(op, mUid, mPackageName)
+ return mAppOps.startOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
== AppOpsManager.MODE_ALLOWED;
}
} else {
- if (!allowMonitoring || mAppOps.checkOpNoThrow(op, mUid, mPackageName)
+ if (!allowMonitoring
+ || mAppOps.checkOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
!= AppOpsManager.MODE_ALLOWED) {
- mAppOps.finishOp(op, mUid, mPackageName);
+ mAppOps.finishOp(op, mIdentity.mUid, mIdentity.mPackageName);
return false;
}
}
@@ -1628,7 +1672,7 @@
ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
if (records != null) {
for (UpdateRecord record : records) {
- if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mUid))) {
+ if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
// Sends a notification message to the receiver
if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
if (deadReceivers == null) {
@@ -1673,16 +1717,16 @@
if (records != null) {
for (UpdateRecord record : records) {
- if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mUid))) {
+ if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
if (checkLocationAccess(
- record.mReceiver.mPid,
- record.mReceiver.mUid,
- record.mReceiver.mPackageName,
+ record.mReceiver.mIdentity.mPid,
+ record.mReceiver.mIdentity.mUid,
+ record.mReceiver.mIdentity.mPackageName,
record.mReceiver.mAllowedResolutionLevel)) {
LocationRequest locationRequest = record.mRequest;
long interval = locationRequest.getInterval();
- if (!isThrottlingExemptLocked(record.mReceiver)) {
+ if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
if (!record.mIsForegroundUid) {
interval = Math.max(interval, backgroundThrottleInterval);
}
@@ -1709,7 +1753,7 @@
// under that threshold.
long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
for (UpdateRecord record : records) {
- if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mUid))) {
+ if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
LocationRequest locationRequest = record.mRequest;
// Don't assign battery blame for update records whose
@@ -1728,8 +1772,8 @@
} else {
// Assign blame to caller.
worksource.add(
- record.mReceiver.mUid,
- record.mReceiver.mPackageName);
+ record.mReceiver.mIdentity.mUid,
+ record.mReceiver.mIdentity.mPackageName);
}
}
}
@@ -1741,7 +1785,15 @@
p.setRequest(providerRequest, worksource);
}
- private void updateThrottlingWhitelistLocked() {
+ @Override
+ public String[] getBackgroundThrottlingWhitelist() {
+ synchronized (mLock) {
+ return mBackgroundThrottlePackageWhitelist.toArray(
+ new String[mBackgroundThrottlePackageWhitelist.size()]);
+ }
+ }
+
+ private void updateBackgroundThrottlingWhitelistLocked() {
String setting = Settings.Global.getString(
mContext.getContentResolver(),
Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST);
@@ -1756,17 +1808,17 @@
Arrays.asList(setting.split(",")));
}
- private boolean isThrottlingExemptLocked(Receiver receiver) {
- if (receiver.mUid == Process.SYSTEM_UID) {
+ private boolean isThrottlingExemptLocked(Identity identity) {
+ if (identity.mUid == Process.SYSTEM_UID) {
return true;
}
- if (mBackgroundThrottlePackageWhitelist.contains(receiver.mPackageName)) {
+ if (mBackgroundThrottlePackageWhitelist.contains(identity.mPackageName)) {
return true;
}
for (LocationProviderProxy provider : mProxyProviders) {
- if (receiver.mPackageName.equals(provider.getConnectedPackageName())) {
+ if (identity.mPackageName.equals(provider.getConnectedPackageName())) {
return true;
}
}
@@ -1790,7 +1842,7 @@
mRequest = request;
mReceiver = receiver;
mIsForegroundUid = isImportanceForeground(
- mActivityManager.getPackageImportance(mReceiver.mPackageName));
+ mActivityManager.getPackageImportance(mReceiver.mIdentity.mPackageName));
ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
if (records == null) {
@@ -1803,14 +1855,14 @@
// Update statistics for historical location requests by package/provider
mRequestStatistics.startRequesting(
- mReceiver.mPackageName, provider, request.getInterval());
+ mReceiver.mIdentity.mPackageName, provider, request.getInterval());
}
/**
* Method to be called when a record will no longer be used.
*/
void disposeLocked(boolean removeReceiver) {
- mRequestStatistics.stopRequesting(mReceiver.mPackageName, mProvider);
+ mRequestStatistics.stopRequesting(mReceiver.mIdentity.mPackageName, mProvider);
// remove from mRecordsByProvider
ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
@@ -1834,8 +1886,8 @@
@Override
public String toString() {
- return "UpdateRecord[" + mProvider + " " + mReceiver.mPackageName
- + "(" + mReceiver.mUid + (mIsForegroundUid ? " foreground" : " background")
+ return "UpdateRecord[" + mProvider + " " + mReceiver.mIdentity.mPackageName
+ + "(" + mReceiver.mIdentity.mUid + (mIsForegroundUid ? " foreground" : " background")
+ ")" + " " + mRequest + "]";
}
}
@@ -1994,7 +2046,8 @@
if (D) Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
+ " " + name + " " + request + " from " + packageName + "(" + uid + " "
+ (record.mIsForegroundUid ? "foreground" : "background")
- + (isThrottlingExemptLocked(receiver) ? " [whitelisted]" : "") + ")");
+ + (isThrottlingExemptLocked(receiver.mIdentity)
+ ? " [whitelisted]" : "") + ")");
UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
if (oldRecord != null) {
@@ -2227,13 +2280,33 @@
if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) {
return false;
}
- return mGnssMeasurementsProvider.addListener(listener);
+
+ synchronized (mLock) {
+ Identity callerIdentity
+ = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
+ mGnssMeasurementsListeners.put(listener, callerIdentity);
+ long identity = Binder.clearCallingIdentity();
+ try {
+ if (isThrottlingExemptLocked(callerIdentity)
+ || isImportanceForeground(
+ mActivityManager.getPackageImportance(packageName))) {
+ return mGnssMeasurementsProvider.addListener(listener);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+
+ return true;
+ }
}
@Override
public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
if (mGnssMeasurementsProvider != null) {
- mGnssMeasurementsProvider.removeListener(listener);
+ synchronized (mLock) {
+ mGnssMeasurementsListeners.remove(listener);
+ mGnssMeasurementsProvider.removeListener(listener);
+ }
}
}
@@ -2244,13 +2317,33 @@
if (!hasGnssPermissions(packageName) || mGnssNavigationMessageProvider == null) {
return false;
}
- return mGnssNavigationMessageProvider.addListener(listener);
+
+ synchronized (mLock) {
+ Identity callerIdentity
+ = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
+ mGnssNavigationMessageListeners.put(listener, callerIdentity);
+ long identity = Binder.clearCallingIdentity();
+ try {
+ if (isThrottlingExemptLocked(callerIdentity)
+ || isImportanceForeground(
+ mActivityManager.getPackageImportance(packageName))) {
+ return mGnssNavigationMessageProvider.addListener(listener);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+
+ return true;
+ }
}
@Override
public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
if (mGnssNavigationMessageProvider != null) {
- mGnssNavigationMessageProvider.removeListener(listener);
+ synchronized (mLock) {
+ mGnssNavigationMessageListeners.remove(listener);
+ mGnssNavigationMessageProvider.removeListener(listener);
+ }
}
}
@@ -2529,26 +2622,30 @@
Receiver receiver = r.mReceiver;
boolean receiverDead = false;
- int receiverUserId = UserHandle.getUserId(receiver.mUid);
- if (!isCurrentProfile(receiverUserId) && !isUidALocationProvider(receiver.mUid)) {
+ int receiverUserId = UserHandle.getUserId(receiver.mIdentity.mUid);
+ if (!isCurrentProfile(receiverUserId)
+ && !isUidALocationProvider(receiver.mIdentity.mUid)) {
if (D) {
Log.d(TAG, "skipping loc update for background user " + receiverUserId +
" (current user: " + mCurrentUserId + ", app: " +
- receiver.mPackageName + ")");
+ receiver.mIdentity.mPackageName + ")");
}
continue;
}
- if (mBlacklist.isBlacklisted(receiver.mPackageName)) {
+ if (mBlacklist.isBlacklisted(receiver.mIdentity.mPackageName)) {
if (D) Log.d(TAG, "skipping loc update for blacklisted app: " +
- receiver.mPackageName);
+ receiver.mIdentity.mPackageName);
continue;
}
- if (!reportLocationAccessNoThrow(receiver.mPid, receiver.mUid, receiver.mPackageName,
+ if (!reportLocationAccessNoThrow(
+ receiver.mIdentity.mPid,
+ receiver.mIdentity.mUid,
+ receiver.mIdentity.mPackageName,
receiver.mAllowedResolutionLevel)) {
if (D) Log.d(TAG, "skipping loc update for no op app: " +
- receiver.mPackageName);
+ receiver.mIdentity.mPackageName);
continue;
}
@@ -2671,7 +2768,7 @@
ArrayList<Receiver> deadReceivers = null;
for (Receiver receiver : mReceivers.values()) {
- if (receiver.mPackageName.equals(packageName)) {
+ if (receiver.mIdentity.mPackageName.equals(packageName)) {
if (deadReceivers == null) {
deadReceivers = new ArrayList<>();
}
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index b33538cb..d54ebaa 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -35,8 +35,7 @@
import android.net.INetworkScoreService;
import android.net.NetworkKey;
import android.net.NetworkScoreManager;
-import android.net.NetworkScorerAppManager;
-import android.net.NetworkScorerAppManager.NetworkScorerAppData;
+import android.net.NetworkScorerAppData;
import android.net.RecommendationRequest;
import android.net.RecommendationResult;
import android.net.ScoredNetwork;
@@ -132,10 +131,10 @@
* manages the service connection.
*/
private class NetworkScorerPackageMonitor extends PackageMonitor {
- final List<String> mPackagesToWatch;
+ final String mPackageToWatch;
- private NetworkScorerPackageMonitor(List<String> packagesToWatch) {
- mPackagesToWatch = packagesToWatch;
+ private NetworkScorerPackageMonitor(String packageToWatch) {
+ mPackageToWatch = packageToWatch;
}
@Override
@@ -168,37 +167,27 @@
evaluateBinding(packageName, true /* forceUnbind */);
}
- private void evaluateBinding(String scorerPackageName, boolean forceUnbind) {
- if (!mPackagesToWatch.contains(scorerPackageName)) {
+ private void evaluateBinding(String changedPackageName, boolean forceUnbind) {
+ if (!mPackageToWatch.equals(changedPackageName)) {
// Early exit when we don't care about the package that has changed.
return;
}
if (DBG) {
- Log.d(TAG, "Evaluating binding for: " + scorerPackageName
+ Log.d(TAG, "Evaluating binding for: " + changedPackageName
+ ", forceUnbind=" + forceUnbind);
}
+
final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
if (activeScorer == null) {
// Package change has invalidated a scorer, this will also unbind any service
// connection.
if (DBG) Log.d(TAG, "No active scorers available.");
- unbindFromScoringServiceIfNeeded();
- } else if (activeScorer.getRecommendationServicePackageName().equals(scorerPackageName))
- {
- // The active scoring service changed in some way.
- if (DBG) {
- Log.d(TAG, "Possible change to the active scorer: "
- + activeScorer.getRecommendationServicePackageName());
- }
+ refreshBinding();
+ } else { // The scoring service changed in some way.
if (forceUnbind) {
unbindFromScoringServiceIfNeeded();
}
- bindToScoringServiceIfNeeded(activeScorer);
- } else {
- // One of the scoring apps on the device has changed and we may no longer be
- // bound to the correct scoring app. The logic in bindToScoringServiceIfNeeded()
- // will sort that out to leave us bound to the most recent active scorer.
if (DBG) {
Log.d(TAG, "Binding to " + activeScorer.getRecommendationServiceComponent()
+ " if needed.");
@@ -272,60 +261,71 @@
/** Called when the system is ready to run third-party code but before it actually does so. */
void systemReady() {
if (DBG) Log.d(TAG, "systemReady");
- registerPackageMonitorIfNeeded();
registerRecommendationSettingsObserver();
- refreshRecommendationRequestTimeoutMs();
}
/** Called when the system is ready for us to start third-party code. */
void systemRunning() {
if (DBG) Log.d(TAG, "systemRunning");
- bindToScoringServiceIfNeeded();
}
- private void onUserUnlocked(int userId) {
+ @VisibleForTesting
+ void onUserUnlocked(int userId) {
+ if (DBG) Log.d(TAG, "onUserUnlocked(" + userId + ")");
+ refreshBinding();
+ }
+
+ private void refreshBinding() {
+ if (DBG) Log.d(TAG, "refreshBinding()");
+ // Apply the default package name if the Setting isn't set.
+ mNetworkScorerAppManager.revertToDefaultIfNoActive();
registerPackageMonitorIfNeeded();
bindToScoringServiceIfNeeded();
}
private void registerRecommendationSettingsObserver() {
- final List<String> providerPackages =
- mNetworkScorerAppManager.getPotentialRecommendationProviderPackages();
- if (!providerPackages.isEmpty()) {
- final Uri enabledUri = Global.getUriFor(Global.NETWORK_RECOMMENDATIONS_ENABLED);
- mContentObserver.observe(enabledUri,
- ServiceHandler.MSG_RECOMMENDATIONS_ENABLED_CHANGED);
- }
+ final Uri packageNameUri = Global.getUriFor(Global.NETWORK_RECOMMENDATIONS_PACKAGE);
+ mContentObserver.observe(packageNameUri,
+ ServiceHandler.MSG_RECOMMENDATIONS_PACKAGE_CHANGED);
final Uri timeoutUri = Global.getUriFor(Global.NETWORK_RECOMMENDATION_REQUEST_TIMEOUT_MS);
mContentObserver.observe(timeoutUri,
ServiceHandler.MSG_RECOMMENDATION_REQUEST_TIMEOUT_CHANGED);
}
+ /**
+ * Ensures the package manager is registered to monitor the current active scorer.
+ * If a discrepancy is found any previous monitor will be cleaned up
+ * and a new monitor will be created.
+ *
+ * This method is idempotent.
+ */
private void registerPackageMonitorIfNeeded() {
- if (DBG) Log.d(TAG, "registerPackageMonitorIfNeeded");
- final List<String> providerPackages =
- mNetworkScorerAppManager.getPotentialRecommendationProviderPackages();
+ if (DBG) Log.d(TAG, "registerPackageMonitorIfNeeded()");
+ final NetworkScorerAppData appData = mNetworkScorerAppManager.getActiveScorer();
synchronized (mPackageMonitorLock) {
// Unregister the current monitor if needed.
- if (mPackageMonitor != null) {
+ if (mPackageMonitor != null && (appData == null
+ || !appData.getRecommendationServicePackageName().equals(
+ mPackageMonitor.mPackageToWatch))) {
if (DBG) {
Log.d(TAG, "Unregistering package monitor for "
- + mPackageMonitor.mPackagesToWatch);
+ + mPackageMonitor.mPackageToWatch);
}
mPackageMonitor.unregister();
mPackageMonitor = null;
}
- // Create and register the monitor if there are packages that could be providers.
- if (!providerPackages.isEmpty()) {
- mPackageMonitor = new NetworkScorerPackageMonitor(providerPackages);
+ // Create and register the monitor if a scorer is active.
+ if (appData != null && mPackageMonitor == null) {
+ mPackageMonitor = new NetworkScorerPackageMonitor(
+ appData.getRecommendationServicePackageName());
// TODO: Need to update when we support per-user scorers. http://b/23422763
mPackageMonitor.register(mContext, null /* thread */, UserHandle.SYSTEM,
false /* externalStorage */);
if (DBG) {
Log.d(TAG, "Registered package monitor for "
- + mPackageMonitor.mPackagesToWatch);
+ + mPackageMonitor.mPackageToWatch);
}
}
}
@@ -337,6 +337,13 @@
bindToScoringServiceIfNeeded(scorerData);
}
+ /**
+ * Ensures the service connection is bound to the current active scorer.
+ * If a discrepancy is found any previous connection will be cleaned up
+ * and a new connection will be created.
+ *
+ * This method is idempotent.
+ */
private void bindToScoringServiceIfNeeded(NetworkScorerAppData appData) {
if (DBG) Log.d(TAG, "bindToScoringServiceIfNeeded(" + appData + ")");
if (appData != null) {
@@ -365,6 +372,8 @@
synchronized (mServiceConnectionLock) {
if (mServiceConnection != null) {
mServiceConnection.disconnect(mContext);
+ if (DBG) Log.d(TAG, "Disconnected from: "
+ + mServiceConnection.mAppData.getRecommendationServiceComponent());
}
mServiceConnection = null;
}
@@ -653,17 +662,13 @@
@Override
public boolean setActiveScorer(String packageName) {
- // TODO: For now, since SCORE_NETWORKS requires an app to be privileged, we allow such apps
- // to directly set the scorer app rather than having to use the consent dialog. The
- // assumption is that anyone bundling a scorer app with the system is trusted by the OEM to
- // do the right thing and not enable this feature without explaining it to the user.
- // In the future, should this API be opened to 3p apps, we will need to lock this down and
- // figure out another way to streamline the UX.
-
- mContext.enforceCallingOrSelfPermission(permission.SCORE_NETWORKS, TAG);
-
- // Scorers (recommendation providers) are selected and no longer set.
- return false;
+ // Only the system can set the active scorer
+ if (isCallerSystemProcess(getCallingUid()) || callerCanRequestScores()) {
+ return mNetworkScorerAppManager.setActiveScorer(packageName);
+ } else {
+ throw new SecurityException(
+ "Caller is neither the system process nor a score requester.");
+ }
}
/**
@@ -700,7 +705,6 @@
return null;
}
-
/**
* Returns metadata about the active scorer or <code>null</code> if there is no active scorer.
*/
@@ -727,7 +731,13 @@
*/
@Override
public List<NetworkScorerAppData> getAllValidScorers() {
- return mNetworkScorerAppManager.getAllValidScorers();
+ // Only the system can access this data.
+ if (isCallerSystemProcess(getCallingUid()) || callerCanRequestScores()) {
+ return mNetworkScorerAppManager.getAllValidScorers();
+ } else {
+ throw new SecurityException(
+ "Caller is neither the system process nor a score requester.");
+ }
}
@Override
@@ -1159,7 +1169,7 @@
@VisibleForTesting
public final class ServiceHandler extends Handler {
public static final int MSG_RECOMMENDATION_REQUEST_TIMEOUT = 1;
- public static final int MSG_RECOMMENDATIONS_ENABLED_CHANGED = 2;
+ public static final int MSG_RECOMMENDATIONS_PACKAGE_CHANGED = 2;
public static final int MSG_RECOMMENDATION_REQUEST_TIMEOUT_CHANGED = 3;
public ServiceHandler(Looper looper) {
@@ -1181,8 +1191,8 @@
sendDefaultRecommendationResponse(request, remoteCallback);
break;
- case MSG_RECOMMENDATIONS_ENABLED_CHANGED:
- bindToScoringServiceIfNeeded();
+ case MSG_RECOMMENDATIONS_PACKAGE_CHANGED:
+ refreshBinding();
break;
case MSG_RECOMMENDATION_REQUEST_TIMEOUT_CHANGED:
diff --git a/services/core/java/com/android/server/NetworkScorerAppManager.java b/services/core/java/com/android/server/NetworkScorerAppManager.java
new file mode 100644
index 0000000..2f4485a
--- /dev/null
+++ b/services/core/java/com/android/server/NetworkScorerAppManager.java
@@ -0,0 +1,245 @@
+/*
+ * 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.server;
+
+import android.Manifest.permission;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.net.NetworkScoreManager;
+import android.net.NetworkScorerAppData;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Internal class for discovering and managing the network scorer/recommendation application.
+ *
+ * @hide
+ */
+@VisibleForTesting
+public class NetworkScorerAppManager {
+ private static final String TAG = "NetworkScorerAppManager";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+ private final Context mContext;
+ private final SettingsFacade mSettingsFacade;
+
+ public NetworkScorerAppManager(Context context) {
+ this(context, new SettingsFacade());
+ }
+
+ @VisibleForTesting
+ public NetworkScorerAppManager(Context context, SettingsFacade settingsFacade) {
+ mContext = context;
+ mSettingsFacade = settingsFacade;
+ }
+
+ /**
+ * Returns the list of available scorer apps. The list will be empty if there are
+ * no valid scorers.
+ */
+ @VisibleForTesting
+ public List<NetworkScorerAppData> getAllValidScorers() {
+ if (VERBOSE) Log.v(TAG, "getAllValidScorers()");
+ final PackageManager pm = mContext.getPackageManager();
+ final Intent serviceIntent = new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS);
+ final List<ResolveInfo> resolveInfos =
+ pm.queryIntentServices(serviceIntent, PackageManager.GET_META_DATA);
+ if (resolveInfos == null || resolveInfos.isEmpty()) {
+ if (DEBUG) Log.d(TAG, "Found 0 Services able to handle " + serviceIntent);
+ return Collections.emptyList();
+ }
+
+ List<NetworkScorerAppData> appDataList = new ArrayList<>();
+ for (int i = 0; i < resolveInfos.size(); i++) {
+ final ServiceInfo serviceInfo = resolveInfos.get(i).serviceInfo;
+ if (hasPermissions(serviceInfo.packageName)) {
+ if (VERBOSE) {
+ Log.v(TAG, serviceInfo.packageName + " is a valid scorer/recommender.");
+ }
+ final ComponentName serviceComponentName =
+ new ComponentName(serviceInfo.packageName, serviceInfo.name);
+ final ComponentName useOpenWifiNetworksActivity =
+ findUseOpenWifiNetworksActivity(serviceInfo);
+ appDataList.add(
+ new NetworkScorerAppData(serviceInfo.applicationInfo.uid,
+ serviceComponentName, useOpenWifiNetworksActivity));
+ } else {
+ if (VERBOSE) Log.v(TAG, serviceInfo.packageName
+ + " is NOT a valid scorer/recommender.");
+ }
+ }
+
+ return appDataList;
+ }
+
+ @Nullable
+ private ComponentName findUseOpenWifiNetworksActivity(ServiceInfo serviceInfo) {
+ if (serviceInfo.metaData == null) {
+ if (DEBUG) {
+ Log.d(TAG, "No metadata found on " + serviceInfo.getComponentName());
+ }
+ return null;
+ }
+ final String useOpenWifiPackage = serviceInfo.metaData
+ .getString(NetworkScoreManager.USE_OPEN_WIFI_PACKAGE_META_DATA);
+ if (TextUtils.isEmpty(useOpenWifiPackage)) {
+ if (DEBUG) {
+ Log.d(TAG, "No use_open_wifi_package metadata found on "
+ + serviceInfo.getComponentName());
+ }
+ return null;
+ }
+ final Intent enableUseOpenWifiIntent = new Intent(NetworkScoreManager.ACTION_CUSTOM_ENABLE)
+ .setPackage(useOpenWifiPackage);
+ final ResolveInfo resolveActivityInfo = mContext.getPackageManager()
+ .resolveActivity(enableUseOpenWifiIntent, 0 /* flags */);
+ if (VERBOSE) {
+ Log.d(TAG, "Resolved " + enableUseOpenWifiIntent + " to " + resolveActivityInfo);
+ }
+
+ if (resolveActivityInfo != null && resolveActivityInfo.activityInfo != null) {
+ return resolveActivityInfo.activityInfo.getComponentName();
+ }
+
+ return null;
+ }
+
+ /**
+ * Get the application to use for scoring networks.
+ *
+ * @return the scorer app info or null if scoring is disabled (including if no scorer was ever
+ * selected) or if the previously-set scorer is no longer a valid scorer app (e.g. because
+ * it was disabled or uninstalled).
+ */
+ @Nullable
+ @VisibleForTesting
+ public NetworkScorerAppData getActiveScorer() {
+ return getScorer(getNetworkRecommendationsPackage());
+ }
+
+ private NetworkScorerAppData getScorer(String packageName) {
+ if (TextUtils.isEmpty(packageName)) {
+ return null;
+ }
+
+ // Otherwise return the recommendation provider (which may be null).
+ List<NetworkScorerAppData> apps = getAllValidScorers();
+ for (int i = 0; i < apps.size(); i++) {
+ NetworkScorerAppData app = apps.get(i);
+ if (app.getRecommendationServicePackageName().equals(packageName)) {
+ return app;
+ }
+ }
+
+ return null;
+ }
+
+ private boolean hasPermissions(String packageName) {
+ final PackageManager pm = mContext.getPackageManager();
+ return pm.checkPermission(permission.SCORE_NETWORKS, packageName)
+ == PackageManager.PERMISSION_GRANTED;
+ }
+
+ /**
+ * Set the specified package as the default scorer application.
+ *
+ * <p>The caller must have permission to write to {@link Settings.Global}.
+ *
+ * @param packageName the packageName of the new scorer to use. If null, the scoring app will
+ * revert back to the configured default. Otherwise, the scorer will only
+ * be set if it is a valid scorer application.
+ * @return true if the scorer was changed, or false if the package is not a valid scorer or
+ * a valid network recommendation provider exists.
+ */
+ @VisibleForTesting
+ public boolean setActiveScorer(String packageName) {
+ String oldPackageName = getNetworkRecommendationsPackage();
+ if (TextUtils.equals(oldPackageName, packageName)) {
+ // No change.
+ return true;
+ }
+
+ Log.i(TAG, "Changing network scorer from " + oldPackageName + " to " + packageName);
+
+ if (packageName == null) {
+ // revert to the default setting.
+ setNetworkRecommendationsPackage(getDefaultPackageSetting());
+ return true;
+ } else {
+ // We only make the change if the new package is valid.
+ if (getScorer(packageName) != null) {
+ setNetworkRecommendationsPackage(packageName);
+ return true;
+ } else {
+ Log.w(TAG, "Requested network scorer is not valid: " + packageName);
+ return false;
+ }
+ }
+ }
+
+ /**
+ * If the active scorer is null then revert to the default scorer.
+ */
+ @VisibleForTesting
+ public void revertToDefaultIfNoActive() {
+ if (getActiveScorer() == null) {
+ final String defaultPackage = getDefaultPackageSetting();
+ setNetworkRecommendationsPackage(defaultPackage);
+ Log.i(TAG, "Defaulted the network recommendations app to: " + defaultPackage);
+ }
+ }
+
+ private String getDefaultPackageSetting() {
+ return mContext.getResources().getString(
+ R.string.config_defaultNetworkRecommendationProviderPackage);
+ }
+
+ private String getNetworkRecommendationsPackage() {
+ return mSettingsFacade.getString(mContext, Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE);
+ }
+
+ private void setNetworkRecommendationsPackage(String packageName) {
+ mSettingsFacade.putString(mContext,
+ Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, packageName);
+ }
+
+ /**
+ * Wrapper around Settings to make testing easier.
+ */
+ public static class SettingsFacade {
+ public boolean putString(Context context, String name, String value) {
+ return Settings.Global.putString(context.getContentResolver(), name, value);
+ }
+
+ public String getString(Context context, String name) {
+ return Settings.Global.getString(context.getContentResolver(), name);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/SystemService.java b/services/core/java/com/android/server/SystemService.java
index ce3166d..421d5a6 100644
--- a/services/core/java/com/android/server/SystemService.java
+++ b/services/core/java/com/android/server/SystemService.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.os.IBinder;
import android.os.ServiceManager;
+import android.os.UserManager;
/**
* The base class for services running in the system process. Override and implement
@@ -133,9 +134,16 @@
public void onStartUser(int userHandle) {}
/**
- * Called when an existing user is unlocked. This means the
- * credential-encrypted storage for that user is now available, and
- * encryption-aware component filtering is no longer in effect.
+ * Called when an existing user is in the process of being unlocked. This
+ * means the credential-encrypted storage for that user is now available,
+ * and encryption-aware component filtering is no longer in effect.
+ * <p>
+ * While dispatching this event to services, the user is in the
+ * {@code STATE_RUNNING_UNLOCKING} state, and once dispatching is finished
+ * the user will transition into the {@code STATE_RUNNING_UNLOCKED} state.
+ * Code written inside system services should use
+ * {@link UserManager#isUserUnlockingOrUnlocked(int)} to handle both of
+ * these states.
*
* @param userHandle The identifier of the user.
*/
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 7524351..d287d85 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -10708,10 +10708,7 @@
} catch (RemoteException ignored) {
}
if (cpi == null) {
- // TODO: make this an outright failure in a future platform release;
- // until then anonymous content notifications are unprotected
- //return "Failed to find provider " + authority + " for user " + userId;
- return null;
+ return "Failed to find provider " + authority + " for user " + userId;
}
ProcessRecord r = null;
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 886c97f..4b34eba56 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -43,6 +43,7 @@
import android.database.sqlite.SQLiteException;
import android.net.Uri;
import android.os.Binder;
+import android.os.Build;
import android.os.Bundle;
import android.os.FactoryTest;
import android.os.IBinder;
@@ -287,7 +288,7 @@
*/
@Override
public void registerContentObserver(Uri uri, boolean notifyForDescendants,
- IContentObserver observer, int userHandle) {
+ IContentObserver observer, int userHandle, int targetSdkVersion) {
if (observer == null || uri == null) {
throw new IllegalArgumentException("You must pass a valid uri and observer");
}
@@ -301,8 +302,17 @@
final String msg = LocalServices.getService(ActivityManagerInternal.class)
.checkContentProviderAccess(uri.getAuthority(), userHandle);
if (msg != null) {
- Log.w(TAG, "Ignoring content changes for " + uri + " from " + uid + ": " + msg);
- return;
+ if (targetSdkVersion >= Build.VERSION_CODES.O) {
+ throw new SecurityException(msg);
+ } else {
+ if (msg.startsWith("Failed to find provider")) {
+ // Sigh, we need to quietly let apps targeting older API
+ // levels notify on non-existent providers.
+ } else {
+ Log.w(TAG, "Ignoring content changes for " + uri + " from " + uid + ": " + msg);
+ return;
+ }
+ }
}
synchronized (mRootNode) {
@@ -316,7 +326,7 @@
public void registerContentObserver(Uri uri, boolean notifyForDescendants,
IContentObserver observer) {
registerContentObserver(uri, notifyForDescendants, observer,
- UserHandle.getCallingUserId());
+ UserHandle.getCallingUserId(), Build.VERSION_CODES.CUR_DEVELOPMENT);
}
@Override
@@ -340,8 +350,8 @@
*/
@Override
public void notifyChange(Uri uri, IContentObserver observer,
- boolean observerWantsSelfNotifications, int flags,
- int userHandle) {
+ boolean observerWantsSelfNotifications, int flags, int userHandle,
+ int targetSdkVersion) {
if (DEBUG) Slog.d(TAG, "Notifying update of " + uri + " for user " + userHandle
+ " from observer " + observer + ", flags " + Integer.toHexString(flags));
@@ -359,8 +369,17 @@
final String msg = LocalServices.getService(ActivityManagerInternal.class)
.checkContentProviderAccess(uri.getAuthority(), userHandle);
if (msg != null) {
- Log.w(TAG, "Ignoring notify for " + uri + " from " + uid + ": " + msg);
- return;
+ if (targetSdkVersion >= Build.VERSION_CODES.O) {
+ throw new SecurityException(msg);
+ } else {
+ if (msg.startsWith("Failed to find provider")) {
+ // Sigh, we need to quietly let apps targeting older API
+ // levels notify on non-existent providers.
+ } else {
+ Log.w(TAG, "Ignoring notify for " + uri + " from " + uid + ": " + msg);
+ return;
+ }
+ }
}
// This makes it so that future permission checks will be in the context of this
@@ -427,7 +446,7 @@
boolean observerWantsSelfNotifications, boolean syncToNetwork) {
notifyChange(uri, observer, observerWantsSelfNotifications,
syncToNetwork ? ContentResolver.NOTIFY_SYNC_TO_NETWORK : 0,
- UserHandle.getCallingUserId());
+ UserHandle.getCallingUserId(), Build.VERSION_CODES.CUR_DEVELOPMENT);
}
/**
diff --git a/services/core/java/com/android/server/notification/BadgeExtractor.java b/services/core/java/com/android/server/notification/BadgeExtractor.java
index 4795fbf..e6edaf1 100644
--- a/services/core/java/com/android/server/notification/BadgeExtractor.java
+++ b/services/core/java/com/android/server/notification/BadgeExtractor.java
@@ -46,7 +46,9 @@
if (!appCanShowBadge) {
record.setShowBadge(false);
} else {
- record.setShowBadge(record.getChannel().canShowBadge() && appCanShowBadge);
+ record.setShowBadge(mConfig.getNotificationChannel(record.sbn.getPackageName(),
+ record.sbn.getUid(), record.getChannel().getId(), false).canShowBadge()
+ && appCanShowBadge);
}
return null;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 8f4ad00..45ff20b 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2029,11 +2029,11 @@
*/
@Override
public void snoozeNotificationUntilFromListener(INotificationListener token, String key,
- long snoozeUntil) {
+ long duration) {
long identity = Binder.clearCallingIdentity();
try {
final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
- snoozeNotificationInt(key, snoozeUntil, null, info);
+ snoozeNotificationInt(key, duration, null, info);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -3409,7 +3409,7 @@
@VisibleForTesting
void scheduleTimeoutLocked(NotificationRecord record) {
- if (record.getNotification().getTimeout() > System.currentTimeMillis()) {
+ if (record.getNotification().getTimeout() > 0) {
final PendingIntent pi = PendingIntent.getBroadcast(getContext(),
REQUEST_CODE_TIMEOUT,
new Intent(ACTION_NOTIFICATION_TIMEOUT)
@@ -3418,8 +3418,8 @@
.addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
.putExtra(EXTRA_KEY, record.getKey()),
PendingIntent.FLAG_UPDATE_CURRENT);
- mAlarmManager.setExactAndAllowWhileIdle(
- AlarmManager.RTC_WAKEUP, record.getNotification().getTimeout(), pi);
+ mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ SystemClock.elapsedRealtime() + record.getNotification().getTimeout(), pi);
}
}
@@ -4185,16 +4185,16 @@
}
}
- void snoozeNotificationInt(String key, long until, String snoozeCriterionId,
+ void snoozeNotificationInt(String key, long duration, String snoozeCriterionId,
ManagedServiceInfo listener) {
String listenerName = listener == null ? null : listener.component.toShortString();
- if (until < System.currentTimeMillis() && snoozeCriterionId == null) {
+ if (duration <= 0 && snoozeCriterionId == null) {
return;
}
if (DBG) {
- Slog.d(TAG, String.format("snooze event(%s, %d, %s, %s)", key, until, snoozeCriterionId,
- listenerName));
+ Slog.d(TAG, String.format("snooze event(%s, %d, %s, %s)", key, duration,
+ snoozeCriterionId, listenerName));
}
// Needs to post so that it can cancel notifications not yet enqueued.
mHandler.post(new Runnable() {
@@ -4215,7 +4215,7 @@
snoozeCriterionId);
mSnoozeHelper.snooze(r);
} else {
- mSnoozeHelper.snooze(r, until);
+ mSnoozeHelper.snooze(r, duration);
}
savePolicyFile();
}
diff --git a/services/core/java/com/android/server/notification/SnoozeHelper.java b/services/core/java/com/android/server/notification/SnoozeHelper.java
index 0cd8cea..913f636 100644
--- a/services/core/java/com/android/server/notification/SnoozeHelper.java
+++ b/services/core/java/com/android/server/notification/SnoozeHelper.java
@@ -32,6 +32,7 @@
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Binder;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
@@ -125,9 +126,9 @@
/**
* Snoozes a notification and schedules an alarm to repost at that time.
*/
- protected void snooze(NotificationRecord record, long until) {
+ protected void snooze(NotificationRecord record, long duration) {
snooze(record);
- scheduleRepost(record.sbn.getPackageName(), record.getKey(), record.getUserId(), until);
+ scheduleRepost(record.sbn.getPackageName(), record.getKey(), record.getUserId(), duration);
}
/**
@@ -291,13 +292,14 @@
PendingIntent.FLAG_UPDATE_CURRENT);
}
- private void scheduleRepost(String pkg, String key, int userId, long time) {
+ private void scheduleRepost(String pkg, String key, int userId, long duration) {
long identity = Binder.clearCallingIdentity();
try {
final PendingIntent pi = createPendingIntent(pkg, key, userId);
mAm.cancel(pi);
+ long time = SystemClock.elapsedRealtime() + duration;
if (DEBUG) Slog.d(TAG, "Scheduling evaluate for " + new Date(time));
- mAm.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, time, pi);
+ mAm.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, time, pi);
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 53765f2..a7a1683 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -607,6 +607,12 @@
+ "to use the PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS flag");
}
+ if ((params.installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0
+ || (params.installFlags & PackageManager.INSTALL_EXTERNAL) != 0) {
+ throw new IllegalArgumentException(
+ "New installs into ASEC containers no longer supported");
+ }
+
// Defensively resize giant app icons
if (params.appIcon != null) {
final ActivityManager am = (ActivityManager) mContext.getSystemService(
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index fbf953f..6157f57 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -128,7 +128,6 @@
import android.content.pm.AppsQueryHelper;
import android.content.pm.ChangedPackages;
import android.content.pm.ComponentInfo;
-import android.content.pm.InstantAppInfo;
import android.content.pm.EphemeralRequest;
import android.content.pm.EphemeralResolveInfo;
import android.content.pm.AuxiliaryResolveInfo;
@@ -143,6 +142,7 @@
import android.content.pm.IPackageManager;
import android.content.pm.IPackageMoveObserver;
import android.content.pm.IPackageStatsObserver;
+import android.content.pm.InstantAppInfo;
import android.content.pm.InstrumentationInfo;
import android.content.pm.IntentFilterVerificationInfo;
import android.content.pm.KeySet;
@@ -204,15 +204,16 @@
import android.os.UserManager;
import android.os.UserManagerInternal;
import android.os.storage.IStorageManager;
-import android.os.storage.StorageManagerInternal;
import android.os.storage.StorageEventListener;
import android.os.storage.StorageManager;
+import android.os.storage.StorageManagerInternal;
import android.os.storage.VolumeInfo;
import android.os.storage.VolumeRecord;
import android.provider.Settings.Global;
import android.provider.Settings.Secure;
import android.security.KeyStore;
import android.security.SystemKeyStore;
+import android.service.pm.PackageServiceDumpProto;
import android.system.ErrnoException;
import android.system.Os;
import android.text.TextUtils;
@@ -235,6 +236,7 @@
import android.util.SparseIntArray;
import android.util.Xml;
import android.util.jar.StrictJarFile;
+import android.util.proto.ProtoOutputStream;
import android.view.Display;
import com.android.internal.R;
@@ -316,8 +318,8 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
-import java.util.HashSet;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -13068,6 +13070,12 @@
+ "to use the PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS flag");
}
+ if ((installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0
+ || (installFlags & PackageManager.INSTALL_EXTERNAL) != 0) {
+ throw new IllegalArgumentException(
+ "New installs into ASEC containers no longer supported");
+ }
+
final File originFile = new File(originPath);
final OriginInfo origin = OriginInfo.fromUntrustedFile(originFile);
@@ -20299,6 +20307,9 @@
checkin = true;
} else if ("-f".equals(opt)) {
dumpState.setOptionEnabled(DumpState.OPTION_SHOW_FILTERS);
+ } else if ("--proto".equals(opt)) {
+ dumpProto(fd);
+ return;
} else {
pw.println("Unknown argument: " + opt + "; use -h for help");
}
@@ -20836,6 +20847,98 @@
}
}
+ private void dumpProto(FileDescriptor fd) {
+ final ProtoOutputStream proto = new ProtoOutputStream(fd);
+
+ synchronized (mPackages) {
+ final long requiredVerifierPackageToken =
+ proto.start(PackageServiceDumpProto.REQUIRED_VERIFIER_PACKAGE);
+ proto.write(PackageServiceDumpProto.PackageShortProto.NAME, mRequiredVerifierPackage);
+ proto.write(
+ PackageServiceDumpProto.PackageShortProto.UID,
+ getPackageUid(
+ mRequiredVerifierPackage,
+ MATCH_DEBUG_TRIAGED_MISSING,
+ UserHandle.USER_SYSTEM));
+ proto.end(requiredVerifierPackageToken);
+
+ if (mIntentFilterVerifierComponent != null) {
+ String verifierPackageName = mIntentFilterVerifierComponent.getPackageName();
+ final long verifierPackageToken =
+ proto.start(PackageServiceDumpProto.VERIFIER_PACKAGE);
+ proto.write(PackageServiceDumpProto.PackageShortProto.NAME, verifierPackageName);
+ proto.write(
+ PackageServiceDumpProto.PackageShortProto.UID,
+ getPackageUid(
+ verifierPackageName,
+ MATCH_DEBUG_TRIAGED_MISSING,
+ UserHandle.USER_SYSTEM));
+ proto.end(verifierPackageToken);
+ }
+
+ dumpSharedLibrariesProto(proto);
+ dumpFeaturesProto(proto);
+ mSettings.dumpPackagesProto(proto);
+ mSettings.dumpSharedUsersProto(proto);
+ dumpMessagesProto(proto);
+ }
+ proto.flush();
+ }
+
+ private void dumpMessagesProto(ProtoOutputStream proto) {
+ BufferedReader in = null;
+ String line = null;
+ try {
+ in = new BufferedReader(new FileReader(getSettingsProblemFile()));
+ while ((line = in.readLine()) != null) {
+ if (line.contains("ignored: updated version")) continue;
+ proto.write(PackageServiceDumpProto.MESSAGES, line);
+ }
+ } catch (IOException ignored) {
+ } finally {
+ IoUtils.closeQuietly(in);
+ }
+ }
+
+ private void dumpFeaturesProto(ProtoOutputStream proto) {
+ synchronized (mAvailableFeatures) {
+ final int count = mAvailableFeatures.size();
+ for (int i = 0; i < count; i++) {
+ final FeatureInfo feat = mAvailableFeatures.valueAt(i);
+ final long featureToken = proto.start(PackageServiceDumpProto.FEATURES);
+ proto.write(PackageServiceDumpProto.FeatureProto.NAME, feat.name);
+ proto.write(PackageServiceDumpProto.FeatureProto.VERSION, feat.version);
+ proto.end(featureToken);
+ }
+ }
+ }
+
+ private void dumpSharedLibrariesProto(ProtoOutputStream proto) {
+ final int count = mSharedLibraries.size();
+ for (int i = 0; i < count; i++) {
+ final String libName = mSharedLibraries.keyAt(i);
+ SparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.get(libName);
+ if (versionedLib == null) {
+ continue;
+ }
+ final int versionCount = versionedLib.size();
+ for (int j = 0; j < versionCount; j++) {
+ final SharedLibraryEntry libEntry = versionedLib.valueAt(j);
+ final long sharedLibraryToken =
+ proto.start(PackageServiceDumpProto.SHARED_LIBRARIES);
+ proto.write(PackageServiceDumpProto.SharedLibraryProto.NAME, libEntry.info.getName());
+ final boolean isJar = (libEntry.path != null);
+ proto.write(PackageServiceDumpProto.SharedLibraryProto.IS_JAR, isJar);
+ if (isJar) {
+ proto.write(PackageServiceDumpProto.SharedLibraryProto.PATH, libEntry.path);
+ } else {
+ proto.write(PackageServiceDumpProto.SharedLibraryProto.APK, libEntry.apk);
+ }
+ proto.end(sharedLibraryToken);
+ }
+ }
+ }
+
private void dumpDexoptStateLPr(PrintWriter pw, String packageName) {
final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120);
ipw.println();
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 5f348ab..b4bba88 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -19,6 +19,9 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
+import android.content.pm.UserInfo;
+import android.service.pm.PackageProto;
+import android.util.proto.ProtoOutputStream;
import java.io.File;
import java.util.List;
@@ -128,4 +131,32 @@
}
return true;
}
+
+ public void writeToProto(ProtoOutputStream proto, long fieldId, List<UserInfo> users) {
+ final long packageToken = proto.start(fieldId);
+ proto.write(PackageProto.NAME, (realName != null ? realName : name));
+ proto.write(PackageProto.UID, appId);
+ proto.write(PackageProto.VERSION_CODE, versionCode);
+ proto.write(PackageProto.VERSION_STRING, pkg.mVersionName);
+ proto.write(PackageProto.INSTALL_TIME_MS, firstInstallTime);
+ proto.write(PackageProto.UPDATE_TIME_MS, lastUpdateTime);
+ proto.write(PackageProto.INSTALLER_NAME, installerPackageName);
+
+ if (pkg != null) {
+ long splitToken = proto.start(PackageProto.SPLITS);
+ proto.write(PackageProto.SplitProto.NAME, "base");
+ proto.write(PackageProto.SplitProto.REVISION_CODE, pkg.baseRevisionCode);
+ proto.end(splitToken);
+ if (pkg.splitNames != null) {
+ for (int i = 0; i < pkg.splitNames.length; i++) {
+ splitToken = proto.start(PackageProto.SPLITS);
+ proto.write(PackageProto.SplitProto.NAME, pkg.splitNames[i]);
+ proto.write(PackageProto.SplitProto.REVISION_CODE, pkg.splitRevisionCodes[i]);
+ proto.end(splitToken);
+ }
+ }
+ }
+ writeUsersInfoToProto(proto, PackageProto.USERS);
+ proto.end(packageToken);
+ }
}
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 601377d6..b9c43da 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -25,8 +25,10 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageUserState;
import android.os.storage.VolumeInfo;
+import android.service.pm.PackageProto;
import android.util.ArraySet;
import android.util.SparseArray;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
@@ -564,4 +566,32 @@
modifyUserState(userId).domainVerificationStatus =
PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
}
+
+ protected void writeUsersInfoToProto(ProtoOutputStream proto, long fieldId) {
+ int count = userState.size();
+ for (int i = 0; i < count; i++) {
+ final long userToken = proto.start(fieldId);
+ final int userId = userState.keyAt(i);
+ final PackageUserState state = userState.valueAt(i);
+ proto.write(PackageProto.UserInfoProto.ID, userId);
+ final int installType;
+ if (state.instantApp) {
+ installType = PackageProto.UserInfoProto.INSTANT_APP_INSTALL;
+ } else if (state.installed) {
+ installType = PackageProto.UserInfoProto.FULL_APP_INSTALL;
+ } else {
+ installType = PackageProto.UserInfoProto.NOT_INSTALLED_FOR_USER;
+ }
+ proto.write(PackageProto.UserInfoProto.INSTALL_TYPE, installType);
+ proto.write(PackageProto.UserInfoProto.IS_HIDDEN, state.hidden);
+ proto.write(PackageProto.UserInfoProto.IS_SUSPENDED, state.suspended);
+ proto.write(PackageProto.UserInfoProto.IS_STOPPED, state.stopped);
+ proto.write(PackageProto.UserInfoProto.IS_LAUNCHED, !state.notLaunched);
+ proto.write(PackageProto.UserInfoProto.ENABLED_STATE, state.enabled);
+ proto.write(
+ PackageProto.UserInfoProto.LAST_DISABLED_APP_CALLER,
+ state.lastDisableAppCaller);
+ proto.end(userToken);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index a057e9b..570b31f 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -65,6 +65,7 @@
import android.os.UserManager;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
+import android.service.pm.PackageServiceDumpProto;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -77,6 +78,7 @@
import android.util.SparseIntArray;
import android.util.SparseLongArray;
import android.util.Xml;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BackgroundThread;
@@ -887,9 +889,9 @@
}
if (p.appId < 0) {
PackageManagerService.reportSettingsProblem(Log.WARN,
- "Package " + p.name + " could not be assigned a valid uid");
+ "Package " + p.name + " could not be assigned a valid UID");
throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
- "Creating application package " + p.name + " failed");
+ "Package " + p.name + " could not be assigned a valid UID");
}
}
@@ -4876,6 +4878,16 @@
}
}
+ void dumpPackagesProto(ProtoOutputStream proto) {
+ List<UserInfo> users = getAllUsers(UserManagerService.getInstance());
+
+ final int count = mPackages.size();
+ for (int i = 0; i < count; i++) {
+ final PackageSetting ps = mPackages.valueAt(i);
+ ps.writeToProto(proto, PackageServiceDumpProto.PACKAGES, users);
+ }
+ }
+
void dumpPermissionsLPr(PrintWriter pw, String packageName, ArraySet<String> permissionNames,
DumpState dumpState) {
boolean printedSomething = false;
@@ -4966,6 +4978,17 @@
}
}
+ void dumpSharedUsersProto(ProtoOutputStream proto) {
+ final int count = mSharedUsers.size();
+ for (int i = 0; i < count; i++) {
+ final SharedUserSetting su = mSharedUsers.valueAt(i);
+ final long sharedUserToken = proto.start(PackageServiceDumpProto.SHARED_USERS);
+ proto.write(PackageServiceDumpProto.SharedUserProto.USER_ID, su.userId);
+ proto.write(PackageServiceDumpProto.SharedUserProto.NAME, su.name);
+ proto.end(sharedUserToken);
+ }
+ }
+
void dumpReadMessagesLPr(PrintWriter pw, DumpState dumpState) {
pw.println("Settings parse messages:");
pw.print(mReadMessages.toString());
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index b76a249..d3931fb 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -51,21 +51,23 @@
import android.os.UserHandle;
import android.os.WorkSource;
import android.provider.Settings;
-import android.provider.Settings.Secure;
import android.provider.Settings.SettingNotFoundException;
import android.service.dreams.DreamManagerInternal;
+import android.service.power.PowerServiceDumpProto;
+import android.service.power.PowerServiceSettingsAndConfigurationDumpProto;
+import android.service.power.SuspendBlockerProto;
+import android.service.power.WakeLockProto;
import android.service.vr.IVrManager;
import android.service.vr.IVrStateCallbacks;
import android.util.EventLog;
import android.util.KeyValueListParser;
-import android.util.Log;
import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.util.SparseArray;
import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
import android.view.Display;
import android.view.WindowManagerPolicy;
-
import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IBatteryStats;
import com.android.internal.os.BackgroundThread;
@@ -78,7 +80,7 @@
import com.android.server.am.BatteryStatsService;
import com.android.server.lights.Light;
import com.android.server.lights.LightsManager;
-import com.android.server.vr.VrManagerService;
+
import libcore.util.Objects;
import java.io.FileDescriptor;
@@ -575,6 +577,13 @@
pw.print(" "); pw.print(KEY_NO_CACHED_WAKE_LOCKS); pw.print("=");
pw.println(NO_CACHED_WAKE_LOCKS);
}
+
+ void dumpProto(ProtoOutputStream proto) {
+ final long constantsToken = proto.start(PowerServiceDumpProto.CONSTANTS);
+ proto.write(PowerServiceDumpProto.ConstantsProto.IS_NO_CACHED_WAKE_LOCKS,
+ NO_CACHED_WAKE_LOCKS);
+ proto.end(constantsToken);
+ }
}
final Constants mConstants;
@@ -3244,6 +3253,354 @@
}
}
+ private void dumpProto(FileDescriptor fd) {
+ final WirelessChargerDetector wcd;
+ final ProtoOutputStream proto = new ProtoOutputStream(fd);
+
+ synchronized (mLock) {
+ mConstants.dumpProto(proto);
+ proto.write(PowerServiceDumpProto.DIRTY, mDirty);
+ proto.write(PowerServiceDumpProto.WAKEFULNESS, mWakefulness);
+ proto.write(PowerServiceDumpProto.IS_WAKEFULNESS_CHANGING, mWakefulnessChanging);
+ proto.write(PowerServiceDumpProto.IS_POWERED, mIsPowered);
+ proto.write(PowerServiceDumpProto.PLUG_TYPE, mPlugType);
+ proto.write(PowerServiceDumpProto.BATTERY_LEVEL, mBatteryLevel);
+ proto.write(
+ PowerServiceDumpProto.BATTERY_LEVEL_WHEN_DREAM_STARTED,
+ mBatteryLevelWhenDreamStarted);
+ proto.write(PowerServiceDumpProto.DOCK_STATE, mDockState);
+ proto.write(PowerServiceDumpProto.IS_STAY_ON, mStayOn);
+ proto.write(PowerServiceDumpProto.IS_PROXIMITY_POSITIVE, mProximityPositive);
+ proto.write(PowerServiceDumpProto.IS_BOOT_COMPLETED, mBootCompleted);
+ proto.write(PowerServiceDumpProto.IS_SYSTEM_READY, mSystemReady);
+ proto.write(
+ PowerServiceDumpProto.IS_HAL_AUTO_SUSPEND_MODE_ENABLED,
+ mHalAutoSuspendModeEnabled);
+ proto.write(
+ PowerServiceDumpProto.IS_HAL_AUTO_INTERACTIVE_MODE_ENABLED,
+ mHalInteractiveModeEnabled);
+
+ final long activeWakeLocksToken = proto.start(PowerServiceDumpProto.ACTIVE_WAKE_LOCKS);
+ proto.write(
+ PowerServiceDumpProto.ActiveWakeLocksProto.IS_CPU,
+ (mWakeLockSummary & WAKE_LOCK_CPU) != 0);
+ proto.write(
+ PowerServiceDumpProto.ActiveWakeLocksProto.IS_SCREEN_BRIGHT,
+ (mWakeLockSummary & WAKE_LOCK_SCREEN_BRIGHT) != 0);
+ proto.write(
+ PowerServiceDumpProto.ActiveWakeLocksProto.IS_SCREEN_DIM,
+ (mWakeLockSummary & WAKE_LOCK_SCREEN_DIM) != 0);
+ proto.write(
+ PowerServiceDumpProto.ActiveWakeLocksProto.IS_BUTTON_BRIGHT,
+ (mWakeLockSummary & WAKE_LOCK_BUTTON_BRIGHT) != 0);
+ proto.write(
+ PowerServiceDumpProto.ActiveWakeLocksProto.IS_PROXIMITY_SCREEN_OFF,
+ (mWakeLockSummary & WAKE_LOCK_PROXIMITY_SCREEN_OFF) != 0);
+ proto.write(
+ PowerServiceDumpProto.ActiveWakeLocksProto.IS_STAY_AWAKE,
+ (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) != 0);
+ proto.write(
+ PowerServiceDumpProto.ActiveWakeLocksProto.IS_DOZE,
+ (mWakeLockSummary & WAKE_LOCK_DOZE) != 0);
+ proto.write(
+ PowerServiceDumpProto.ActiveWakeLocksProto.IS_DRAW,
+ (mWakeLockSummary & WAKE_LOCK_DRAW) != 0);
+ proto.end(activeWakeLocksToken);
+
+ proto.write(PowerServiceDumpProto.NOTIFY_LONG_SCHEDULED_MS, mNotifyLongScheduled);
+ proto.write(PowerServiceDumpProto.NOTIFY_LONG_DISPATCHED_MS, mNotifyLongDispatched);
+ proto.write(PowerServiceDumpProto.NOTIFY_LONG_NEXT_CHECK_MS, mNotifyLongNextCheck);
+
+ final long userActivityToken = proto.start(PowerServiceDumpProto.USER_ACTIVITY);
+ proto.write(
+ PowerServiceDumpProto.UserActivityProto.IS_SCREEN_BRIGHT,
+ (mUserActivitySummary & USER_ACTIVITY_SCREEN_BRIGHT) != 0);
+ proto.write(
+ PowerServiceDumpProto.UserActivityProto.IS_SCREEN_DIM,
+ (mUserActivitySummary & USER_ACTIVITY_SCREEN_DIM) != 0);
+ proto.write(
+ PowerServiceDumpProto.UserActivityProto.IS_SCREEN_DREAM,
+ (mUserActivitySummary & USER_ACTIVITY_SCREEN_DREAM) != 0);
+ proto.end(userActivityToken);
+
+ proto.write(
+ PowerServiceDumpProto.IS_REQUEST_WAIT_FOR_NEGATIVE_PROXIMITY,
+ mRequestWaitForNegativeProximity);
+ proto.write(PowerServiceDumpProto.IS_SANDMAN_SCHEDULED, mSandmanScheduled);
+ proto.write(PowerServiceDumpProto.IS_SANDMAN_SUMMONED, mSandmanSummoned);
+ proto.write(PowerServiceDumpProto.IS_LOW_POWER_MODE_ENABLED, mLowPowerModeEnabled);
+ proto.write(PowerServiceDumpProto.IS_BATTERY_LEVEL_LOW, mBatteryLevelLow);
+ proto.write(PowerServiceDumpProto.IS_LIGHT_DEVICE_IDLE_MODE, mLightDeviceIdleMode);
+ proto.write(PowerServiceDumpProto.IS_DEVICE_IDLE_MODE, mDeviceIdleMode);
+
+ for (int id : mDeviceIdleWhitelist) {
+ proto.write(PowerServiceDumpProto.DEVICE_IDLE_WHITELIST, id);
+ }
+ for (int id : mDeviceIdleTempWhitelist) {
+ proto.write(PowerServiceDumpProto.DEVICE_IDLE_TEMP_WHITELIST, id);
+ }
+
+ proto.write(PowerServiceDumpProto.LAST_WAKE_TIME_MS, mLastWakeTime);
+ proto.write(PowerServiceDumpProto.LAST_SLEEP_TIME_MS, mLastSleepTime);
+ proto.write(PowerServiceDumpProto.LAST_USER_ACTIVITY_TIME_MS, mLastUserActivityTime);
+ proto.write(
+ PowerServiceDumpProto.LAST_USER_ACTIVITY_TIME_NO_CHANGE_LIGHTS_MS,
+ mLastUserActivityTimeNoChangeLights);
+ proto.write(
+ PowerServiceDumpProto.LAST_INTERACTIVE_POWER_HINT_TIME_MS,
+ mLastInteractivePowerHintTime);
+ proto.write(
+ PowerServiceDumpProto.LAST_SCREEN_BRIGHTNESS_BOOST_TIME_MS,
+ mLastScreenBrightnessBoostTime);
+ proto.write(
+ PowerServiceDumpProto.IS_SCREEN_BRIGHTNESS_BOOST_IN_PROGRESS,
+ mScreenBrightnessBoostInProgress);
+ proto.write(PowerServiceDumpProto.IS_DISPLAY_READY, mDisplayReady);
+ proto.write(
+ PowerServiceDumpProto.IS_HOLDING_WAKE_LOCK_SUSPEND_BLOCKER,
+ mHoldingWakeLockSuspendBlocker);
+ proto.write(
+ PowerServiceDumpProto.IS_HOLDING_DISPLAY_SUSPEND_BLOCKER,
+ mHoldingDisplaySuspendBlocker);
+
+ final long settingsAndConfigurationToken =
+ proto.start(PowerServiceDumpProto.SETTINGS_AND_CONFIGURATION);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .IS_DECOUPLE_HAL_AUTO_SUSPEND_MODE_FROM_DISPLAY_CONFIG,
+ mDecoupleHalAutoSuspendModeFromDisplayConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .IS_DECOUPLE_HAL_INTERACTIVE_MODE_FROM_DISPLAY_CONFIG,
+ mDecoupleHalInteractiveModeFromDisplayConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .IS_WAKE_UP_WHEN_PLUGGED_OR_UNPLUGGED_CONFIG,
+ mWakeUpWhenPluggedOrUnpluggedConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .IS_WAKE_UP_WHEN_PLUGGED_OR_UNPLUGGED_IN_THEATER_MODE_CONFIG,
+ mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.IS_THEATER_MODE_ENABLED,
+ mTheaterModeEnabled);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .IS_SUSPEND_WHEN_SCREEN_OFF_DUE_TO_PROXIMITY_CONFIG,
+ mSuspendWhenScreenOffDueToProximityConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.ARE_DREAMS_SUPPORTED_CONFIG,
+ mDreamsSupportedConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .ARE_DREAMS_ENABLED_BY_DEFAULT_CONFIG,
+ mDreamsEnabledByDefaultConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .ARE_DREAMS_ACTIVATED_ON_SLEEP_BY_DEFAULT_CONFIG,
+ mDreamsActivatedOnSleepByDefaultConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .ARE_DREAMS_ACTIVATED_ON_DOCK_BY_DEFAULT_CONFIG,
+ mDreamsActivatedOnDockByDefaultConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .ARE_DREAMS_ENABLED_ON_BATTERY_CONFIG,
+ mDreamsEnabledOnBatteryConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .DREAMS_BATTERY_LEVEL_MINIMUM_WHEN_POWERED_CONFIG,
+ mDreamsBatteryLevelMinimumWhenPoweredConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .DREAMS_BATTERY_LEVEL_MINIMUM_WHEN_NOT_POWERED_CONFIG,
+ mDreamsBatteryLevelMinimumWhenNotPoweredConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .DREAMS_BATTERY_LEVEL_DRAIN_CUTOFF_CONFIG,
+ mDreamsBatteryLevelDrainCutoffConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.ARE_DREAMS_ENABLED_SETTING,
+ mDreamsEnabledSetting);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .ARE_DREAMS_ACTIVATE_ON_SLEEP_SETTING,
+ mDreamsActivateOnSleepSetting);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .ARE_DREAMS_ACTIVATE_ON_DOCK_SETTING,
+ mDreamsActivateOnDockSetting);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.IS_DOZE_AFTER_SCREEN_OFF_CONFIG,
+ mDozeAfterScreenOffConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.IS_LOW_POWER_MODE_SETTING,
+ mLowPowerModeSetting);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.IS_AUTO_LOW_POWER_MODE_CONFIGURED,
+ mAutoLowPowerModeConfigured);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.IS_AUTO_LOW_POWER_MODE_SNOOZING,
+ mAutoLowPowerModeSnoozing);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .MINIMUM_SCREEN_OFF_TIMEOUT_CONFIG_MS,
+ mMinimumScreenOffTimeoutConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .MAXIMUM_SCREEN_DIM_DURATION_CONFIG_MS,
+ mMaximumScreenDimDurationConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.MAXIMUM_SCREEN_DIM_RATIO_CONFIG,
+ mMaximumScreenDimRatioConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.SCREEN_OFF_TIMEOUT_SETTING_MS,
+ mScreenOffTimeoutSetting);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.SLEEP_TIMEOUT_SETTING_MS,
+ mSleepTimeoutSetting);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .MAXIMUM_SCREEN_OFF_TIMEOUT_FROM_DEVICE_ADMIN_MS,
+ mMaximumScreenOffTimeoutFromDeviceAdmin);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .IS_MAXIMUM_SCREEN_OFF_TIMEOUT_FROM_DEVICE_ADMIN_ENFORCED_LOCKED,
+ isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked());
+
+ final long stayOnWhilePluggedInToken =
+ proto.start(
+ PowerServiceSettingsAndConfigurationDumpProto.STAY_ON_WHILE_PLUGGED_IN);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.StayOnWhilePluggedInProto
+ .IS_STAY_ON_WHILE_PLUGGED_IN_AC,
+ ((mStayOnWhilePluggedInSetting & BatteryManager.BATTERY_PLUGGED_AC) != 0));
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.StayOnWhilePluggedInProto
+ .IS_STAY_ON_WHILE_PLUGGED_IN_USB,
+ ((mStayOnWhilePluggedInSetting & BatteryManager.BATTERY_PLUGGED_USB) != 0));
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.StayOnWhilePluggedInProto
+ .IS_STAY_ON_WHILE_PLUGGED_IN_WIRELESS,
+ ((mStayOnWhilePluggedInSetting & BatteryManager.BATTERY_PLUGGED_WIRELESS)
+ != 0));
+ proto.end(stayOnWhilePluggedInToken);
+
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.SCREEN_BRIGHTNESS_SETTING,
+ mScreenBrightnessSetting);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_SETTING,
+ mScreenAutoBrightnessAdjustmentSetting);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.SCREEN_BRIGHTNESS_MODE_SETTING,
+ mScreenBrightnessModeSetting);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .SCREEN_BRIGHTNESS_OVERRIDE_FROM_WINDOW_MANAGER,
+ mScreenBrightnessOverrideFromWindowManager);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .USER_ACTIVITY_TIMEOUT_OVERRIDE_FROM_WINDOW_MANAGER_MS,
+ mUserActivityTimeoutOverrideFromWindowManager);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .IS_USER_INACTIVE_OVERRIDE_FROM_WINDOW_MANAGER,
+ mUserInactiveOverrideFromWindowManager);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .TEMPORARY_SCREEN_BRIGHTNESS_SETTING_OVERRIDE,
+ mTemporaryScreenBrightnessSettingOverride);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .TEMPORARY_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_SETTING_OVERRIDE,
+ mTemporaryScreenAutoBrightnessAdjustmentSettingOverride);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .DOZE_SCREEN_STATE_OVERRIDE_FROM_DREAM_MANAGER,
+ mDozeScreenStateOverrideFromDreamManager);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .DOZED_SCREEN_BRIGHTNESS_OVERRIDE_FROM_DREAM_MANAGER,
+ mDozeScreenBrightnessOverrideFromDreamManager);
+
+ final long screenBrightnessSettingLimitsToken =
+ proto.start(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .SCREEN_BRIGHTNESS_SETTING_LIMITS);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.ScreenBrightnessSettingLimitsProto
+ .SETTING_MINIMUM,
+ mScreenBrightnessSettingMinimum);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.ScreenBrightnessSettingLimitsProto
+ .SETTING_MAXIMUM,
+ mScreenBrightnessSettingMaximum);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.ScreenBrightnessSettingLimitsProto
+ .SETTING_DEFAULT,
+ mScreenBrightnessSettingDefault);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.ScreenBrightnessSettingLimitsProto
+ .SETTING_FOR_VR_DEFAULT,
+ mScreenBrightnessForVrSettingDefault);
+ proto.end(screenBrightnessSettingLimitsToken);
+
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.SCREEN_BRIGHTNESS_FOR_VR_SETTING,
+ mScreenBrightnessForVrSetting);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.IS_DOUBLE_TAP_WAKE_ENABLED,
+ mDoubleTapWakeEnabled);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.IS_VR_MODE_ENABLED,
+ mIsVrModeEnabled);
+ proto.end(settingsAndConfigurationToken);
+
+ final int sleepTimeout = getSleepTimeoutLocked();
+ final int screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);
+ final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
+ proto.write(PowerServiceDumpProto.SLEEP_TIMEOUT_MS, sleepTimeout);
+ proto.write(PowerServiceDumpProto.SCREEN_OFF_TIMEOUT_MS, screenOffTimeout);
+ proto.write(PowerServiceDumpProto.SCREEN_DIM_DURATION_MS, screenDimDuration);
+ proto.write(PowerServiceDumpProto.ARE_UIDS_CHANGING, mUidsChanging);
+ proto.write(PowerServiceDumpProto.ARE_UIDS_CHANGED, mUidsChanged);
+
+ for (int i = 0; i < mUidState.size(); i++) {
+ final UidState state = mUidState.valueAt(i);
+ final long uIDToken = proto.start(PowerServiceDumpProto.UIDS);
+ final int uid = mUidState.keyAt(i);
+ proto.write(PowerServiceDumpProto.UidProto.UID, uid);
+ proto.write(PowerServiceDumpProto.UidProto.UID_STRING, UserHandle.formatUid(uid));
+ proto.write(PowerServiceDumpProto.UidProto.IS_ACTIVE, state.mActive);
+ proto.write(PowerServiceDumpProto.UidProto.NUM_WAKE_LOCKS, state.mNumWakeLocks);
+ if (state.mProcState == ActivityManager.PROCESS_STATE_UNKNOWN) {
+ proto.write(PowerServiceDumpProto.UidProto.IS_PROCESS_STATE_UNKNOWN, true);
+ } else {
+ proto.write(PowerServiceDumpProto.UidProto.PROCESS_STATE, state.mProcState);
+ }
+ proto.end(uIDToken);
+ }
+
+ mHandler.getLooper().writeToProto(proto, PowerServiceDumpProto.LOOPER);
+
+ for (WakeLock wl : mWakeLocks) {
+ wl.writeToProto(proto, PowerServiceDumpProto.WAKE_LOCKS);
+ }
+
+ for (SuspendBlocker sb : mSuspendBlockers) {
+ sb.writeToProto(proto, PowerServiceDumpProto.SUSPEND_BLOCKERS);
+ }
+ wcd = mWirelessChargerDetector;
+ }
+
+ if (wcd != null) {
+ wcd.writeToProto(proto, PowerServiceDumpProto.WIRELESS_CHARGER_DETECTOR);
+ }
+ proto.flush();
+ }
+
private SuspendBlocker createSuspendBlockerLocked(String name) {
SuspendBlocker suspendBlocker = new SuspendBlockerImpl(name);
mSuspendBlockers.add(suspendBlocker);
@@ -3471,6 +3828,32 @@
return sb.toString();
}
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long wakeLockToken = proto.start(fieldId);
+ proto.write(WakeLockProto.LOCK_LEVEL, (mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK));
+ proto.write(WakeLockProto.TAG, mTag);
+
+ final long wakeLockFlagsToken = proto.start(WakeLockProto.FLAGS);
+ proto.write(WakeLockProto.WakeLockFlagsProto.IS_ACQUIRE_CAUSES_WAKEUP,
+ (mFlags & PowerManager.ACQUIRE_CAUSES_WAKEUP)!=0);
+ proto.write(WakeLockProto.WakeLockFlagsProto.IS_ON_AFTER_RELEASE,
+ (mFlags & PowerManager.ON_AFTER_RELEASE)!=0);
+ proto.end(wakeLockFlagsToken);
+
+ proto.write(WakeLockProto.IS_DISABLED, mDisabled);
+ if (mNotifiedAcquired) {
+ proto.write(WakeLockProto.ACQ_MS, mAcquireTime);
+ }
+ proto.write(WakeLockProto.IS_NOTIFIED_LONG, mNotifiedLong);
+ proto.write(WakeLockProto.UID, mOwnerUid);
+ proto.write(WakeLockProto.PID, mOwnerPid);
+
+ if (mWorkSource != null) {
+ mWorkSource.writeToProto(proto, WakeLockProto.WORK_SOURCE);
+ }
+ proto.end(wakeLockToken);
+ }
+
@SuppressWarnings("deprecation")
private String getLockLevelString() {
switch (mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
@@ -3568,6 +3951,15 @@
return mName + ": ref count=" + mReferenceCount;
}
}
+
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long sbToken = proto.start(fieldId);
+ synchronized (this) {
+ proto.write(SuspendBlockerProto.NAME, mName);
+ proto.write(SuspendBlockerProto.REFERENCE_COUNT, mReferenceCount);
+ }
+ proto.end(sbToken);
+ }
}
static final class UidState {
@@ -4055,8 +4447,19 @@
}
final long ident = Binder.clearCallingIdentity();
+
+ boolean isDumpProto = false;
+ for (String arg : args) {
+ if (arg.equals("--proto")) {
+ isDumpProto = true;
+ }
+ }
try {
- dumpInternal(pw);
+ if (isDumpProto) {
+ dumpProto(fd);
+ } else {
+ dumpInternal(pw);
+ }
} finally {
Binder.restoreCallingIdentity(ident);
}
diff --git a/services/core/java/com/android/server/power/SuspendBlocker.java b/services/core/java/com/android/server/power/SuspendBlocker.java
index 70b278a..30b35f0 100644
--- a/services/core/java/com/android/server/power/SuspendBlocker.java
+++ b/services/core/java/com/android/server/power/SuspendBlocker.java
@@ -16,6 +16,8 @@
package com.android.server.power;
+import android.util.proto.ProtoOutputStream;
+
/**
* Low-level suspend blocker mechanism equivalent to holding a partial wake lock.
*
@@ -40,4 +42,6 @@
* The system may crash.
*/
void release();
+
+ void writeToProto(ProtoOutputStream proto, long fieldId);
}
diff --git a/services/core/java/com/android/server/power/WirelessChargerDetector.java b/services/core/java/com/android/server/power/WirelessChargerDetector.java
index 38f5d77..6ee9dcd 100644
--- a/services/core/java/com/android/server/power/WirelessChargerDetector.java
+++ b/services/core/java/com/android/server/power/WirelessChargerDetector.java
@@ -24,8 +24,10 @@
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
+import android.service.power.WirelessChargerDetectorProto;
import android.util.Slog;
import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
import java.io.PrintWriter;
@@ -170,6 +172,44 @@
}
}
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long wcdToken = proto.start(fieldId);
+ synchronized (mLock) {
+ proto.write(WirelessChargerDetectorProto.IS_POWERED_WIRELESSLY, mPoweredWirelessly);
+ proto.write(WirelessChargerDetectorProto.IS_AT_REST, mAtRest);
+
+ final long restVectorToken = proto.start(WirelessChargerDetectorProto.REST);
+ proto.write(WirelessChargerDetectorProto.VectorProto.X, mRestX);
+ proto.write(WirelessChargerDetectorProto.VectorProto.Y, mRestY);
+ proto.write(WirelessChargerDetectorProto.VectorProto.Z, mRestZ);
+ proto.end(restVectorToken);
+
+ proto.write(
+ WirelessChargerDetectorProto.IS_DETECTION_IN_PROGRESS, mDetectionInProgress);
+ proto.write(WirelessChargerDetectorProto.DETECTION_START_TIME_MS, mDetectionStartTime);
+ proto.write(
+ WirelessChargerDetectorProto.IS_MUST_UPDATE_REST_POSITION,
+ mMustUpdateRestPosition);
+ proto.write(WirelessChargerDetectorProto.TOTAL_SAMPLES, mTotalSamples);
+ proto.write(WirelessChargerDetectorProto.MOVING_SAMPLES, mMovingSamples);
+
+ final long firstSampleVectorToken =
+ proto.start(WirelessChargerDetectorProto.FIRST_SAMPLE);
+ proto.write(WirelessChargerDetectorProto.VectorProto.X, mFirstSampleX);
+ proto.write(WirelessChargerDetectorProto.VectorProto.Y, mFirstSampleY);
+ proto.write(WirelessChargerDetectorProto.VectorProto.Z, mFirstSampleZ);
+ proto.end(firstSampleVectorToken);
+
+ final long lastSampleVectorToken =
+ proto.start(WirelessChargerDetectorProto.LAST_SAMPLE);
+ proto.write(WirelessChargerDetectorProto.VectorProto.X, mLastSampleX);
+ proto.write(WirelessChargerDetectorProto.VectorProto.Y, mLastSampleY);
+ proto.write(WirelessChargerDetectorProto.VectorProto.Z, mLastSampleZ);
+ proto.end(lastSampleVectorToken);
+ }
+ proto.end(wcdToken);
+ }
+
/**
* Updates the charging state and returns true if docking was detected.
*
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 2b74f84..5041138 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -19,6 +19,7 @@
import static android.app.ActivityManager.ENABLE_TASK_SNAPSHOTS;
import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.app.ActivityManager.StackId;
import android.app.ActivityManager.TaskSnapshot;
import android.graphics.GraphicBuffer;
@@ -65,26 +66,22 @@
}
void onTransitionStarting() {
- if (!ENABLE_TASK_SNAPSHOTS) {
- return;
- }
handleClosingApps(mService.mClosingApps);
}
-
/**
* Called when the visibility of an app changes outside of the regular app transition flow.
*/
void notifyAppVisibilityChanged(AppWindowToken appWindowToken, boolean visible) {
- if (!ENABLE_TASK_SNAPSHOTS) {
- return;
- }
if (!visible) {
handleClosingApps(Sets.newArraySet(appWindowToken));
}
}
private void handleClosingApps(ArraySet<AppWindowToken> closingApps) {
+ if (!ENABLE_TASK_SNAPSHOTS || ActivityManager.isLowRamDeviceStatic()) {
+ return;
+ }
// We need to take a snapshot of the task if and only if all activities of the task are
// either closing or hidden.
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 4c89705..20b70a6 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -1036,7 +1036,7 @@
}
// TODO(b/31632518)
- gnssHal = IGnss::getService("gnss");
+ gnssHal = IGnss::getService();
if (gnssHal != nullptr) {
auto gnssXtra = gnssHal->getExtensionXtra();
if (!gnssXtra.isOk()) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 620d441..7b6b941 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -41,6 +41,7 @@
import static android.app.admin.DevicePolicyManager.DELEGATION_PACKAGE_ACCESS;
import static android.app.admin.DevicePolicyManager.DELEGATION_PERMISSION_GRANT;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
+import static android.app.admin.DevicePolicyManager.PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER;
import static android.app.admin.DevicePolicyManager.WIPE_EXTERNAL_STORAGE;
import static android.app.admin.DevicePolicyManager.WIPE_RESET_PROTECTION_DATA;
import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
@@ -332,15 +333,6 @@
}
/**
- * Keyguard features that when set on a managed profile that doesn't have its own challenge will
- * affect the profile's parent user. These can also be set on the managed profile's parent DPM
- * instance.
- */
- private static final int PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER =
- DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS
- | DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT;
-
- /**
* Keyguard features that when set on a profile affect the profile content or challenge only.
* These cannot be set on the managed profile's parent DPM instance
*/
diff --git a/services/tests/notification/src/com/android/server/notification/BadgeExtractorTest.java b/services/tests/notification/src/com/android/server/notification/BadgeExtractorTest.java
index b26bac3..0cf4994 100644
--- a/services/tests/notification/src/com/android/server/notification/BadgeExtractorTest.java
+++ b/services/tests/notification/src/com/android/server/notification/BadgeExtractorTest.java
@@ -89,6 +89,7 @@
when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true);
NotificationChannel channel =
new NotificationChannel("a", "a", NotificationManager.IMPORTANCE_UNSPECIFIED);
+ when(mConfig.getNotificationChannel(mPkg, mUid, "a", false)).thenReturn(channel);
channel.setShowBadge(false);
NotificationRecord r = getNotificationRecord(channel);
@@ -107,6 +108,7 @@
NotificationChannel channel =
new NotificationChannel("a", "a", NotificationManager.IMPORTANCE_HIGH);
channel.setShowBadge(true);
+ when(mConfig.getNotificationChannel(mPkg, mUid, "a", false)).thenReturn(channel);
NotificationRecord r = getNotificationRecord(channel);
@@ -124,6 +126,7 @@
NotificationChannel channel =
new NotificationChannel("a", "a", NotificationManager.IMPORTANCE_UNSPECIFIED);
channel.setShowBadge(true);
+ when(mConfig.getNotificationChannel(mPkg, mUid, "a", false)).thenReturn(channel);
NotificationRecord r = getNotificationRecord(channel);
@@ -141,6 +144,7 @@
NotificationChannel channel =
new NotificationChannel("a", "a", NotificationManager.IMPORTANCE_UNSPECIFIED);
channel.setShowBadge(false);
+ when(mConfig.getNotificationChannel(mPkg, mUid, "a", false)).thenReturn(channel);
NotificationRecord r = getNotificationRecord(channel);
diff --git a/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java b/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java
index 69724f4..c5abba8 100644
--- a/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java
@@ -18,6 +18,7 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -27,6 +28,7 @@
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.support.test.InstrumentationRegistry;
@@ -71,8 +73,11 @@
public void testSnoozeForTime() throws Exception {
NotificationRecord r = getNotificationRecord("pkg", 1, "one", UserHandle.SYSTEM);
mSnoozeHelper.snooze(r, 1000);
+ ArgumentCaptor<Long> captor = ArgumentCaptor.forClass(Long.class);
verify(mAm, times(1)).setExactAndAllowWhileIdle(
- anyInt(), eq((long) 1000), any(PendingIntent.class));
+ anyInt(), captor.capture(), any(PendingIntent.class));
+ long actualSnoozedUntilDuration = captor.getValue() - SystemClock.elapsedRealtime();
+ assertTrue(Math.abs(actualSnoozedUntilDuration - 1000) < 2);
assertTrue(mSnoozeHelper.isSnoozed(
UserHandle.USER_SYSTEM, r.sbn.getPackageName(), r.getKey()));
}
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
index 665f01f..4141f2f 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
@@ -56,8 +56,7 @@
import android.net.INetworkScoreCache;
import android.net.NetworkKey;
import android.net.NetworkScoreManager;
-import android.net.NetworkScorerAppManager;
-import android.net.NetworkScorerAppManager.NetworkScorerAppData;
+import android.net.NetworkScorerAppData;
import android.net.RecommendationRequest;
import android.net.RecommendationResult;
import android.net.ScoredNetwork;
@@ -201,10 +200,10 @@
}
@Test
- public void testSystemRunning() {
+ public void testOnUserUnlocked() {
when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
- mNetworkScoreService.systemRunning();
+ mNetworkScoreService.onUserUnlocked(0);
verify(mContext).bindServiceAsUser(MockUtils.checkIntent(
new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS)
@@ -549,9 +548,9 @@
}
@Test
- public void testSetActiveScorer_noScoreNetworksPermission() {
- doThrow(new SecurityException()).when(mContext)
- .enforceCallingOrSelfPermission(eq(permission.SCORE_NETWORKS), anyString());
+ public void testSetActiveScorer_noRequestNetworkScoresPermission() {
+ when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
+ .thenReturn(PackageManager.PERMISSION_DENIED);
try {
mNetworkScoreService.setActiveScorer(null);
@@ -630,7 +629,7 @@
@Test
public void testIsCallerActiveScorer_noBoundService() throws Exception {
- mNetworkScoreService.systemRunning();
+ mNetworkScoreService.onUserUnlocked(0);
assertFalse(mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid()));
}
@@ -651,7 +650,7 @@
@Test
public void testGetActiveScorerPackage_notActive() throws Exception {
- mNetworkScoreService.systemRunning();
+ mNetworkScoreService.onUserUnlocked(0);
assertNull(mNetworkScoreService.getActiveScorerPackage());
}
@@ -659,7 +658,7 @@
@Test
public void testGetActiveScorerPackage_active() throws Exception {
when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
- mNetworkScoreService.systemRunning();
+ mNetworkScoreService.onUserUnlocked(0);
assertEquals(NEW_SCORER.getRecommendationServicePackageName(),
mNetworkScoreService.getActiveScorerPackage());
@@ -960,7 +959,7 @@
return true;
}
});
- mNetworkScoreService.systemRunning();
+ mNetworkScoreService.onUserUnlocked(0);
}
private void bindToScorer(boolean callerIsScorer) {
@@ -974,7 +973,7 @@
when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(appData);
when(mContext.bindServiceAsUser(isA(Intent.class), isA(ServiceConnection.class), anyInt(),
isA(UserHandle.class))).thenReturn(true);
- mNetworkScoreService.systemRunning();
+ mNetworkScoreService.onUserUnlocked(0);
}
private static class OnResultListener implements RemoteCallback.OnResultListener {
diff --git a/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java b/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
similarity index 61%
rename from core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
rename to services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
index 347024d..e9a2d34 100644
--- a/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
@@ -14,13 +14,22 @@
* limitations under the License
*/
-package android.net;
+package com.android.server;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+
+import static org.junit.Assert.assertFalse;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.Manifest.permission;
import android.content.ComponentName;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@@ -29,144 +38,84 @@
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.res.Resources;
-import android.net.NetworkScorerAppManager.NetworkScorerAppData;
+import android.net.NetworkScoreManager;
+import android.net.NetworkScorerAppData;
import android.os.Bundle;
import android.provider.Settings;
-import android.test.InstrumentationTestCase;
+import android.support.test.runner.AndroidJUnit4;
import com.android.internal.R;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+import java.util.ArrayList;
import java.util.List;
-public class NetworkScorerAppManagerTest extends InstrumentationTestCase {
+@RunWith(AndroidJUnit4.class)
+public class NetworkScorerAppManagerTest {
@Mock private Context mMockContext;
@Mock private PackageManager mMockPm;
@Mock private Resources mResources;
- @Mock private ContentResolver mContentResolver;
- private Context mTargetContext;
+ @Mock private NetworkScorerAppManager.SettingsFacade mSettingsFacade;
private NetworkScorerAppManager mNetworkScorerAppManager;
+ private List<ResolveInfo> mAvailableServices;
- @Override
+ @Before
public void setUp() throws Exception {
- super.setUp();
-
- // Configuration needed to make mockito/dexcache work.
- mTargetContext = getInstrumentation().getTargetContext();
- System.setProperty("dexmaker.dexcache", mTargetContext.getCacheDir().getPath());
- ClassLoader newClassLoader = getInstrumentation().getClass().getClassLoader();
- Thread.currentThread().setContextClassLoader(newClassLoader);
-
MockitoAnnotations.initMocks(this);
+ mAvailableServices = new ArrayList<>();
when(mMockContext.getPackageManager()).thenReturn(mMockPm);
+ when(mMockPm.queryIntentServices(Mockito.argThat(new ArgumentMatcher<Intent>() {
+ @Override
+ public boolean matches(Object object) {
+ Intent intent = (Intent) object;
+ return NetworkScoreManager.ACTION_RECOMMEND_NETWORKS.equals(intent.getAction());
+ }
+ }), eq(PackageManager.GET_META_DATA))).thenReturn(mAvailableServices);
when(mMockContext.getResources()).thenReturn(mResources);
- when(mMockContext.getContentResolver()).thenReturn(mTargetContext.getContentResolver());
- mNetworkScorerAppManager = new NetworkScorerAppManager(mMockContext);
+
+ mNetworkScorerAppManager = new NetworkScorerAppManager(mMockContext, mSettingsFacade);
}
- public void testGetPotentialRecommendationProviderPackages_emptyConfig() throws Exception {
- setNetworkRecommendationPackageNames(/*no configured packages*/);
- assertTrue(mNetworkScorerAppManager.getPotentialRecommendationProviderPackages().isEmpty());
- }
-
- public void testGetPotentialRecommendationProviderPackages_permissionNotGranted()
- throws Exception {
- setNetworkRecommendationPackageNames("package1");
- mockScoreNetworksDenied("package1");
-
- assertTrue(mNetworkScorerAppManager.getPotentialRecommendationProviderPackages().isEmpty());
- }
-
- public void testGetPotentialRecommendationProviderPackages_permissionGranted()
- throws Exception {
- setNetworkRecommendationPackageNames("package1");
- mockScoreNetworksGranted("package1");
-
- List<String> potentialProviderPackages =
- mNetworkScorerAppManager.getPotentialRecommendationProviderPackages();
-
- assertFalse(potentialProviderPackages.isEmpty());
- assertEquals("package1", potentialProviderPackages.get(0));
- }
-
- public void testGetPotentialRecommendationProviderPackages_multipleConfigured()
- throws Exception {
- setNetworkRecommendationPackageNames("package1", "package2");
- mockScoreNetworksDenied("package1");
- mockScoreNetworksGranted("package2");
-
- List<String> potentialProviderPackages =
- mNetworkScorerAppManager.getPotentialRecommendationProviderPackages();
-
- assertEquals(1, potentialProviderPackages.size());
- assertEquals("package2", potentialProviderPackages.get(0));
- }
-
- public void testGetNetworkRecommendationProviderData_noPotentialPackages() throws Exception {
- setNetworkRecommendationPackageNames(/*no configured packages*/);
- assertNull(mNetworkScorerAppManager.getNetworkRecommendationProviderData());
- }
-
- public void testGetNetworkRecommendationProviderData_serviceMissing() throws Exception {
- setNetworkRecommendationPackageNames("package1");
- mockScoreNetworksGranted("package1");
-
- assertNull(mNetworkScorerAppManager.getNetworkRecommendationProviderData());
- }
-
- public void testGetNetworkRecommendationProviderData_scoreNetworksNotGranted()
- throws Exception {
- final ComponentName recoComponent = new ComponentName("package1", "class1");
- setNetworkRecommendationPackageNames(recoComponent.getPackageName());
- mockScoreNetworksDenied(recoComponent.getPackageName());
- mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */);
-
- assertNull(mNetworkScorerAppManager.getNetworkRecommendationProviderData());
- }
-
- public void testGetNetworkRecommendationProviderData_available() throws Exception {
- final ComponentName recoComponent = new ComponentName("package1", "class1");
- setNetworkRecommendationPackageNames(recoComponent.getPackageName());
- mockScoreNetworksGranted(recoComponent.getPackageName());
- mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */);
-
- NetworkScorerAppData appData =
- mNetworkScorerAppManager.getNetworkRecommendationProviderData();
- assertNotNull(appData);
- assertEquals(recoComponent, appData.getRecommendationServiceComponent());
- assertEquals(924, appData.packageUid);
- }
-
+ @Test
public void testGetActiveScorer_providerAvailable() throws Exception {
final ComponentName recoComponent = new ComponentName("package1", "class1");
- setNetworkRecommendationPackageNames(recoComponent.getPackageName());
+ setNetworkRecoPackageSetting(recoComponent.getPackageName());
mockScoreNetworksGranted(recoComponent.getPackageName());
mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */);
- ContentResolver cr = mTargetContext.getContentResolver();
- Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 1);
-
final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
assertNotNull(activeScorer);
assertEquals(recoComponent, activeScorer.getRecommendationServiceComponent());
assertEquals(924, activeScorer.packageUid);
}
+ @Test
+ public void testGetActiveScorer_permissionMissing() throws Exception {
+ final ComponentName recoComponent = new ComponentName("package1", "class1");
+ setNetworkRecoPackageSetting(recoComponent.getPackageName());
+ mockScoreNetworksDenied(recoComponent.getPackageName());
+ mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */);
+
+ final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
+ assertNull(activeScorer);
+ }
+
+ @Test
public void testGetActiveScorer_providerAvailable_enableUseOpenWifiActivityNotSet()
throws Exception {
final ComponentName recoComponent = new ComponentName("package1", "class1");
- setNetworkRecommendationPackageNames(recoComponent.getPackageName());
+ setNetworkRecoPackageSetting(recoComponent.getPackageName());
mockScoreNetworksGranted(recoComponent.getPackageName());
mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
null /* enableUseOpenWifiPackageActivityPackage*/);
- ContentResolver cr = mTargetContext.getContentResolver();
- Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 1);
-
final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
assertNotNull(activeScorer);
assertEquals(recoComponent, activeScorer.getRecommendationServiceComponent());
@@ -174,17 +123,15 @@
assertNull(activeScorer.getEnableUseOpenWifiActivity());
}
+ @Test
public void testGetActiveScorer_providerAvailable_enableUseOpenWifiActivityNotResolved()
throws Exception {
final ComponentName recoComponent = new ComponentName("package1", "class1");
- setNetworkRecommendationPackageNames(recoComponent.getPackageName());
+ setNetworkRecoPackageSetting(recoComponent.getPackageName());
mockScoreNetworksGranted(recoComponent.getPackageName());
mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
"package2" /* enableUseOpenWifiPackageActivityPackage*/);
- ContentResolver cr = mTargetContext.getContentResolver();
- Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 1);
-
final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
assertNotNull(activeScorer);
assertEquals(recoComponent, activeScorer.getRecommendationServiceComponent());
@@ -192,19 +139,17 @@
assertNull(activeScorer.getEnableUseOpenWifiActivity());
}
+ @Test
public void testGetActiveScorer_providerAvailable_enableUseOpenWifiActivityResolved()
throws Exception {
final ComponentName recoComponent = new ComponentName("package1", "class1");
final ComponentName enableUseOpenWifiComponent = new ComponentName("package2", "class2");
- setNetworkRecommendationPackageNames(recoComponent.getPackageName());
+ setNetworkRecoPackageSetting(recoComponent.getPackageName());
mockScoreNetworksGranted(recoComponent.getPackageName());
mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
enableUseOpenWifiComponent.getPackageName());
mockEnableUseOpenWifiActivity(enableUseOpenWifiComponent);
- ContentResolver cr = mTargetContext.getContentResolver();
- Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 1);
-
final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
assertNotNull(activeScorer);
assertEquals(recoComponent, activeScorer.getRecommendationServiceComponent());
@@ -212,33 +157,105 @@
assertEquals(enableUseOpenWifiComponent, activeScorer.getEnableUseOpenWifiActivity());
}
- public void testGetActiveScorer_providerNotAvailable()
+ @Test
+ public void testGetActiveScorer_packageSettingIsNull()
throws Exception {
- ContentResolver cr = mTargetContext.getContentResolver();
- Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 1);
+ // NETWORK_RECOMMENDATIONS_PACKAGE is null
final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
assertNull(activeScorer);
}
- public void testGetActiveScorer_recommendationsDisabled() throws Exception {
+ @Test
+ public void testGetActiveScorer_packageSettingIsInvalid() throws Exception {
final ComponentName recoComponent = new ComponentName("package1", "class1");
- setNetworkRecommendationPackageNames(recoComponent.getPackageName());
+ setDefaultNetworkRecommendationPackage(recoComponent.getPackageName());
mockScoreNetworksGranted(recoComponent.getPackageName());
- mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */);
- ContentResolver cr = mTargetContext.getContentResolver();
- Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0);
+ // NETWORK_RECOMMENDATIONS_PACKAGE is set to a package that isn't a recommender.
final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
assertNull(activeScorer);
}
- private void setNetworkRecommendationPackageNames(String... names) {
- if (names == null) {
- names = new String[0];
- }
- when(mResources.getStringArray(R.array.config_networkRecommendationPackageNames))
- .thenReturn(names);
+ @Test
+ public void testSetActiveScorer_noChange() throws Exception {
+ String packageName = "package";
+ setNetworkRecoPackageSetting(packageName);
+
+ assertTrue(mNetworkScorerAppManager.setActiveScorer(packageName));
+ verify(mSettingsFacade, never()).putString(any(), any(), any());
+ }
+
+ @Test
+ public void testSetActiveScorer_nullPackage() throws Exception {
+ String packageName = "package";
+ String defaultPackage = "defaultPackage";
+ setNetworkRecoPackageSetting(packageName);
+ setDefaultNetworkRecommendationPackage(defaultPackage);
+
+ assertTrue(mNetworkScorerAppManager.setActiveScorer(null));
+ verify(mSettingsFacade).putString(mMockContext,
+ Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, defaultPackage);
+ }
+
+ @Test
+ public void testSetActiveScorer_validPackage() throws Exception {
+ String packageName = "package";
+ String newPackage = "newPackage";
+ setNetworkRecoPackageSetting(packageName);
+ final ComponentName recoComponent = new ComponentName(newPackage, "class1");
+ mockScoreNetworksGranted(recoComponent.getPackageName());
+ mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */, null);
+
+ assertTrue(mNetworkScorerAppManager.setActiveScorer(newPackage));
+ verify(mSettingsFacade).putString(mMockContext,
+ Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, newPackage);
+ }
+
+ @Test
+ public void testSetActiveScorer_invalidPackage() throws Exception {
+ String packageName = "package";
+ String newPackage = "newPackage";
+ setNetworkRecoPackageSetting(packageName);
+ // newPackage doesn't resolve to a valid recommender
+
+ assertFalse(mNetworkScorerAppManager.setActiveScorer(newPackage));
+ verify(mSettingsFacade, never()).putString(any(), any(), any());
+ }
+
+
+ @Test
+ public void testRevertToDefaultIfNoActive_notActive() throws Exception {
+ String defaultPackage = "defaultPackage";
+ setDefaultNetworkRecommendationPackage(defaultPackage);
+
+ mNetworkScorerAppManager.revertToDefaultIfNoActive();
+
+ verify(mSettingsFacade).putString(mMockContext,
+ Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, defaultPackage);
+ }
+
+ @Test
+ public void testRevertToDefaultIfNoActive_active() throws Exception {
+ String packageName = "package";
+ setNetworkRecoPackageSetting(packageName);
+ final ComponentName recoComponent = new ComponentName(packageName, "class1");
+ mockScoreNetworksGranted(recoComponent.getPackageName());
+ mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */, null);
+
+ mNetworkScorerAppManager.revertToDefaultIfNoActive();
+
+ verify(mSettingsFacade, never()).putString(any(), any(), any());
+ }
+
+ private void setNetworkRecoPackageSetting(String packageName) {
+ when(mSettingsFacade.getString(mMockContext,
+ Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE)).thenReturn(packageName);
+ }
+
+ private void setDefaultNetworkRecommendationPackage(String name) {
+ when(mResources.getString(R.string.config_defaultNetworkRecommendationProviderPackage))
+ .thenReturn(name);
}
private void mockScoreNetworksGranted(String packageName) {
@@ -281,6 +298,8 @@
&& compName.getPackageName().equals(intent.getPackage());
}
}), Mockito.eq(flags))).thenReturn(serviceInfo);
+
+ mAvailableServices.add(serviceInfo);
}
private void mockEnableUseOpenWifiActivity(final ComponentName useOpenWifiComp) {
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index dd03305..afff6d5 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -208,7 +208,9 @@
*
* @see #onOemHookRawEvent
* @hide
+ * @deprecated OEM needs a vendor-extension hal and their apps should use that instead
*/
+ @Deprecated
public static final int LISTEN_OEM_HOOK_RAW_EVENT = 0x00008000;
/**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index a4235d7..f5974cd 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -5229,7 +5229,9 @@
* 0 request was handled succesfully, but no response data
* positive value success, data length of response
* @hide
+ * @deprecated OEM needs a vendor-extension hal and their apps should use that instead
*/
+ @Deprecated
public int invokeOemRilRequestRaw(byte[] oemReq, byte[] oemResp) {
try {
ITelephony telephony = getITelephony();
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index d40835b..dc8dfba 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -264,15 +264,6 @@
= "android.intent.action.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS";
/**
- * Activity Action: Start this activity to invoke the carrier setup app.
- * The carrier app must be signed using a certificate that matches the UICC access rules.
- *
- * <p class="note">Callers of this should hold the android.permission.INVOKE_CARRIER_SETUP
- * permission.</p>
- */
- public static final String ACTION_CARRIER_SETUP = "android.intent.action.ACTION_CARRIER_SETUP";
-
- /**
* <p>Broadcast Action: Indicates that the action is forbidden by network.
* <p class="note">
* This is for the OEM applications to understand about possible provisioning issues.
diff --git a/tests/SoundTriggerTestApp/res/layout/main.xml b/tests/SoundTriggerTestApp/res/layout/main.xml
index 0fd8b12..2c6c8d7 100644
--- a/tests/SoundTriggerTestApp/res/layout/main.xml
+++ b/tests/SoundTriggerTestApp/res/layout/main.xml
@@ -87,6 +87,7 @@
android:text="@string/capture"
android:id="@+id/caputre_check_box"
android:layout_gravity="center_horizontal"
+ android:onClick="onCaptureAudioCheckboxClicked"
android:padding="20dp" />
<Button
@@ -94,6 +95,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/play_capture"
+ android:onClick="onPlayCapturedAudioButtonClicked"
android:padding="20dp"
android:enabled="false" />
</LinearLayout>
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
index 56aad23..9b1a9f2 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
@@ -297,6 +297,7 @@
Notification n = new Notification.Builder(NotificationTestList.this)
.setSmallIcon(R.drawable.icon2)
.setContentTitle("Low priority")
+ .setTimeout(60000)
.setLights(0xff0000ff, 1, 0)
.setPriority(Notification.PRIORITY_LOW)
.build();