Merge "Revert "UsbDeviceManager: fix b/21429947 regression"" into mnc-dev
diff --git a/api/current.txt b/api/current.txt
index 741ff9b..462ca0a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -66,6 +66,7 @@
field public static final java.lang.String FACTORY_TEST = "android.permission.FACTORY_TEST";
field public static final java.lang.String FLASHLIGHT = "android.permission.FLASHLIGHT";
field public static final java.lang.String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS";
+ field public static final java.lang.String GET_ACCOUNTS_PRIVILEGED = "android.permission.GET_ACCOUNTS_PRIVILEGED";
field public static final java.lang.String GET_PACKAGE_SIZE = "android.permission.GET_PACKAGE_SIZE";
field public static final deprecated java.lang.String GET_TASKS = "android.permission.GET_TASKS";
field public static final java.lang.String GLOBAL_SEARCH = "android.permission.GLOBAL_SEARCH";
diff --git a/api/system-current.txt b/api/system-current.txt
index 4c2d7b1..d6e3c03 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -95,6 +95,7 @@
field public static final java.lang.String FORCE_BACK = "android.permission.FORCE_BACK";
field public static final java.lang.String FORCE_STOP_PACKAGES = "android.permission.FORCE_STOP_PACKAGES";
field public static final java.lang.String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS";
+ field public static final java.lang.String GET_ACCOUNTS_PRIVILEGED = "android.permission.GET_ACCOUNTS_PRIVILEGED";
field public static final java.lang.String GET_APP_OPS_STATS = "android.permission.GET_APP_OPS_STATS";
field public static final java.lang.String GET_PACKAGE_IMPORTANCE = "android.permission.GET_PACKAGE_IMPORTANCE";
field public static final java.lang.String GET_PACKAGE_SIZE = "android.permission.GET_PACKAGE_SIZE";
diff --git a/cmds/sm/src/com/android/commands/sm/Sm.java b/cmds/sm/src/com/android/commands/sm/Sm.java
index 0dad4dc..0a1ba4d1 100644
--- a/cmds/sm/src/com/android/commands/sm/Sm.java
+++ b/cmds/sm/src/com/android/commands/sm/Sm.java
@@ -81,6 +81,8 @@
runUnmount();
} else if ("format".equals(op)) {
runFormat();
+ } else if ("benchmark".equals(op)) {
+ runBenchmark();
} else if ("forget".equals(op)) {
runForget();
} else {
@@ -89,9 +91,12 @@
}
public void runListDisks() throws RemoteException {
+ final boolean onlyAdoptable = "adoptable".equals(nextArg());
final DiskInfo[] disks = mSm.getDisks();
for (DiskInfo disk : disks) {
- System.out.println(disk.getId());
+ if (!onlyAdoptable || disk.isAdoptable()) {
+ System.out.println(disk.getId());
+ }
}
}
@@ -161,6 +166,11 @@
mSm.format(volId);
}
+ public void runBenchmark() throws RemoteException {
+ final String volId = nextArg();
+ mSm.benchmark(volId);
+ }
+
public void runForget() throws RemoteException{
final String fsUuid = nextArg();
if ("all".equals(fsUuid)) {
@@ -180,7 +190,7 @@
}
private static int showUsage() {
- System.err.println("usage: sm list-disks");
+ System.err.println("usage: sm list-disks [adoptable]");
System.err.println(" sm list-volumes [public|private|emulated|all]");
System.err.println(" sm has-adoptable");
System.err.println(" sm get-primary-storage-uuid");
@@ -190,6 +200,7 @@
System.err.println(" sm mount VOLUME");
System.err.println(" sm unmount VOLUME");
System.err.println(" sm format VOLUME");
+ System.err.println(" sm benchmark VOLUME");
System.err.println("");
System.err.println(" sm forget [UUID|all]");
System.err.println("");
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 40126d6..ee0fc91 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -4,6 +4,7 @@
import android.content.ComponentName;
import android.graphics.Matrix;
import android.graphics.Rect;
+import android.os.BadParcelableException;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
@@ -31,8 +32,12 @@
static final String TAG = "AssistStructure";
static final boolean DEBUG_PARCEL = false;
+ static final boolean DEBUG_PARCEL_CHILDREN = false;
static final boolean DEBUG_PARCEL_TREE = false;
+ static final int VALIDATE_WINDOW_TOKEN = 0x11111111;
+ static final int VALIDATE_VIEW_TOKEN = 0x22222222;
+
boolean mHaveData;
ComponentName mActivityComponent;
@@ -173,6 +178,26 @@
mCurViewStackEntry = entry;
}
+ void writeView(ViewNode child, Parcel out, PooledStringWriter pwriter, int levelAdj) {
+ if (DEBUG_PARCEL) Log.d(TAG, "write view: at " + out.dataPosition()
+ + ", windows=" + mNumWrittenWindows
+ + ", views=" + mNumWrittenViews
+ + ", level=" + (mCurViewStackPos+levelAdj));
+ out.writeInt(VALIDATE_VIEW_TOKEN);
+ int flags = child.writeSelfToParcel(out, pwriter, mTmpMatrix);
+ mNumWrittenViews++;
+ // If the child has children, push it on the stack to write them next.
+ if ((flags&ViewNode.FLAGS_HAS_CHILDREN) != 0) {
+ if (DEBUG_PARCEL_TREE || DEBUG_PARCEL_CHILDREN) Log.d(TAG,
+ "Preparing to write " + child.mChildren.length
+ + " children: @ #" + mNumWrittenViews
+ + ", level " + (mCurViewStackPos+levelAdj));
+ out.writeInt(child.mChildren.length);
+ int pos = ++mCurViewStackPos;
+ pushViewStackEntry(child, pos);
+ }
+ }
+
boolean writeNextEntryToParcel(AssistStructure as, Parcel out, PooledStringWriter pwriter) {
// Write next view node if appropriate.
if (mCurViewStackEntry != null) {
@@ -182,20 +207,7 @@
+ mCurViewStackEntry.curChild + " in " + mCurViewStackEntry.node);
ViewNode child = mCurViewStackEntry.node.mChildren[mCurViewStackEntry.curChild];
mCurViewStackEntry.curChild++;
- if (DEBUG_PARCEL) Log.d(TAG, "write view: at " + out.dataPosition()
- + ", windows=" + mNumWrittenWindows
- + ", views=" + mNumWrittenViews);
- out.writeInt(1);
- int flags = child.writeSelfToParcel(out, pwriter, mTmpMatrix);
- mNumWrittenViews++;
- // If the child has children, push it on the stack to write them next.
- if ((flags&ViewNode.FLAGS_HAS_CHILDREN) != 0) {
- if (DEBUG_PARCEL_TREE) Log.d(TAG, "Preparing to write "
- + child.mChildren.length + " children under " + child);
- out.writeInt(child.mChildren.length);
- int pos = ++mCurViewStackPos;
- pushViewStackEntry(child, pos);
- }
+ writeView(child, out, pwriter, 1);
return true;
}
@@ -223,13 +235,13 @@
if (DEBUG_PARCEL) Log.d(TAG, "write window #" + pos + ": at " + out.dataPosition()
+ ", windows=" + mNumWrittenWindows
+ ", views=" + mNumWrittenViews);
- out.writeInt(1);
+ out.writeInt(VALIDATE_WINDOW_TOKEN);
win.writeSelfToParcel(out, pwriter, mTmpMatrix);
mNumWrittenWindows++;
ViewNode root = win.mRoot;
mCurViewStackPos = 0;
- if (DEBUG_PARCEL_TREE) Log.d(TAG, "Pushing initial root view " + root);
- pushViewStackEntry(root, 0);
+ if (DEBUG_PARCEL_TREE) Log.d(TAG, "Writing initial root view " + root);
+ writeView(root, out, pwriter, 0);
return true;
}
@@ -271,11 +283,16 @@
+ ", views=" + mNumReadViews);
}
- Parcel readParcel() {
+ Parcel readParcel(int validateToken, int level) {
if (DEBUG_PARCEL) Log.d(TAG, "readParcel: at " + mCurParcel.dataPosition()
+ ", avail=" + mCurParcel.dataAvail() + ", windows=" + mNumReadWindows
- + ", views=" + mNumReadViews);
- if (mCurParcel.readInt() != 0) {
+ + ", views=" + mNumReadViews + ", level=" + level);
+ int token = mCurParcel.readInt();
+ if (token != 0) {
+ if (token != validateToken) {
+ throw new BadParcelableException("Got token " + Integer.toHexString(token)
+ + ", expected token " + Integer.toHexString(validateToken));
+ }
return mCurParcel;
}
// We have run out of partial data, need to read another batch.
@@ -406,7 +423,7 @@
}
WindowNode(ParcelTransferReader reader) {
- Parcel in = reader.readParcel();
+ Parcel in = reader.readParcel(VALIDATE_WINDOW_TOKEN, 0);
reader.mNumReadWindows++;
mX = in.readInt();
mY = in.readInt();
@@ -414,7 +431,7 @@
mHeight = in.readInt();
mTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
mDisplayId = in.readInt();
- mRoot = new ViewNode(reader);
+ mRoot = new ViewNode(reader, 0);
}
void writeSelfToParcel(Parcel out, PooledStringWriter pwriter, float[] tmpMatrix) {
@@ -548,8 +565,8 @@
ViewNode() {
}
- ViewNode(ParcelTransferReader reader) {
- final Parcel in = reader.readParcel();
+ ViewNode(ParcelTransferReader reader, int nestingLevel) {
+ final Parcel in = reader.readParcel(VALIDATE_VIEW_TOKEN, nestingLevel);
reader.mNumReadViews++;
final PooledStringReader preader = reader.mStringReader;
mClassName = preader.readString();
@@ -604,9 +621,13 @@
}
if ((flags&FLAGS_HAS_CHILDREN) != 0) {
final int NCHILDREN = in.readInt();
+ if (DEBUG_PARCEL_TREE || DEBUG_PARCEL_CHILDREN) Log.d(TAG,
+ "Preparing to read " + NCHILDREN
+ + " children: @ #" + reader.mNumReadViews
+ + ", level " + nestingLevel);
mChildren = new ViewNode[NCHILDREN];
for (int i=0; i<NCHILDREN; i++) {
- mChildren[i] = new ViewNode(reader);
+ mChildren[i] = new ViewNode(reader, nestingLevel + 1);
}
}
}
diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
index e09ab56..2ba87744 100644
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java
@@ -79,6 +79,10 @@
* delivered through {@code callback}.
* <p>
* Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
+ * An app must hold
+ * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
+ * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission
+ * in order to get results.
*
* @param callback Callback used to deliver scan results.
* @throws IllegalArgumentException If {@code callback} is null.
@@ -95,6 +99,10 @@
* Start Bluetooth LE scan. The scan results will be delivered through {@code callback}.
* <p>
* Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
+ * An app must hold
+ * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
+ * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission
+ * in order to get results.
*
* @param filters {@link ScanFilter}s for finding exact BLE devices.
* @param settings Settings for the scan.
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 864225a..af4c2bc 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -16,6 +16,7 @@
package android.os;
+import android.annotation.NonNull;
import android.provider.DocumentsContract.Document;
import android.system.ErrnoException;
import android.system.Os;
@@ -69,6 +70,8 @@
/** Regular expression for safe filenames: no spaces or metacharacters */
private static final Pattern SAFE_FILENAME_PATTERN = Pattern.compile("[\\w%+,./=_-]+");
+ private static final File[] EMPTY = new File[0];
+
/**
* Set owner and mode of of given {@link File}.
*
@@ -634,4 +637,13 @@
return new File(parent, name + "." + ext);
}
}
+
+ public static @NonNull File[] listFilesOrEmpty(File dir) {
+ File[] res = dir.listFiles();
+ if (res != null) {
+ return res;
+ } else {
+ return EMPTY;
+ }
+ }
}
diff --git a/core/java/android/os/IDeviceIdleController.aidl b/core/java/android/os/IDeviceIdleController.aidl
index b768852..d3eec1e 100644
--- a/core/java/android/os/IDeviceIdleController.aidl
+++ b/core/java/android/os/IDeviceIdleController.aidl
@@ -29,5 +29,6 @@
boolean isPowerSaveWhitelistApp(String name);
void addPowerSaveTempWhitelistApp(String name, long duration, int userId, String reason);
long addPowerSaveTempWhitelistAppForMms(String name, int userId, String reason);
+ long addPowerSaveTempWhitelistAppForSms(String name, int userId, String reason);
void exitIdle(String reason);
}
diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java
index e3ce6f2..a12b15e 100644
--- a/core/java/android/widget/AppSecurityPermissions.java
+++ b/core/java/android/widget/AppSecurityPermissions.java
@@ -533,6 +533,12 @@
int existingReqFlags) {
final int base = pInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
final boolean isNormal = (base == PermissionInfo.PROTECTION_NORMAL);
+
+ // We do not show normal permissions in the UI.
+ if (isNormal) {
+ return false;
+ }
+
final boolean isDangerous = (base == PermissionInfo.PROTECTION_DANGEROUS)
|| ((pInfo.protectionLevel&PermissionInfo.PROTECTION_FLAG_PRE23) != 0);
final boolean isRequired =
@@ -546,7 +552,7 @@
// Dangerous and normal permissions are always shown to the user if the permission
// is required, or it was previously granted
- if ((isNormal || isDangerous) && (isRequired || wasGranted || isGranted)) {
+ if (isDangerous && (isRequired || wasGranted || isGranted)) {
return true;
}
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index dac02fa..6a561e6 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -731,7 +731,8 @@
// Negative values in a mySize value in RelativeLayout
// measurement is code for, "we got an unspecified mode in the
// RelativeLayout's measure spec."
- if (mySize < 0 && !mAllowBrokenMeasureSpecs) {
+ final boolean isUnspecified = mySize < 0;
+ if (isUnspecified && !mAllowBrokenMeasureSpecs) {
if (childStart != VALUE_NOT_SET && childEnd != VALUE_NOT_SET) {
// Constraints fixed both edges, so child has an exact size.
childSpecSize = Math.max(0, childEnd - childStart);
@@ -767,7 +768,7 @@
if (childStart != VALUE_NOT_SET && childEnd != VALUE_NOT_SET) {
// Constraints fixed both edges, so child must be an exact size.
- childSpecMode = MeasureSpec.EXACTLY;
+ childSpecMode = isUnspecified ? MeasureSpec.UNSPECIFIED : MeasureSpec.EXACTLY;
childSpecSize = Math.max(0, maxAvailable);
} else {
if (childSize >= 0) {
@@ -784,7 +785,7 @@
} else if (childSize == LayoutParams.MATCH_PARENT) {
// Child wanted to be as big as possible. Give all available
// space.
- childSpecMode = MeasureSpec.EXACTLY;
+ childSpecMode = isUnspecified ? MeasureSpec.UNSPECIFIED : MeasureSpec.EXACTLY;
childSpecSize = Math.max(0, maxAvailable);
} else if (childSize == LayoutParams.WRAP_CONTENT) {
// Child wants to wrap content. Use AT_MOST to communicate
diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java
index cbe535f..91ae27b 100644
--- a/core/java/com/android/internal/logging/MetricsLogger.java
+++ b/core/java/com/android/internal/logging/MetricsLogger.java
@@ -27,7 +27,20 @@
*/
public class MetricsLogger implements MetricsConstants {
// Temporary constants go here, to await migration to MetricsConstants.
- // next value is 227;
+ // next value is 238;
+
+ public static final int TUNER = 227;
+ public static final int TUNER_QS = 228;
+ public static final int TUNER_DEMO_MODE = 229;
+
+ public static final int TUNER_QS_REORDER = 230;
+ public static final int TUNER_QS_ADD = 231;
+ public static final int TUNER_QS_REMOVE = 232;
+ public static final int TUNER_STATUS_BAR_ENABLE = 233;
+ public static final int TUNER_STATUS_BAR_DISABLE = 234;
+ public static final int TUNER_DEMO_MODE_ENABLED = 235;
+ public static final int TUNER_DEMO_MODE_ON = 236;
+ public static final int TUNER_BATTERY_PERCENTAGE = 237;
public static void visible(Context context, int category) throws IllegalArgumentException {
if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) {
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
index 264b8c1..9caf78a 100644
--- a/core/java/com/android/internal/os/BatteryStatsHelper.java
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -47,6 +47,7 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
+import java.util.Locale;
/**
* A helper class for retrieving the power usage information for all applications and services.
@@ -267,15 +268,20 @@
public static String makemAh(double power) {
if (power == 0) return "0";
- else if (power < .00001) return String.format("%.8f", power);
- else if (power < .0001) return String.format("%.7f", power);
- else if (power < .001) return String.format("%.6f", power);
- else if (power < .01) return String.format("%.5f", power);
- else if (power < .1) return String.format("%.4f", power);
- else if (power < 1) return String.format("%.3f", power);
- else if (power < 10) return String.format("%.2f", power);
- else if (power < 100) return String.format("%.1f", power);
- else return String.format("%.0f", power);
+
+ final String format;
+ if (power < .00001) format = "%.8f";
+ else if (power < .0001) format = "%.7f";
+ else if (power < .001) format = "%.6f";
+ else if (power < .01) format = "%.5f";
+ else if (power < .1) format = "%.4f";
+ else if (power < 1) format = "%.3f";
+ else if (power < 10) format = "%.2f";
+ else if (power < 100) format = "%.1f";
+ else format = "%.0f";
+
+ // Use English locale because this is never used in UI (only in checkin and dump).
+ return String.format(Locale.ENGLISH, format, power);
}
/**
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 60f47d6..e7c58f4 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -2560,14 +2560,24 @@
addHistoryEventLocked(elapsedRealtime, uptime, code, name, uid);
}
+ boolean ensureStartClockTime(final long currentTime) {
+ final long ABOUT_ONE_YEAR = 365*24*60*60*1000L;
+ if (currentTime > ABOUT_ONE_YEAR && mStartClockTime < (currentTime-ABOUT_ONE_YEAR)) {
+ // If the start clock time has changed by more than a year, then presumably
+ // the previous time was completely bogus. So we are going to figure out a
+ // new time based on how much time has elapsed since we started counting.
+ mStartClockTime = currentTime - (SystemClock.elapsedRealtime()-(mRealtimeStart/1000));
+ return true;
+ }
+ return false;
+ }
+
public void noteCurrentTimeChangedLocked() {
final long currentTime = System.currentTimeMillis();
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
recordCurrentTimeChangeLocked(currentTime, elapsedRealtime, uptime);
- if (isStartClockTimeValid()) {
- mStartClockTime = currentTime;
- }
+ ensureStartClockTime(currentTime);
}
public void noteProcessStartLocked(String name, int uid) {
@@ -4306,19 +4316,11 @@
}
}
- boolean isStartClockTimeValid() {
- return mStartClockTime > 365*24*60*60*1000L;
- }
-
@Override public long getStartClockTime() {
- if (!isStartClockTimeValid()) {
- // If the last clock time we got was very small, then we hadn't had a real
- // time yet, so try to get it again.
- mStartClockTime = System.currentTimeMillis();
- if (isStartClockTimeValid()) {
- recordCurrentTimeChangeLocked(mStartClockTime, SystemClock.elapsedRealtime(),
- SystemClock.uptimeMillis());
- }
+ final long currentTime = System.currentTimeMillis();
+ if (ensureStartClockTime(currentTime)) {
+ recordCurrentTimeChangeLocked(currentTime, SystemClock.elapsedRealtime(),
+ SystemClock.uptimeMillis());
}
return mStartClockTime;
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 92862f5..3e22e09 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1749,6 +1749,10 @@
<!-- ==================================== -->
<eat-comment />
+ <!-- @SystemApi Allows access to the list of accounts in the Accounts Service. -->
+ <permission android:name="android.permission.GET_ACCOUNTS_PRIVILEGED"
+ android:protectionLevel="signature|privileged" />
+
<!-- @SystemApi Allows applications to RW to diagnostic resources.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.DIAGNOSTIC"
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 06b6389..54848e9 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -408,6 +408,7 @@
<integer translatable="false" name="config_wifi_framework_wifi_score_good_link_speed_24">24</integer>
<integer translatable="false" name="config_wifi_framework_wifi_score_good_link_speed_5">36</integer>
<string translatable="false" name="config_wifi_random_mac_oui">DA-A1-19</string>
+ <string translatable="false" name="config_wifi_framework_sap_2G_channel_list">1,6,11</string>
<bool translatable="false" name="config_wifi_framework_cellular_handover_enable_user_triggered_adjustment">true</bool>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index fe82b8c..8070986 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -337,6 +337,7 @@
<java-symbol type="integer" name="config_wifi_active_rx_cur_ma" />
<java-symbol type="integer" name="config_wifi_tx_cur_ma" />
<java-symbol type="integer" name="config_wifi_operating_voltage_mv" />
+ <java-symbol type="string" name="config_wifi_framework_sap_2G_channel_list" />
<java-symbol type="bool" name="editable_voicemailnumber" />
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 86e8560..053d43b6 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -20,6 +20,7 @@
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
+import android.app.ActivityManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
@@ -1200,12 +1201,15 @@
// We make the overlay view non-focusable and non-touchable so that
// the application that owns the window token can decide whether to consume or
// dispatch the input events.
- int flag = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
- | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+ int flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+ | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
+ if (ActivityManager.isHighEndGfx()) {
+ flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+ }
mWindowParams = new WindowManager.LayoutParams(
frame.right - frame.left, frame.bottom - frame.top,
- frame.left, frame.top, type, flag, PixelFormat.TRANSPARENT);
+ frame.left, frame.top, type, flags, PixelFormat.TRANSPARENT);
mWindowParams.privateFlags |=
WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
mWindowParams.gravity = Gravity.START | Gravity.TOP;
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 6e5dc3f..fea7f94 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -405,5 +405,13 @@
android:exported="true"
android:singleUser="true"
android:permission="android.permission.BIND_DREAM_SERVICE" />
+
+ <receiver
+ android:name=".tuner.TunerService$ClearReceiver"
+ android:exported="false">
+ <intent-filter>
+ <action android:name="com.android.systemui.action.CLEAR_TUNER" />
+ </intent-filter>
+ </receiver>
</application>
</manifest>
diff --git a/packages/SystemUI/res/drawable-nodpi/tuner.xml b/packages/SystemUI/res/drawable-nodpi/tuner.xml
index e27423f..0596aa4 100644
--- a/packages/SystemUI/res/drawable-nodpi/tuner.xml
+++ b/packages/SystemUI/res/drawable-nodpi/tuner.xml
@@ -1,7 +1,7 @@
<!--
- Copyright (C) 2015 The Android Open Source Project
+ Copyright (C) 2015 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ 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
@@ -14,14 +14,11 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48.0dp"
- android:height="48.0dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
<path
- android:fillColor="#FF000000"
- android:pathData="M29.9,24.8c0.0,-0.3 0.1,-0.5 0.1,-0.8s0.0,-0.5 -0.1,-0.8l1.7,-1.3c0.2,-0.1 0.2,-0.3 0.1,-0.5l-1.6,-2.8c-0.1,-0.2 -0.3,-0.2 -0.5,-0.2l-2.0,0.8c-0.4,-0.3 -0.9,-0.6 -1.4,-0.8L26.0,16.3c0.0,-0.2 -0.2,-0.3 -0.4,-0.3l-3.2,0.0c-0.2,0.0 -0.4,0.1 -0.4,0.3l-0.3,2.1c-0.5,0.2 -0.9,0.5 -1.4,0.8l-2.0,-0.8c-0.2,-0.1 -0.4,0.0 -0.5,0.2l-1.6,2.8c-0.1,0.2 -0.1,0.4 0.1,0.5l1.7,1.3c0.0,0.3 -0.1,0.5 -0.1,0.8s0.0,0.5 0.1,0.8l-1.7,1.3c-0.2,0.1 -0.2,0.3 -0.1,0.5l1.6,2.8c0.1,0.2 0.3,0.2 0.5,0.2l2.0,-0.8c0.4,0.3 0.9,0.6 1.4,0.8l0.3,2.1c0.0,0.2 0.2,0.3 0.4,0.3l3.2,0.0c0.2,0.0 0.4,-0.1 0.4,-0.3l0.3,-2.1c0.5,-0.2 0.9,-0.5 1.4,-0.8l2.0,0.8c0.2,0.1 0.4,0.0 0.5,-0.2l1.6,-2.8c0.1,-0.2 0.1,-0.4 -0.1,-0.5L29.9,24.8zM24.0,26.8c-1.5,0.0 -2.8,-1.3 -2.8,-2.8s1.3,-2.8 2.8,-2.8s2.8,1.3 2.8,2.8S25.5,26.8 24.0,26.8z"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M18.0,38.0c-0.6,0.0 -1.0,-0.4 -1.0,-1.0s0.4,-1.0 1.0,-1.0s1.0,0.4 1.0,1.0S18.6,38.0 18.0,38.0zM24.0,38.0c-0.6,0.0 -1.0,-0.4 -1.0,-1.0s0.4,-1.0 1.0,-1.0s1.0,0.4 1.0,1.0S24.6,38.0 24.0,38.0zM30.0,38.0c-0.6,0.0 -1.0,-0.4 -1.0,-1.0s0.4,-1.0 1.0,-1.0s1.0,0.4 1.0,1.0S30.6,38.0 30.0,38.0zM42.0,6.0L6.0,6.0c-2.2,0.0 -4.0,1.8 -4.0,4.0l0.0,28.0c0.0,2.2 1.8,4.0 4.0,4.0l36.0,0.0c2.2,0.0 4.0,-1.8 4.0,-4.0L46.0,10.0C46.0,7.8 44.2,6.0 42.0,6.0zM42.0,34.0L6.0,34.0L6.0,14.0l36.0,0.0L42.0,34.0zM9.0,12.0L7.0,12.0l0.0,-2.0l2.0,0.0L9.0,12.0zM13.0,12.0l-2.0,0.0l0.0,-2.0l2.0,0.0L13.0,12.0zM17.0,12.0l-2.0,0.0l0.0,-2.0l2.0,0.0L17.0,12.0z"/>
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M22.7,19.0l-9.1,-9.1c0.9,-2.0 0.4,-5.0 -1.5,-6.9 -2.0,-2.0 -5.0,-2.4 -7.4,-1.3L9.0,6.0 6.0,9.0 1.6,4.7C0.4,7.0 0.9,10.1 2.9,12.1c1.9,1.9 4.6,2.4 6.9,1.5l9.1,9.1c0.4,0.4 1.0,0.4 1.4,0.0l2.3,-2.3c0.5,-0.4 0.5,-1.0 0.1,-1.4z"/>
</vector>
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index 1488ad6..444f0f0 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -26,7 +26,7 @@
<com.android.systemui.statusbar.phone.KeyguardIndicationTextView
android:id="@+id/keyguard_indication_text"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/keyguard_indication_margin_bottom"
android:layout_gravity="bottom|center_horizontal"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index 7262ed2..8c8a3dd 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -44,14 +44,31 @@
android:scaleType="centerInside"/>
</com.android.systemui.statusbar.phone.MultiUserSwitch>
- <com.android.keyguard.AlphaOptimizedImageButton android:id="@+id/settings_button"
- style="@android:style/Widget.Material.Button.Borderless"
- android:layout_toStartOf="@id/multi_user_switch"
+ <com.android.keyguard.AlphaOptimizedLinearLayout
+ android:id="@+id/settings_button_container"
android:layout_width="48dp"
android:layout_height="@dimen/status_bar_header_height"
- android:background="@drawable/ripple_drawable"
- android:src="@drawable/ic_settings"
- android:contentDescription="@string/accessibility_desc_settings" />
+ android:paddingStart="12dp"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:layout_toStartOf="@id/multi_user_switch">
+
+ <com.android.systemui.statusbar.phone.SettingsButton android:id="@+id/settings_button"
+ style="@android:style/Widget.Material.Button.Borderless"
+ android:layout_width="24dp"
+ android:layout_height="@dimen/status_bar_header_height"
+ android:background="@drawable/ripple_drawable"
+ android:src="@drawable/ic_settings"
+ android:contentDescription="@string/accessibility_desc_settings" />
+ <com.android.systemui.statusbar.AlphaOptimizedImageView android:id="@+id/tuner_icon"
+ android:layout_width="12dp"
+ android:layout_height="@dimen/status_bar_header_height"
+ android:tint="#4DFFFFFF"
+ android:tintMode="src_in"
+ android:visibility="invisible"
+ android:src="@drawable/tuner" />
+
+ </com.android.keyguard.AlphaOptimizedLinearLayout>
<LinearLayout android:id="@+id/system_icons_super_container"
android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index fcf7e3e..3eac84f 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1032,7 +1032,7 @@
<string name="volume_stream_vibrate_dnd" translatable="false">%s vibrate — Priority only</string>
<!-- Name of special SystemUI debug settings -->
- <string name="system_ui_tuner">System UI tuner</string>
+ <string name="system_ui_tuner">System UI Tuner</string>
<!-- Preference to show/hide embedded battery percentage [CHAR LIMIT=50] -->
<string name="show_battery_percentage">Show embedded battery percentage</string>
@@ -1099,4 +1099,25 @@
<!-- Accessibility label for managed profile icon (not shown on screen) [CHAR LIMIT=NONE] -->
<string name="accessibility_managed_profile">Work profile</string>
+ <!-- Title of warning when entering System UI tuner for first time [CHAR LIMIT=NONE] -->
+ <string name="tuner_warning_title">Fun for some but not for all</string>
+
+ <!-- Warning for users entering the System UI tuner for the first time [CHAR LIMIT=NONE]-->
+ <string name="tuner_warning">System UI Tuner gives you extra ways to tweak and customize the Android user interface. These experimental features may change, break, or disappear in future releases. Proceed with caution.</string>
+
+ <!-- Warning for users entering the System UI tuner [CHAR LIMIT=NONE]-->
+ <string name="tuner_persistent_warning">These experimental features may change, break, or disappear in future releases. Proceed with caution.</string>
+
+ <!-- Generic "got it" acceptance of dialog or cling [CHAR LIMIT=NONE] -->
+ <string name="got_it">Got it</string>
+
+ <!-- Toast describing tuner has been enabled [CHAR LIMIT=NONE] -->
+ <string name="tuner_toast">Congrats! System UI Tuner has been added to Settings</string>
+
+ <!-- Option to remove the tuner from settings [CHAR LIMIT=NONE] -->
+ <string name="remove_from_settings">Remove from Settings</string>
+
+ <!-- Dialog asking if the tuner should really be removed from settings [CHAR LIMIT=NONE]-->
+ <string name="remove_from_settings_prompt">Remove System UI Tuner from Settings and stop using all of its features?"</string>
+
</resources>
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index 8c1acc3..3a41c3c 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -76,4 +76,8 @@
android:key="demo_mode"
android:title="@string/demo_mode" />
+ <Preference
+ android:summary="@string/tuner_persistent_warning"
+ android:selectable="false" />
+
</PreferenceScreen>
diff --git a/packages/SystemUI/src/com/android/systemui/DemoMode.java b/packages/SystemUI/src/com/android/systemui/DemoMode.java
index d406f5b..11996d0 100644
--- a/packages/SystemUI/src/com/android/systemui/DemoMode.java
+++ b/packages/SystemUI/src/com/android/systemui/DemoMode.java
@@ -20,6 +20,8 @@
public interface DemoMode {
+ public static final String DEMO_MODE_ALLOWED = "sysui_demo_allowed";
+
void dispatchDemoCommand(String command, Bundle args);
public static final String ACTION_DEMO = "com.android.systemui.demo";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index f62dc59..a2e6632 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -729,11 +729,15 @@
}
protected void setNotificationShown(StatusBarNotification n) {
- mNotificationListener.setNotificationsShown(new String[] { n.getKey() });
+ setNotificationsShown(new String[]{n.getKey()});
}
protected void setNotificationsShown(String[] keys) {
- mNotificationListener.setNotificationsShown(keys);
+ try {
+ mNotificationListener.setNotificationsShown(keys);
+ } catch (RuntimeException e) {
+ Log.d(TAG, "failed setNotificationsShown: ", e);
+ }
}
protected boolean isCurrentProfile(int userId) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index d829299..e1ba2d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -198,6 +198,8 @@
public static final boolean SHOW_LOCKSCREEN_MEDIA_ARTWORK = true;
+ public static final String ACTION_FAKE_ARTWORK = "fake_artwork";
+
private static final int MSG_OPEN_NOTIFICATION_PANEL = 1000;
private static final int MSG_CLOSE_PANELS = 1001;
private static final int MSG_OPEN_SETTINGS_PANEL = 1002;
@@ -890,12 +892,16 @@
filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
- if (DEBUG_MEDIA_FAKE_ARTWORK) {
- filter.addAction("fake_artwork");
- }
- filter.addAction(ACTION_DEMO);
context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
+ IntentFilter demoFilter = new IntentFilter();
+ if (DEBUG_MEDIA_FAKE_ARTWORK) {
+ demoFilter.addAction(ACTION_FAKE_ARTWORK);
+ }
+ demoFilter.addAction(ACTION_DEMO);
+ context.registerReceiverAsUser(mDemoReceiver, UserHandle.ALL, demoFilter,
+ android.Manifest.permission.DUMP, null);
+
// listen for USER_SETUP_COMPLETE setting (per-user)
resetUserSetupObserver();
@@ -2852,7 +2858,14 @@
mScreenOn = true;
notifyNavigationBarScreenOn(true);
}
- else if (ACTION_DEMO.equals(action)) {
+ }
+ };
+
+ private BroadcastReceiver mDemoReceiver = new BroadcastReceiver() {
+ public void onReceive(Context context, Intent intent) {
+ if (DEBUG) Log.v(TAG, "onReceive: " + intent);
+ String action = intent.getAction();
+ if (ACTION_DEMO.equals(action)) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
String command = bundle.getString("command", "").trim().toLowerCase();
@@ -2864,7 +2877,7 @@
}
}
}
- } else if ("fake_artwork".equals(action)) {
+ } else if (ACTION_FAKE_ARTWORK.equals(action)) {
if (DEBUG_MEDIA_FAKE_ARTWORK) {
updateMediaMetaData(true);
}
@@ -3188,6 +3201,7 @@
mHandlerThread = null;
}
mContext.unregisterReceiver(mBroadcastReceiver);
+ mContext.unregisterReceiver(mDemoReceiver);
mAssistManager.destroy();
final SignalClusterView signalCluster =
@@ -3211,7 +3225,7 @@
public void dispatchDemoCommand(String command, Bundle args) {
if (!mDemoModeAllowed) {
mDemoModeAllowed = Settings.Global.getInt(mContext.getContentResolver(),
- "sysui_demo_allowed", 0) != 0;
+ DEMO_MODE_ALLOWED, 0) != 0;
}
if (!mDemoModeAllowed) return;
if (command.equals(COMMAND_ENTER)) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java
new file mode 100644
index 0000000..a1e9ece
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.statusbar.phone;
+
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.os.Handler;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+
+import com.android.keyguard.AlphaOptimizedImageButton;
+
+public class SettingsButton extends AlphaOptimizedImageButton {
+
+ private static final long LONG_PRESS_LENGTH = 1000;
+ private static final long ACCEL_LENGTH = 750;
+ private static final long FULL_SPEED_LENGTH = 375;
+ private static final long RUN_DURATION = 350;
+
+ private boolean mUpToSpeed;
+ private ObjectAnimator mAnimator;
+
+ private float mSlop;
+
+ public SettingsButton(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
+ }
+
+ public boolean isAnimating() {
+ return mAnimator != null && mAnimator.isRunning();
+ }
+
+ public boolean isTunerClick() {
+ return mUpToSpeed;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ postDelayed(mLongPressCallback, LONG_PRESS_LENGTH);
+ break;
+ case MotionEvent.ACTION_UP:
+ if (mUpToSpeed) {
+ startExitAnimation();
+ } else {
+ cancelLongClick();
+ }
+ break;
+ case MotionEvent.ACTION_CANCEL:
+ cancelLongClick();
+ break;
+ case MotionEvent.ACTION_MOVE:
+ float x = event.getX();
+ float y = event.getY();
+ if ((x < -mSlop) || (y < -mSlop) || (x > getWidth() + mSlop)
+ || (y > getHeight() + mSlop)) {
+ cancelLongClick();
+ }
+ break;
+ }
+ return super.onTouchEvent(event);
+ }
+
+ private void cancelLongClick() {
+ cancelAnimation();
+ mUpToSpeed = false;
+ removeCallbacks(mLongPressCallback);
+ }
+
+ private void cancelAnimation() {
+ if (mAnimator != null) {
+ mAnimator.removeAllListeners();
+ mAnimator.cancel();
+ mAnimator = null;
+ }
+ }
+
+ private void startExitAnimation() {
+ animate()
+ .translationX(((View) getParent().getParent()).getWidth() - getX())
+ .alpha(0)
+ .setDuration(RUN_DURATION)
+ .setInterpolator(AnimationUtils.loadInterpolator(mContext,
+ android.R.interpolator.accelerate_cubic))
+ .setListener(new AnimatorListener() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ setAlpha(1f);
+ setTranslationX(0);
+ cancelLongClick();
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ }
+ })
+ .start();
+ }
+
+ protected void startAccelSpin() {
+ cancelAnimation();
+ mAnimator = ObjectAnimator.ofFloat(this, View.ROTATION, 0, 360);
+ mAnimator.setInterpolator(AnimationUtils.loadInterpolator(mContext,
+ android.R.interpolator.accelerate_quad));
+ mAnimator.setDuration(ACCEL_LENGTH);
+ mAnimator.addListener(new AnimatorListener() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ startContinuousSpin();
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ }
+ });
+ mAnimator.start();
+ }
+
+ protected void startContinuousSpin() {
+ cancelAnimation();
+ mUpToSpeed = true;
+ mAnimator = ObjectAnimator.ofFloat(this, View.ROTATION, 0, 360);
+ mAnimator.setInterpolator(AnimationUtils.loadInterpolator(mContext,
+ android.R.interpolator.linear));
+ mAnimator.setDuration(FULL_SPEED_LENGTH);
+ mAnimator.setRepeatCount(Animation.INFINITE);
+ mAnimator.start();
+ }
+
+ private final Runnable mLongPressCallback = new Runnable() {
+ @Override
+ public void run() {
+ startAccelSpin();
+ }
+ };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index a81f06e2..5d58cd0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -37,6 +37,7 @@
import android.widget.RelativeLayout;
import android.widget.Switch;
import android.widget.TextView;
+import android.widget.Toast;
import com.android.keyguard.KeyguardStatusView;
import com.android.systemui.BatteryMeterView;
@@ -48,6 +49,7 @@
import com.android.systemui.statusbar.policy.NetworkControllerImpl.EmergencyListener;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.UserInfoController;
+import com.android.systemui.tuner.TunerService;
import java.text.NumberFormat;
@@ -73,7 +75,8 @@
private TextView mDateExpanded;
private LinearLayout mSystemIcons;
private View mSignalCluster;
- private View mSettingsButton;
+ private SettingsButton mSettingsButton;
+ private View mSettingsContainer;
private View mQsDetailHeader;
private TextView mQsDetailHeaderTitle;
private Switch mQsDetailHeaderSwitch;
@@ -142,7 +145,8 @@
mMultiUserAvatar = (ImageView) findViewById(R.id.multi_user_avatar);
mDateCollapsed = (TextView) findViewById(R.id.date_collapsed);
mDateExpanded = (TextView) findViewById(R.id.date_expanded);
- mSettingsButton = findViewById(R.id.settings_button);
+ mSettingsButton = (SettingsButton) findViewById(R.id.settings_button);
+ mSettingsContainer = findViewById(R.id.settings_button_container);
mSettingsButton.setOnClickListener(this);
mQsDetailHeader = findViewById(R.id.qs_detail_header);
mQsDetailHeader.setAlpha(0);
@@ -323,13 +327,15 @@
mDateCollapsed.setVisibility(mExpanded && mAlarmShowing ? View.VISIBLE : View.INVISIBLE);
mDateExpanded.setVisibility(mExpanded && mAlarmShowing ? View.INVISIBLE : View.VISIBLE);
mAlarmStatus.setVisibility(mExpanded && mAlarmShowing ? View.VISIBLE : View.INVISIBLE);
- mSettingsButton.setVisibility(mExpanded ? View.VISIBLE : View.INVISIBLE);
+ mSettingsContainer.setVisibility(mExpanded ? View.VISIBLE : View.INVISIBLE);
mQsDetailHeader.setVisibility(mExpanded && mShowingDetail? View.VISIBLE : View.INVISIBLE);
if (mSignalCluster != null) {
updateSignalClusterDetachment();
}
mEmergencyCallsOnly.setVisibility(mExpanded && mShowEmergencyCallsOnly ? VISIBLE : GONE);
mBatteryLevel.setVisibility(mExpanded ? View.VISIBLE : View.GONE);
+ mSettingsContainer.findViewById(R.id.tuner_icon).setVisibility(
+ TunerService.isTunerEnabled(mContext) ? View.VISIBLE : View.INVISIBLE);
}
private void updateSignalClusterDetachment() {
@@ -352,7 +358,7 @@
private void updateSystemIconsLayoutParams() {
RelativeLayout.LayoutParams lp = (LayoutParams) mSystemIconsSuperContainer.getLayoutParams();
int rule = mExpanded
- ? mSettingsButton.getId()
+ ? mSettingsContainer.getId()
: mMultiUserSwitch.getId();
if (rule != lp.getRules()[RelativeLayout.START_OF]) {
lp.addRule(RelativeLayout.START_OF, rule);
@@ -495,6 +501,20 @@
@Override
public void onClick(View v) {
if (v == mSettingsButton) {
+ if (mSettingsButton.isTunerClick()) {
+ if (TunerService.isTunerEnabled(mContext)) {
+ TunerService.showResetRequest(mContext, new Runnable() {
+ @Override
+ public void run() {
+ // Relaunch settings so that the tuner disappears.
+ startSettingsActivity();
+ }
+ });
+ } else {
+ Toast.makeText(getContext(), R.string.tuner_toast, Toast.LENGTH_LONG).show();
+ TunerService.setTunerEnabled(mContext, true);
+ }
+ }
startSettingsActivity();
} else if (v == mSystemIconsSuperContainer) {
startBatteryActivity();
@@ -567,10 +587,10 @@
}
target.batteryY = mSystemIconsSuperContainer.getTop() + mSystemIconsContainer.getTop();
target.batteryLevelAlpha = getAlphaForVisibility(mBatteryLevel);
- target.settingsAlpha = getAlphaForVisibility(mSettingsButton);
+ target.settingsAlpha = getAlphaForVisibility(mSettingsContainer);
target.settingsTranslation = mExpanded
? 0
- : mMultiUserSwitch.getLeft() - mSettingsButton.getLeft();
+ : mMultiUserSwitch.getLeft() - mSettingsContainer.getLeft();
target.signalClusterAlpha = mSignalClusterDetached ? 0f : 1f;
target.settingsRotation = !mExpanded ? 90f : 0f;
}
@@ -622,9 +642,11 @@
mSignalCluster.setTranslationX(0f);
mSignalCluster.setTranslationY(0f);
}
- mSettingsButton.setTranslationY(mSystemIconsSuperContainer.getTranslationY());
- mSettingsButton.setTranslationX(values.settingsTranslation);
- mSettingsButton.setRotation(values.settingsRotation);
+ if (!mSettingsButton.isAnimating()) {
+ mSettingsContainer.setTranslationY(mSystemIconsSuperContainer.getTranslationY());
+ mSettingsContainer.setTranslationX(values.settingsTranslation);
+ mSettingsButton.setRotation(values.settingsRotation);
+ }
applyAlpha(mEmergencyCallsOnly, values.emergencyCallsOnlyAlpha);
if (!mShowingDetail && !mDetailTransitioning) {
// Otherwise it needs to stay invisible
@@ -633,7 +655,7 @@
applyAlpha(mDateCollapsed, values.dateCollapsedAlpha);
applyAlpha(mDateExpanded, values.dateExpandedAlpha);
applyAlpha(mBatteryLevel, values.batteryLevelAlpha);
- applyAlpha(mSettingsButton, values.settingsAlpha);
+ applyAlpha(mSettingsContainer, values.settingsAlpha);
applyAlpha(mSignalCluster, values.signalClusterAlpha);
if (!mExpanded) {
mTime.setScaleX(1f);
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
index 3f5ca58..a2b062c 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
@@ -28,13 +28,14 @@
import android.preference.PreferenceScreen;
import android.preference.SwitchPreference;
import android.provider.Settings;
+import android.view.MenuItem;
+import com.android.internal.logging.MetricsLogger;
import com.android.systemui.DemoMode;
import com.android.systemui.R;
public class DemoModeFragment extends PreferenceFragment implements OnPreferenceChangeListener {
- private static final String DEMO_MODE_ALLOWED = "sysui_demo_allowed";
private static final String DEMO_MODE_ON = "sysui_tuner_demo_on";
private static final String[] STATUS_ICONS = {
@@ -75,10 +76,33 @@
updateDemoModeEnabled();
updateDemoModeOn();
ContentResolver contentResolver = getContext().getContentResolver();
- contentResolver.registerContentObserver(Settings.Global.getUriFor(DEMO_MODE_ALLOWED), false,
- mDemoModeObserver);
+ contentResolver.registerContentObserver(Settings.Global.getUriFor(
+ DemoMode.DEMO_MODE_ALLOWED), false, mDemoModeObserver);
contentResolver.registerContentObserver(Settings.Global.getUriFor(DEMO_MODE_ON), false,
mDemoModeObserver);
+ setHasOptionsMenu(true);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ getFragmentManager().popBackStack();
+ break;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ MetricsLogger.visibility(getContext(), MetricsLogger.TUNER_DEMO_MODE, true);
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ MetricsLogger.visibility(getContext(), MetricsLogger.TUNER_DEMO_MODE, false);
}
@Override
@@ -89,7 +113,7 @@
private void updateDemoModeEnabled() {
boolean enabled = Settings.Global.getInt(getContext().getContentResolver(),
- DEMO_MODE_ALLOWED, 0) != 0;
+ DemoMode.DEMO_MODE_ALLOWED, 0) != 0;
mEnabledSwitch.setChecked(enabled);
mOnSwitch.setEnabled(enabled);
}
@@ -102,15 +126,18 @@
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
+ boolean enabled = newValue == Boolean.TRUE;
if (preference == mEnabledSwitch) {
- if (newValue != Boolean.TRUE) {
+ if (!enabled) {
// Make sure we aren't in demo mode when disabling it.
mOnSwitch.setChecked(false);
stopDemoMode();
}
- setGlobal(DEMO_MODE_ALLOWED, newValue == Boolean.TRUE ? 1 : 0);
+ MetricsLogger.action(getContext(), MetricsLogger.TUNER_DEMO_MODE_ENABLED, enabled);
+ setGlobal(DemoMode.DEMO_MODE_ALLOWED, enabled ? 1 : 0);
} else if (preference == mOnSwitch) {
- if (newValue == Boolean.TRUE) {
+ MetricsLogger.action(getContext(), MetricsLogger.TUNER_DEMO_MODE_ON, enabled);
+ if (enabled) {
startDemoMode();
} else {
stopDemoMode();
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java b/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java
index a5b244e..37ac098 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java
@@ -40,6 +40,7 @@
import android.widget.FrameLayout;
import android.widget.ScrollView;
+import com.android.internal.logging.MetricsLogger;
import com.android.systemui.R;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QSTile;
@@ -79,12 +80,25 @@
menu.add(0, MENU_RESET, 0, com.android.internal.R.string.reset);
}
+ public void onResume() {
+ super.onResume();
+ MetricsLogger.visibility(getContext(), MetricsLogger.TUNER_QS, true);
+ }
+
+ public void onPause() {
+ super.onPause();
+ MetricsLogger.visibility(getContext(), MetricsLogger.TUNER_QS, false);
+ }
+
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_RESET:
mTileHost.reset();
break;
+ case android.R.id.home:
+ getFragmentManager().popBackStack();
+ break;
}
return super.onOptionsItemSelected(item);
}
@@ -205,6 +219,8 @@
if (oldTile.equals(newTile)) {
return;
}
+ MetricsLogger.action(getContext(), MetricsLogger.TUNER_QS_REORDER, oldTile + ","
+ + newTile);
List<String> order = new ArrayList<>(mTileSpecs);
int index = order.indexOf(oldTile);
if (index < 0) {
@@ -217,12 +233,14 @@
}
public void remove(String tile) {
+ MetricsLogger.action(getContext(), MetricsLogger.TUNER_QS_REMOVE, tile);
List<String> tiles = new ArrayList<>(mTileSpecs);
tiles.remove(tile);
setTiles(tiles);
}
public void add(String tile) {
+ MetricsLogger.action(getContext(), MetricsLogger.TUNER_QS_ADD, tile);
List<String> tiles = new ArrayList<>(mTileSpecs);
tiles.add(tile);
setTiles(tiles);
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
index d4cc56d..e5b550e 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
@@ -23,6 +23,7 @@
import android.text.TextUtils;
import android.util.AttributeSet;
+import com.android.internal.logging.MetricsLogger;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.tuner.TunerService.Tunable;
@@ -50,11 +51,14 @@
if (!value) {
// If not enabled add to blacklist.
if (!mBlacklist.contains(getKey())) {
+ MetricsLogger.action(getContext(), MetricsLogger.TUNER_STATUS_BAR_DISABLE,
+ getKey());
mBlacklist.add(getKey());
setList(mBlacklist);
}
} else {
if (mBlacklist.remove(getKey())) {
+ MetricsLogger.action(getContext(), MetricsLogger.TUNER_STATUS_BAR_ENABLE, getKey());
setList(mBlacklist);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
index 4a8c2e4..71b5de5 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
@@ -17,7 +17,10 @@
import static com.android.systemui.BatteryMeterView.SHOW_PERCENT_SETTING;
+import android.app.AlertDialog;
import android.app.FragmentTransaction;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Bundle;
@@ -28,19 +31,29 @@
import android.preference.PreferenceFragment;
import android.preference.PreferenceGroup;
import android.preference.SwitchPreference;
+import android.provider.Settings;
import android.provider.Settings.System;
+import android.view.Menu;
+import android.view.MenuInflater;
import android.view.MenuItem;
+import com.android.internal.logging.MetricsLogger;
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.tuner.TunerService.Tunable;
public class TunerFragment extends PreferenceFragment {
+ private static final String TAG = "TunerFragment";
+
private static final String KEY_QS_TUNER = "qs_tuner";
private static final String KEY_DEMO_MODE = "demo_mode";
private static final String KEY_BATTERY_PCT = "battery_pct";
+ public static final String SETTING_SEEN_TUNER_WARNING = "seen_tuner_warning";
+
+ private static final int MENU_REMOVE = Menu.FIRST + 1;
+
private final SettingObserver mSettingObserver = new SettingObserver();
private SwitchPreference mBatteryPct;
@@ -73,6 +86,19 @@
}
});
mBatteryPct = (SwitchPreference) findPreference(KEY_BATTERY_PCT);
+ if (Settings.Secure.getInt(getContext().getContentResolver(), SETTING_SEEN_TUNER_WARNING,
+ 0) == 0) {
+ new AlertDialog.Builder(getContext())
+ .setTitle(R.string.tuner_warning_title)
+ .setMessage(R.string.tuner_warning)
+ .setPositiveButton(R.string.got_it, new OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Settings.Secure.putInt(getContext().getContentResolver(),
+ SETTING_SEEN_TUNER_WARNING, 1);
+ }
+ }).show();
+ }
}
@Override
@@ -83,6 +109,7 @@
System.getUriFor(SHOW_PERCENT_SETTING), false, mSettingObserver);
registerPrefs(getPreferenceScreen());
+ MetricsLogger.visibility(getContext(), MetricsLogger.TUNER, true);
}
@Override
@@ -91,6 +118,7 @@
getContext().getContentResolver().unregisterContentObserver(mSettingObserver);
unregisterPrefs(getPreferenceScreen());
+ MetricsLogger.visibility(getContext(), MetricsLogger.TUNER, false);
}
private void registerPrefs(PreferenceGroup group) {
@@ -120,11 +148,24 @@
}
@Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ menu.add(Menu.NONE, MENU_REMOVE, Menu.NONE, R.string.remove_from_settings);
+ }
+
+ @Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
getActivity().finish();
return true;
+ case MENU_REMOVE:
+ TunerService.showResetRequest(getContext(), new Runnable() {
+ @Override
+ public void run() {
+ getActivity().finish();
+ }
+ });
+ return true;
}
return super.onOptionsItemSelected(item);
}
@@ -152,6 +193,7 @@
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
final boolean v = (Boolean) newValue;
+ MetricsLogger.action(getContext(), MetricsLogger.TUNER_BATTERY_PERCENTAGE, v);
System.putInt(getContext().getContentResolver(), SHOW_PERCENT_SETTING, v ? 1 : 0);
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
index de5aaf6..d3f33ab 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
@@ -16,8 +16,15 @@
package com.android.systemui.tuner;
import android.app.ActivityManager;
+import android.app.AlertDialog;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.content.Intent;
+import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
@@ -25,9 +32,13 @@
import android.provider.Settings;
import android.util.ArrayMap;
+import com.android.systemui.BatteryMeterView;
+import com.android.systemui.DemoMode;
+import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.SystemUIApplication;
import com.android.systemui.settings.CurrentUserTracker;
+import com.android.systemui.statusbar.phone.SystemUIDialog;
import java.util.ArrayList;
import java.util.HashMap;
@@ -36,6 +47,8 @@
public class TunerService extends SystemUI {
+ public static final String ACTION_CLEAR = "com.android.systemui.action.CLEAR_TUNER";
+
private final Observer mObserver = new Observer();
// Map of Uris we listen on to their settings keys.
private final ArrayMap<Uri, String> mListeningUris = new ArrayMap<>();
@@ -118,6 +131,19 @@
}
}
+ public void clearAll() {
+ // A couple special cases.
+ Settings.Global.putString(mContentResolver, DemoMode.DEMO_MODE_ALLOWED, null);
+ Settings.System.putString(mContentResolver, BatteryMeterView.SHOW_PERCENT_SETTING, null);
+ Intent intent = new Intent(DemoMode.ACTION_DEMO);
+ intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_EXIT);
+ mContext.sendBroadcast(intent);
+
+ for (String key : mTunableLookup.keySet()) {
+ Settings.Secure.putString(mContentResolver, key, null);
+ }
+ }
+
// Only used in other processes, such as the tuner.
private static TunerService sInstance;
@@ -141,6 +167,44 @@
return sInstance;
}
+ public static final void showResetRequest(final Context context, final Runnable onDisabled) {
+ SystemUIDialog dialog = new SystemUIDialog(context);
+ dialog.setMessage(R.string.remove_from_settings_prompt);
+ dialog.setButton(DialogInterface.BUTTON_NEGATIVE, context.getString(R.string.cancel),
+ (OnClickListener) null);
+ dialog.setButton(DialogInterface.BUTTON_POSITIVE,
+ context.getString(R.string.guest_exit_guest_dialog_remove), new OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ // Tell the tuner (in main SysUI process) to clear all its settings.
+ context.sendBroadcast(new Intent(TunerService.ACTION_CLEAR));
+ // Disable access to tuner.
+ TunerService.setTunerEnabled(context, false);
+ // Make them sit through the warning dialog again.
+ Settings.Secure.putInt(context.getContentResolver(),
+ TunerFragment.SETTING_SEEN_TUNER_WARNING, 0);
+ if (onDisabled != null) {
+ onDisabled.run();
+ }
+ }
+ });
+ dialog.show();
+ }
+
+ public static final void setTunerEnabled(Context context, boolean enabled) {
+ context.getPackageManager().setComponentEnabledSetting(
+ new ComponentName(context, TunerActivity.class),
+ enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
+ : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+ PackageManager.DONT_KILL_APP);
+ }
+
+ public static final boolean isTunerEnabled(Context context) {
+ return context.getPackageManager().getComponentEnabledSetting(
+ new ComponentName(context, TunerActivity.class))
+ == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+ }
+
private class Observer extends ContentObserver {
public Observer() {
super(new Handler(Looper.getMainLooper()));
@@ -157,4 +221,13 @@
public interface Tunable {
void onTuningChanged(String key, String newValue);
}
+
+ public static class ClearReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (ACTION_CLEAR.equals(intent.getAction())) {
+ get(context).clearAll();
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/AssetAtlasService.java b/services/core/java/com/android/server/AssetAtlasService.java
index ebc810f..4569dae 100644
--- a/services/core/java/com/android/server/AssetAtlasService.java
+++ b/services/core/java/com/android/server/AssetAtlasService.java
@@ -93,7 +93,7 @@
// Defines the number of int fields used to represent a single entry
// in the atlas map. This number defines the size of the array returned
// by the getMap(). See the mAtlasMap field for more information
- private static final int ATLAS_MAP_ENTRY_FIELD_COUNT = 4;
+ private static final int ATLAS_MAP_ENTRY_FIELD_COUNT = 3;
// Specifies how our GraphicBuffer will be used. To get proper swizzling
// the buffer will be written to using OpenGL (from JNI) so we can leave
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index c7c9d29..7561c7d 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -253,6 +253,8 @@
"max_temp_app_whitelist_duration";
private static final String KEY_MMS_TEMP_APP_WHITELIST_DURATION =
"mms_temp_app_whitelist_duration";
+ private static final String KEY_SMS_TEMP_APP_WHITELIST_DURATION =
+ "sms_temp_app_whitelist_duration";
/**
* This is the time, after becoming inactive, at which we start looking at the
@@ -357,6 +359,13 @@
*/
public long MMS_TEMP_APP_WHITELIST_DURATION;
+ /**
+ * Amount of time we would like to whitelist an app that is receiving an SMS.
+ * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+ * @see #KEY_SMS_TEMP_APP_WHITELIST_DURATION
+ */
+ public long SMS_TEMP_APP_WHITELIST_DURATION;
+
private final ContentResolver mResolver;
private final KeyValueListParser mParser = new KeyValueListParser(',');
@@ -410,6 +419,8 @@
KEY_MAX_TEMP_APP_WHITELIST_DURATION, 5 * 60 * 1000L);
MMS_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
KEY_MMS_TEMP_APP_WHITELIST_DURATION, 60 * 1000L);
+ SMS_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
+ KEY_SMS_TEMP_APP_WHITELIST_DURATION, 20 * 1000L);
}
}
@@ -465,6 +476,10 @@
pw.print(" "); pw.print(KEY_MMS_TEMP_APP_WHITELIST_DURATION); pw.print("=");
TimeUtils.formatDuration(MMS_TEMP_APP_WHITELIST_DURATION, pw);
pw.println();
+
+ pw.print(" "); pw.print(KEY_SMS_TEMP_APP_WHITELIST_DURATION); pw.print("=");
+ TimeUtils.formatDuration(SMS_TEMP_APP_WHITELIST_DURATION, pw);
+ pw.println();
}
}
@@ -617,6 +632,13 @@
return duration;
}
+ @Override public long addPowerSaveTempWhitelistAppForSms(String packageName,
+ int userId, String reason) throws RemoteException {
+ long duration = mConstants.SMS_TEMP_APP_WHITELIST_DURATION;
+ addPowerSaveTempWhitelistApp(packageName, duration, userId, reason);
+ return duration;
+ }
+
@Override public void exitIdle(String reason) {
getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
null);
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index cb294fd..32fd56a 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -3799,7 +3799,8 @@
* access accounts of the specified account.
*/
boolean isPermitted =
- isPermitted(callingUid, Manifest.permission.GET_ACCOUNTS);
+ isPermitted(callingUid, Manifest.permission.GET_ACCOUNTS,
+ Manifest.permission.GET_ACCOUNTS_PRIVILEGED);
boolean isAccountManagedByCaller = isAccountManagedByCaller(accountType, callingUid);
Log.w(TAG, String.format(
"isReadAccountPermitted: isPermitted: %s, isAM: %s",
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index f04790e..0d1d1ea 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -495,6 +495,16 @@
}
}
+ // Voice recognition
+ Intent voiceRecoIntent = new Intent("android.speech.RecognitionService");
+ voiceRecoIntent.addCategory(Intent.CATEGORY_DEFAULT);
+ PackageParser.Package voiceRecoPackage = getDefaultSystemHandlerServicePackageLPr(
+ voiceRecoIntent, userId);
+ if (voiceRecoPackage != null
+ && doesPackageSupportRuntimePermissions(voiceRecoPackage)) {
+ grantRuntimePermissionsLPw(voiceRecoPackage, MICROPHONE_PERMISSIONS, userId);
+ }
+
// Location
if (locationPackageNames != null) {
for (String packageName : locationPackageNames) {
@@ -627,6 +637,26 @@
return null;
}
+ private PackageParser.Package getDefaultSystemHandlerServicePackageLPr(
+ Intent intent, int userId) {
+ List<ResolveInfo> handlers = mService.queryIntentServices(intent,
+ intent.resolveType(mService.mContext.getContentResolver()),
+ PackageManager.GET_DISABLED_COMPONENTS, userId);
+ if (handlers == null) {
+ return null;
+ }
+ final int handlerCount = handlers.size();
+ for (int i = 0; i < handlerCount; i++) {
+ ResolveInfo handler = handlers.get(i);
+ PackageParser.Package handlerPackage = getSystemPackageLPr(
+ handler.serviceInfo.packageName);
+ if (handlerPackage != null) {
+ return handlerPackage;
+ }
+ }
+ return null;
+ }
+
private List<PackageParser.Package> getHeadlessSyncAdapterPackagesLPr(
String[] syncAdapterPackageNames, int userId) {
List<PackageParser.Package> syncAdapterPackages = new ArrayList<>();
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index e456370..0b74996 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -15605,12 +15605,8 @@
* recycled.
*/
private void reconcileUsers(String volumeUuid) {
- final File[] files = Environment.getDataUserDirectory(volumeUuid).listFiles();
- if (ArrayUtils.isEmpty(files)) {
- Slog.d(TAG, "No users found on " + volumeUuid);
- return;
- }
-
+ final File[] files = FileUtils
+ .listFilesOrEmpty(Environment.getDataUserDirectory(volumeUuid));
for (File file : files) {
if (!file.isDirectory()) continue;
@@ -15666,12 +15662,8 @@
* another volume.
*/
private void reconcileApps(String volumeUuid) {
- final File[] files = Environment.getDataAppDirectory(volumeUuid).listFiles();
- if (ArrayUtils.isEmpty(files)) {
- Slog.d(TAG, "No apps found on " + volumeUuid);
- return;
- }
-
+ final File[] files = FileUtils
+ .listFilesOrEmpty(Environment.getDataAppDirectory(volumeUuid));
for (File file : files) {
final boolean isPackage = (isApkFile(file) || file.isDirectory())
&& !PackageInstallerService.isStageName(file.getName());
@@ -15802,7 +15794,12 @@
}
// Now that we're guarded by frozen state, kill app during move
- killApplication(packageName, appId, "move pkg");
+ final long token = Binder.clearCallingIdentity();
+ try {
+ killApplication(packageName, appId, "move pkg");
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
final Bundle extras = new Bundle();
extras.putString(Intent.EXTRA_PACKAGE_NAME, packageName);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 4f2b1f9..d9828cc 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -10029,70 +10029,70 @@
WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
if (DEBUG_LAYOUT_REPEATS) {
debugLayoutRepeats(
- "dream and commitFinishDrawingLocked true",
- displayContent.pendingLayoutChanges);
+ "dream and commitFinishDrawingLocked true",
+ displayContent.pendingLayoutChanges);
}
}
if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
- "First draw done in potential wallpaper target " + w);
+ "First draw done in potential wallpaper target " + w);
mInnerFields.mWallpaperMayChange = true;
displayContent.pendingLayoutChanges |=
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
if (DEBUG_LAYOUT_REPEATS) {
debugLayoutRepeats(
- "wallpaper and commitFinishDrawingLocked true",
- displayContent.pendingLayoutChanges);
+ "wallpaper and commitFinishDrawingLocked true",
+ displayContent.pendingLayoutChanges);
}
}
}
winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
+ }
- final AppWindowToken atoken = w.mAppToken;
- if (DEBUG_STARTING_WINDOW && atoken != null
- && w == atoken.startingWindow) {
- Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen="
- + w.isOnScreen() + " allDrawn=" + atoken.allDrawn
- + " freezingScreen=" + atoken.mAppAnimator.freezingScreen);
+ final AppWindowToken atoken = w.mAppToken;
+ if (DEBUG_STARTING_WINDOW && atoken != null
+ && w == atoken.startingWindow) {
+ Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen="
+ + w.isOnScreen() + " allDrawn=" + atoken.allDrawn
+ + " freezingScreen=" + atoken.mAppAnimator.freezingScreen);
+ }
+ if (atoken != null
+ && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) {
+ if (atoken.lastTransactionSequence != mTransactionSequence) {
+ atoken.lastTransactionSequence = mTransactionSequence;
+ atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
+ atoken.startingDisplayed = false;
}
- if (atoken != null
- && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) {
- if (atoken.lastTransactionSequence != mTransactionSequence) {
- atoken.lastTransactionSequence = mTransactionSequence;
- atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
- atoken.startingDisplayed = false;
+ if ((w.isOnScreenIgnoringKeyguard()
+ || winAnimator.mAttrType == TYPE_BASE_APPLICATION)
+ && !w.mExiting && !w.mDestroying) {
+ if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
+ Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
+ + ", isAnimating=" + winAnimator.isAnimating());
+ if (!w.isDrawnLw()) {
+ Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl
+ + " pv=" + w.mPolicyVisibility
+ + " mDrawState=" + winAnimator.drawStateToString()
+ + " ah=" + w.mAttachedHidden
+ + " th=" + atoken.hiddenRequested
+ + " a=" + winAnimator.mAnimating);
+ }
}
- if ((w.isOnScreenIgnoringKeyguard()
- || winAnimator.mAttrType == TYPE_BASE_APPLICATION)
- && !w.mExiting && !w.mDestroying) {
- if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
- Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
- + ", isAnimating=" + winAnimator.isAnimating());
- if (!w.isDrawnLw()) {
- Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl
- + " pv=" + w.mPolicyVisibility
- + " mDrawState=" + winAnimator.drawStateToString()
- + " ah=" + w.mAttachedHidden
- + " th=" + atoken.hiddenRequested
- + " a=" + winAnimator.mAnimating);
+ if (w != atoken.startingWindow) {
+ if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) {
+ atoken.numInterestingWindows++;
+ if (w.isDrawnLw()) {
+ atoken.numDrawnWindows++;
+ if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG,
+ "tokenMayBeDrawn: " + atoken
+ + " freezingScreen=" + atoken.mAppAnimator.freezingScreen
+ + " mAppFreezing=" + w.mAppFreezing);
+ updateAllDrawn = true;
}
}
- if (w != atoken.startingWindow) {
- if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) {
- atoken.numInterestingWindows++;
- if (w.isDrawnLw()) {
- atoken.numDrawnWindows++;
- if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG,
- "tokenMayBeDrawn: " + atoken
- + " freezingScreen=" + atoken.mAppAnimator.freezingScreen
- + " mAppFreezing=" + w.mAppFreezing);
- updateAllDrawn = true;
- }
- }
- } else if (w.isDrawnLw()) {
- atoken.startingDisplayed = true;
- }
+ } else if (w.isDrawnLw()) {
+ atoken.startingDisplayed = true;
}
}
}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
index 4498b84..f8ae03f 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
@@ -21,6 +21,7 @@
import android.os.Build;
import android.util.AtomicFile;
import android.util.Slog;
+import android.util.TimeUtils;
import java.io.BufferedReader;
import java.io.BufferedWriter;
@@ -191,7 +192,11 @@
for (File f : files) {
final AtomicFile af = new AtomicFile(f);
- mSortedStatFiles[i].put(UsageStatsXml.parseBeginTime(af), af);
+ try {
+ mSortedStatFiles[i].put(UsageStatsXml.parseBeginTime(af), af);
+ } catch (IOException e) {
+ Slog.e(TAG, "failed to index file: " + f, e);
+ }
}
}
}
@@ -273,14 +278,21 @@
public void onTimeChanged(long timeDiffMillis) {
synchronized (mLock) {
+ StringBuilder logBuilder = new StringBuilder();
+ logBuilder.append("Time changed by ");
+ TimeUtils.formatDuration(timeDiffMillis, logBuilder);
+ logBuilder.append(".");
+
+ int filesDeleted = 0;
+ int filesMoved = 0;
+
for (TimeSparseArray<AtomicFile> files : mSortedStatFiles) {
final int fileCount = files.size();
for (int i = 0; i < fileCount; i++) {
final AtomicFile file = files.valueAt(i);
final long newTime = files.keyAt(i) + timeDiffMillis;
if (newTime < 0) {
- Slog.i(TAG, "Deleting file " + file.getBaseFile().getAbsolutePath()
- + " for it is in the future now.");
+ filesDeleted++;
file.delete();
} else {
try {
@@ -295,14 +307,17 @@
}
final File newFile = new File(file.getBaseFile().getParentFile(), newName);
- Slog.i(TAG, "Moving file " + file.getBaseFile().getAbsolutePath() + " to "
- + newFile.getAbsolutePath());
+ filesMoved++;
file.getBaseFile().renameTo(newFile);
}
}
files.clear();
}
+ logBuilder.append(" files deleted: ").append(filesDeleted);
+ logBuilder.append(" files moved: ").append(filesMoved);
+ Slog.i(TAG, logBuilder.toString());
+
// Now re-index the new files.
indexFilesLocked();
}
@@ -506,7 +521,14 @@
if (path.endsWith(BAK_SUFFIX)) {
f = new File(path.substring(0, path.length() - BAK_SUFFIX.length()));
}
- long beginTime = UsageStatsXml.parseBeginTime(f);
+
+ long beginTime;
+ try {
+ beginTime = UsageStatsXml.parseBeginTime(f);
+ } catch (IOException e) {
+ beginTime = 0;
+ }
+
if (beginTime < expiryTime) {
new AtomicFile(f).delete();
}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsXml.java b/services/usage/java/com/android/server/usage/UsageStatsXml.java
index 186813e..543f361 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsXml.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsXml.java
@@ -33,11 +33,11 @@
private static final String VERSION_ATTR = "version";
static final String CHECKED_IN_SUFFIX = "-c";
- public static long parseBeginTime(AtomicFile file) {
+ public static long parseBeginTime(AtomicFile file) throws IOException {
return parseBeginTime(file.getBaseFile());
}
- public static long parseBeginTime(File file) {
+ public static long parseBeginTime(File file) throws IOException {
String name = file.getName();
// Eat as many occurrences of -c as possible. This is due to a bug where -c
@@ -47,7 +47,12 @@
while (name.endsWith(CHECKED_IN_SUFFIX)) {
name = name.substring(0, name.length() - CHECKED_IN_SUFFIX.length());
}
- return Long.parseLong(name);
+
+ try {
+ return Long.parseLong(name);
+ } catch (NumberFormatException e) {
+ throw new IOException(e);
+ }
}
public static void read(AtomicFile file, IntervalStats statsOut) throws IOException {
diff --git a/services/usb/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java
index 6300a9a..965341e 100644
--- a/services/usb/java/com/android/server/usb/UsbHostManager.java
+++ b/services/usb/java/com/android/server/usb/UsbHostManager.java
@@ -231,6 +231,8 @@
mNewConfigurations = null;
mNewInterfaces = null;
mNewEndpoints = null;
+ mNewConfiguration = null;
+ mNewInterface = null;
}
}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index f390075..d915e5d 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1302,7 +1302,7 @@
* Return the results of the latest access point scan.
* @return the list of access points found in the most recent scan. An app must hold
* {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
- * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_FINE_LOCATION} permission
+ * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission
* in order to get valid results.
*/
public List<ScanResult> getScanResults() {