Merge "DocsUI: Switch the launcher icon to Downloads." into nyc-dev
diff --git a/api/current.txt b/api/current.txt
index 38d2a03..8a83024 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -17760,9 +17760,6 @@
method public android.icu.text.UnicodeSet addAll(java.lang.Iterable<?>);
method public android.icu.text.UnicodeSet addAll(T...);
method public T addAllTo(T);
- method public java.lang.String[] addAllTo(java.lang.String[]);
- method public static U addAllTo(java.lang.Iterable<T>, U);
- method public static T[] addAllTo(java.lang.Iterable<T>, T[]);
method public void addMatchSetTo(android.icu.text.UnicodeSet);
method public android.icu.text.UnicodeSet applyIntPropertyValue(int, int);
method public final android.icu.text.UnicodeSet applyPattern(java.lang.String);
@@ -17776,10 +17773,6 @@
method public android.icu.text.UnicodeSet cloneAsThawed();
method public android.icu.text.UnicodeSet closeOver(int);
method public android.icu.text.UnicodeSet compact();
- method public static int compare(java.lang.CharSequence, int);
- method public static int compare(int, java.lang.CharSequence);
- method public static int compare(java.lang.Iterable<T>, java.lang.Iterable<T>);
- method public static int compare(java.util.Collection<T>, java.util.Collection<T>, android.icu.text.UnicodeSet.ComparisonStyle);
method public int compareTo(android.icu.text.UnicodeSet);
method public int compareTo(android.icu.text.UnicodeSet, android.icu.text.UnicodeSet.ComparisonStyle);
method public int compareTo(java.lang.Iterable<java.lang.String>);
@@ -17822,7 +17815,6 @@
method public android.icu.text.UnicodeSet removeAll(android.icu.text.UnicodeSet);
method public android.icu.text.UnicodeSet removeAll(java.lang.Iterable<T>);
method public final android.icu.text.UnicodeSet removeAllStrings();
- method public static boolean resemblesPattern(java.lang.String, int);
method public android.icu.text.UnicodeSet retain(int, int);
method public final android.icu.text.UnicodeSet retain(int);
method public final android.icu.text.UnicodeSet retain(java.lang.CharSequence);
@@ -17837,7 +17829,6 @@
method public int spanBack(java.lang.CharSequence, android.icu.text.UnicodeSet.SpanCondition);
method public int spanBack(java.lang.CharSequence, int, android.icu.text.UnicodeSet.SpanCondition);
method public java.util.Collection<java.lang.String> strings();
- method public static java.lang.String[] toArray(android.icu.text.UnicodeSet);
method public java.lang.String toPattern(boolean);
field public static final int ADD_CASE_MAPPINGS = 4; // 0x4
field public static final android.icu.text.UnicodeSet ALL_CODE_POINTS;
@@ -17956,11 +17947,8 @@
ctor protected CECalendar(int, int, int);
ctor protected CECalendar(java.util.Date);
ctor protected CECalendar(int, int, int, int, int, int);
- method public static int ceToJD(long, int, int, int);
- method protected abstract int getJDEpochOffset();
method protected int handleComputeMonthStart(int, int, boolean);
method protected int handleGetLimit(int, int);
- method public static void jdToCE(int, int, int[]);
}
public abstract class Calendar implements java.lang.Cloneable java.lang.Comparable java.io.Serializable {
@@ -18188,7 +18176,6 @@
ctor public CopticCalendar(int, int, int);
ctor public CopticCalendar(java.util.Date);
ctor public CopticCalendar(int, int, int, int, int, int);
- method protected deprecated int getJDEpochOffset();
method protected deprecated int handleGetExtendedYear();
field public static final int AMSHIR = 5; // 0x5
field public static final int BABA = 1; // 0x1
@@ -18359,11 +18346,11 @@
ctor public IslamicCalendar(java.util.Date);
ctor public IslamicCalendar(int, int, int);
ctor public IslamicCalendar(int, int, int, int, int, int);
+ method public android.icu.util.IslamicCalendar.CalculationType getCalculationType();
method protected int handleComputeMonthStart(int, int, boolean);
method protected int handleGetExtendedYear();
method protected int handleGetLimit(int, int);
- method public boolean isCivil();
- method public void setCivil(boolean);
+ method public void setCalculationType(android.icu.util.IslamicCalendar.CalculationType);
field public static final int DHU_AL_HIJJAH = 11; // 0xb
field public static final int DHU_AL_QIDAH = 10; // 0xa
field public static final int JUMADA_1 = 4; // 0x4
@@ -18801,7 +18788,6 @@
method public int getMicro();
method public int getMilli();
method public int getMinor();
- method public static void main(java.lang.String[]);
field public static final android.icu.util.VersionInfo ICU_VERSION;
field public static final android.icu.util.VersionInfo UCOL_BUILDER_VERSION;
field public static final android.icu.util.VersionInfo UCOL_RUNTIME_VERSION;
diff --git a/api/system-current.txt b/api/system-current.txt
index d7977f0..2cad670 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -18932,9 +18932,6 @@
method public android.icu.text.UnicodeSet addAll(java.lang.Iterable<?>);
method public android.icu.text.UnicodeSet addAll(T...);
method public T addAllTo(T);
- method public java.lang.String[] addAllTo(java.lang.String[]);
- method public static U addAllTo(java.lang.Iterable<T>, U);
- method public static T[] addAllTo(java.lang.Iterable<T>, T[]);
method public void addMatchSetTo(android.icu.text.UnicodeSet);
method public android.icu.text.UnicodeSet applyIntPropertyValue(int, int);
method public final android.icu.text.UnicodeSet applyPattern(java.lang.String);
@@ -18948,10 +18945,6 @@
method public android.icu.text.UnicodeSet cloneAsThawed();
method public android.icu.text.UnicodeSet closeOver(int);
method public android.icu.text.UnicodeSet compact();
- method public static int compare(java.lang.CharSequence, int);
- method public static int compare(int, java.lang.CharSequence);
- method public static int compare(java.lang.Iterable<T>, java.lang.Iterable<T>);
- method public static int compare(java.util.Collection<T>, java.util.Collection<T>, android.icu.text.UnicodeSet.ComparisonStyle);
method public int compareTo(android.icu.text.UnicodeSet);
method public int compareTo(android.icu.text.UnicodeSet, android.icu.text.UnicodeSet.ComparisonStyle);
method public int compareTo(java.lang.Iterable<java.lang.String>);
@@ -18994,7 +18987,6 @@
method public android.icu.text.UnicodeSet removeAll(android.icu.text.UnicodeSet);
method public android.icu.text.UnicodeSet removeAll(java.lang.Iterable<T>);
method public final android.icu.text.UnicodeSet removeAllStrings();
- method public static boolean resemblesPattern(java.lang.String, int);
method public android.icu.text.UnicodeSet retain(int, int);
method public final android.icu.text.UnicodeSet retain(int);
method public final android.icu.text.UnicodeSet retain(java.lang.CharSequence);
@@ -19009,7 +19001,6 @@
method public int spanBack(java.lang.CharSequence, android.icu.text.UnicodeSet.SpanCondition);
method public int spanBack(java.lang.CharSequence, int, android.icu.text.UnicodeSet.SpanCondition);
method public java.util.Collection<java.lang.String> strings();
- method public static java.lang.String[] toArray(android.icu.text.UnicodeSet);
method public java.lang.String toPattern(boolean);
field public static final int ADD_CASE_MAPPINGS = 4; // 0x4
field public static final android.icu.text.UnicodeSet ALL_CODE_POINTS;
@@ -19128,11 +19119,8 @@
ctor protected CECalendar(int, int, int);
ctor protected CECalendar(java.util.Date);
ctor protected CECalendar(int, int, int, int, int, int);
- method public static int ceToJD(long, int, int, int);
- method protected abstract int getJDEpochOffset();
method protected int handleComputeMonthStart(int, int, boolean);
method protected int handleGetLimit(int, int);
- method public static void jdToCE(int, int, int[]);
}
public abstract class Calendar implements java.lang.Cloneable java.lang.Comparable java.io.Serializable {
@@ -19360,7 +19348,6 @@
ctor public CopticCalendar(int, int, int);
ctor public CopticCalendar(java.util.Date);
ctor public CopticCalendar(int, int, int, int, int, int);
- method protected deprecated int getJDEpochOffset();
method protected deprecated int handleGetExtendedYear();
field public static final int AMSHIR = 5; // 0x5
field public static final int BABA = 1; // 0x1
@@ -19531,11 +19518,11 @@
ctor public IslamicCalendar(java.util.Date);
ctor public IslamicCalendar(int, int, int);
ctor public IslamicCalendar(int, int, int, int, int, int);
+ method public android.icu.util.IslamicCalendar.CalculationType getCalculationType();
method protected int handleComputeMonthStart(int, int, boolean);
method protected int handleGetExtendedYear();
method protected int handleGetLimit(int, int);
- method public boolean isCivil();
- method public void setCivil(boolean);
+ method public void setCalculationType(android.icu.util.IslamicCalendar.CalculationType);
field public static final int DHU_AL_HIJJAH = 11; // 0xb
field public static final int DHU_AL_QIDAH = 10; // 0xa
field public static final int JUMADA_1 = 4; // 0x4
@@ -19973,7 +19960,6 @@
method public int getMicro();
method public int getMilli();
method public int getMinor();
- method public static void main(java.lang.String[]);
field public static final android.icu.util.VersionInfo ICU_VERSION;
field public static final android.icu.util.VersionInfo UCOL_BUILDER_VERSION;
field public static final android.icu.util.VersionInfo UCOL_RUNTIME_VERSION;
@@ -31658,6 +31644,7 @@
method public android.os.Bundle getUserRestrictions(android.os.UserHandle);
method public boolean hasUserRestriction(java.lang.String);
method public boolean isManagedProfile();
+ method public boolean isManagedProfile(int);
method public boolean isQuietModeEnabled(android.os.UserHandle);
method public boolean isSystemUser();
method public boolean isUserAGoat();
diff --git a/api/test-current.txt b/api/test-current.txt
index b48faca..d3a12ed 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -17770,9 +17770,6 @@
method public android.icu.text.UnicodeSet addAll(java.lang.Iterable<?>);
method public android.icu.text.UnicodeSet addAll(T...);
method public T addAllTo(T);
- method public java.lang.String[] addAllTo(java.lang.String[]);
- method public static U addAllTo(java.lang.Iterable<T>, U);
- method public static T[] addAllTo(java.lang.Iterable<T>, T[]);
method public void addMatchSetTo(android.icu.text.UnicodeSet);
method public android.icu.text.UnicodeSet applyIntPropertyValue(int, int);
method public final android.icu.text.UnicodeSet applyPattern(java.lang.String);
@@ -17786,10 +17783,6 @@
method public android.icu.text.UnicodeSet cloneAsThawed();
method public android.icu.text.UnicodeSet closeOver(int);
method public android.icu.text.UnicodeSet compact();
- method public static int compare(java.lang.CharSequence, int);
- method public static int compare(int, java.lang.CharSequence);
- method public static int compare(java.lang.Iterable<T>, java.lang.Iterable<T>);
- method public static int compare(java.util.Collection<T>, java.util.Collection<T>, android.icu.text.UnicodeSet.ComparisonStyle);
method public int compareTo(android.icu.text.UnicodeSet);
method public int compareTo(android.icu.text.UnicodeSet, android.icu.text.UnicodeSet.ComparisonStyle);
method public int compareTo(java.lang.Iterable<java.lang.String>);
@@ -17832,7 +17825,6 @@
method public android.icu.text.UnicodeSet removeAll(android.icu.text.UnicodeSet);
method public android.icu.text.UnicodeSet removeAll(java.lang.Iterable<T>);
method public final android.icu.text.UnicodeSet removeAllStrings();
- method public static boolean resemblesPattern(java.lang.String, int);
method public android.icu.text.UnicodeSet retain(int, int);
method public final android.icu.text.UnicodeSet retain(int);
method public final android.icu.text.UnicodeSet retain(java.lang.CharSequence);
@@ -17847,7 +17839,6 @@
method public int spanBack(java.lang.CharSequence, android.icu.text.UnicodeSet.SpanCondition);
method public int spanBack(java.lang.CharSequence, int, android.icu.text.UnicodeSet.SpanCondition);
method public java.util.Collection<java.lang.String> strings();
- method public static java.lang.String[] toArray(android.icu.text.UnicodeSet);
method public java.lang.String toPattern(boolean);
field public static final int ADD_CASE_MAPPINGS = 4; // 0x4
field public static final android.icu.text.UnicodeSet ALL_CODE_POINTS;
@@ -17966,11 +17957,8 @@
ctor protected CECalendar(int, int, int);
ctor protected CECalendar(java.util.Date);
ctor protected CECalendar(int, int, int, int, int, int);
- method public static int ceToJD(long, int, int, int);
- method protected abstract int getJDEpochOffset();
method protected int handleComputeMonthStart(int, int, boolean);
method protected int handleGetLimit(int, int);
- method public static void jdToCE(int, int, int[]);
}
public abstract class Calendar implements java.lang.Cloneable java.lang.Comparable java.io.Serializable {
@@ -18198,7 +18186,6 @@
ctor public CopticCalendar(int, int, int);
ctor public CopticCalendar(java.util.Date);
ctor public CopticCalendar(int, int, int, int, int, int);
- method protected deprecated int getJDEpochOffset();
method protected deprecated int handleGetExtendedYear();
field public static final int AMSHIR = 5; // 0x5
field public static final int BABA = 1; // 0x1
@@ -18369,11 +18356,11 @@
ctor public IslamicCalendar(java.util.Date);
ctor public IslamicCalendar(int, int, int);
ctor public IslamicCalendar(int, int, int, int, int, int);
+ method public android.icu.util.IslamicCalendar.CalculationType getCalculationType();
method protected int handleComputeMonthStart(int, int, boolean);
method protected int handleGetExtendedYear();
method protected int handleGetLimit(int, int);
- method public boolean isCivil();
- method public void setCivil(boolean);
+ method public void setCalculationType(android.icu.util.IslamicCalendar.CalculationType);
field public static final int DHU_AL_HIJJAH = 11; // 0xb
field public static final int DHU_AL_QIDAH = 10; // 0xa
field public static final int JUMADA_1 = 4; // 0x4
@@ -18811,7 +18798,6 @@
method public int getMicro();
method public int getMilli();
method public int getMinor();
- method public static void main(java.lang.String[]);
field public static final android.icu.util.VersionInfo ICU_VERSION;
field public static final android.icu.util.VersionInfo UCOL_BUILDER_VERSION;
field public static final android.icu.util.VersionInfo UCOL_RUNTIME_VERSION;
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 5ef03d1..5b7dae6 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1147,8 +1147,7 @@
}
private Drawable getManagedProfileIconForDensity(UserHandle user, int drawableId, int density) {
- UserInfo userInfo = getUserInfo(user.getIdentifier());
- if (userInfo != null && userInfo.isManagedProfile()) {
+ if (isManagedProfile(user.getIdentifier())) {
return getDrawableForDensity(drawableId, density);
}
return null;
@@ -1156,8 +1155,7 @@
@Override
public CharSequence getUserBadgedLabel(CharSequence label, UserHandle user) {
- UserInfo userInfo = getUserInfo(user.getIdentifier());
- if (userInfo != null && userInfo.isManagedProfile()) {
+ if (isManagedProfile(user.getIdentifier())) {
return Resources.getSystem().getString(
com.android.internal.R.string.managed_profile_label_badge, label);
}
@@ -2259,17 +2257,16 @@
return drawable;
}
- private int getBadgeResIdForUser(int userHandle) {
+ private int getBadgeResIdForUser(int userId) {
// Return the framework-provided badge.
- UserInfo userInfo = getUserInfo(userHandle);
- if (userInfo != null && userInfo.isManagedProfile()) {
+ if (isManagedProfile(userId)) {
return com.android.internal.R.drawable.ic_corp_icon_badge;
}
return 0;
}
- private UserInfo getUserInfo(int userHandle) {
- return getUserManager().getUserInfo(userHandle);
+ private boolean isManagedProfile(int userId) {
+ return getUserManager().isManagedProfile(userId);
}
/** {@hide} */
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index f382241..55b107a 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -19,8 +19,11 @@
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.TypedProperties;
+import android.app.AppGlobals;
+import android.content.Context;
import android.util.Log;
+import java.io.File;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
@@ -100,14 +103,6 @@
*/
private static final String DEFAULT_TRACE_BODY = "dmtrace";
private static final String DEFAULT_TRACE_EXTENSION = ".trace";
- private static class NoPreloadHolder {
- private static final String DEFAULT_TRACE_PATH_PREFIX =
- Environment.getLegacyExternalStorageDirectory().getPath() + "/";
- private static final String DEFAULT_TRACE_FILE_PATH =
- DEFAULT_TRACE_PATH_PREFIX + DEFAULT_TRACE_BODY
- + DEFAULT_TRACE_EXTENSION;
- }
-
/**
* This class is used to retrieved various statistics about the memory mappings for this
@@ -938,109 +933,171 @@
}
/**
- * Start method tracing with default log name and buffer size. See <a
-href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
- * information about reading these files. Call stopMethodTracing() to stop
- * tracing.
+ * Start method tracing with default log name and buffer size.
+ * <p>
+ * By default, the trace file is called "dmtrace.trace" and it's placed
+ * under your package-specific directory on primary shared/external storage,
+ * as returned by {@link Context#getExternalFilesDir(String)}.
+ * <p>
+ * See <a href="{@docRoot}guide/developing/tools/traceview.html">Traceview:
+ * A Graphical Log Viewer</a> for information about reading trace files.
+ * <p class="note">
+ * When method tracing is enabled, the VM will run more slowly than usual,
+ * so the timings from the trace files should only be considered in relative
+ * terms (e.g. was run #1 faster than run #2). The times for native methods
+ * will not change, so don't try to use this to compare the performance of
+ * interpreted and native implementations of the same method. As an
+ * alternative, consider using sampling-based method tracing via
+ * {@link #startMethodTracingSampling(String, int, int)} or "native" tracing
+ * in the emulator via {@link #startNativeTracing()}.
+ * </p>
*/
public static void startMethodTracing() {
- VMDebug.startMethodTracing(fixTraceName(null), 0, 0, false, 0);
+ VMDebug.startMethodTracing(fixTracePath(null), 0, 0, false, 0);
}
/**
- * Start method tracing, specifying the trace log file name. The trace
- * file will be put under "/sdcard" unless an absolute path is given.
- * See <a
- href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
- * information about reading trace files.
- *
- * @param traceName Name for the trace log file to create.
- * If {@code traceName} is null, this value defaults to "/sdcard/dmtrace.trace".
- * If the files already exist, they will be truncated.
- * If the trace file given does not end in ".trace", it will be appended for you.
- */
- public static void startMethodTracing(String traceName) {
- startMethodTracing(traceName, 0, 0);
- }
-
- /**
- * Start method tracing, specifying the trace log file name and the
- * buffer size. The trace files will be put under "/sdcard" unless an
- * absolute path is given. See <a
- href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
- * information about reading trace files.
- * @param traceName Name for the trace log file to create.
- * If {@code traceName} is null, this value defaults to "/sdcard/dmtrace.trace".
- * If the files already exist, they will be truncated.
- * If the trace file given does not end in ".trace", it will be appended for you.
- *
- * @param bufferSize The maximum amount of trace data we gather. If not given, it defaults to 8MB.
- */
- public static void startMethodTracing(String traceName, int bufferSize) {
- startMethodTracing(traceName, bufferSize, 0);
- }
-
- /**
- * Start method tracing, specifying the trace log file name and the
- * buffer size. The trace files will be put under "/sdcard" unless an
- * absolute path is given. See <a
- href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
- * information about reading trace files.
- *
+ * Start method tracing, specifying the trace log file path.
* <p>
- * When method tracing is enabled, the VM will run more slowly than
- * usual, so the timings from the trace files should only be considered
- * in relative terms (e.g. was run #1 faster than run #2). The times
- * for native methods will not change, so don't try to use this to
- * compare the performance of interpreted and native implementations of the
- * same method. As an alternative, consider using sampling-based method
- * tracing via {@link #startMethodTracingSampling(String, int, int)} or
- * "native" tracing in the emulator via {@link #startNativeTracing()}.
+ * When a relative file path is given, the trace file will be placed under
+ * your package-specific directory on primary shared/external storage, as
+ * returned by {@link Context#getExternalFilesDir(String)}.
+ * <p>
+ * See <a href="{@docRoot}guide/developing/tools/traceview.html">Traceview:
+ * A Graphical Log Viewer</a> for information about reading trace files.
+ * <p class="note">
+ * When method tracing is enabled, the VM will run more slowly than usual,
+ * so the timings from the trace files should only be considered in relative
+ * terms (e.g. was run #1 faster than run #2). The times for native methods
+ * will not change, so don't try to use this to compare the performance of
+ * interpreted and native implementations of the same method. As an
+ * alternative, consider using sampling-based method tracing via
+ * {@link #startMethodTracingSampling(String, int, int)} or "native" tracing
+ * in the emulator via {@link #startNativeTracing()}.
* </p>
*
- * @param traceName Name for the trace log file to create.
- * If {@code traceName} is null, this value defaults to "/sdcard/dmtrace.trace".
- * If the files already exist, they will be truncated.
- * If the trace file given does not end in ".trace", it will be appended for you.
- * @param bufferSize The maximum amount of trace data we gather. If not given, it defaults to 8MB.
- * @param flags Flags to control method tracing. The only one that is currently defined is {@link #TRACE_COUNT_ALLOCS}.
+ * @param tracePath Path to the trace log file to create. If {@code null},
+ * this will default to "dmtrace.trace". If the file already
+ * exists, it will be truncated. If the path given does not end
+ * in ".trace", it will be appended for you.
*/
- public static void startMethodTracing(String traceName, int bufferSize,
- int flags) {
- VMDebug.startMethodTracing(fixTraceName(traceName), bufferSize, flags, false, 0);
+ public static void startMethodTracing(String tracePath) {
+ startMethodTracing(tracePath, 0, 0);
+ }
+
+ /**
+ * Start method tracing, specifying the trace log file name and the buffer
+ * size.
+ * <p>
+ * When a relative file path is given, the trace file will be placed under
+ * your package-specific directory on primary shared/external storage, as
+ * returned by {@link Context#getExternalFilesDir(String)}.
+ * <p>
+ * See <a href="{@docRoot}guide/developing/tools/traceview.html">Traceview:
+ * A Graphical Log Viewer</a> for information about reading trace files.
+ * <p class="note">
+ * When method tracing is enabled, the VM will run more slowly than usual,
+ * so the timings from the trace files should only be considered in relative
+ * terms (e.g. was run #1 faster than run #2). The times for native methods
+ * will not change, so don't try to use this to compare the performance of
+ * interpreted and native implementations of the same method. As an
+ * alternative, consider using sampling-based method tracing via
+ * {@link #startMethodTracingSampling(String, int, int)} or "native" tracing
+ * in the emulator via {@link #startNativeTracing()}.
+ * </p>
+ *
+ * @param tracePath Path to the trace log file to create. If {@code null},
+ * this will default to "dmtrace.trace". If the file already
+ * exists, it will be truncated. If the path given does not end
+ * in ".trace", it will be appended for you.
+ * @param bufferSize The maximum amount of trace data we gather. If not
+ * given, it defaults to 8MB.
+ */
+ public static void startMethodTracing(String tracePath, int bufferSize) {
+ startMethodTracing(tracePath, bufferSize, 0);
+ }
+
+ /**
+ * Start method tracing, specifying the trace log file name, the buffer
+ * size, and flags.
+ * <p>
+ * When a relative file path is given, the trace file will be placed under
+ * your package-specific directory on primary shared/external storage, as
+ * returned by {@link Context#getExternalFilesDir(String)}.
+ * <p>
+ * See <a href="{@docRoot}guide/developing/tools/traceview.html">Traceview:
+ * A Graphical Log Viewer</a> for information about reading trace files.
+ * <p class="note">
+ * When method tracing is enabled, the VM will run more slowly than usual,
+ * so the timings from the trace files should only be considered in relative
+ * terms (e.g. was run #1 faster than run #2). The times for native methods
+ * will not change, so don't try to use this to compare the performance of
+ * interpreted and native implementations of the same method. As an
+ * alternative, consider using sampling-based method tracing via
+ * {@link #startMethodTracingSampling(String, int, int)} or "native" tracing
+ * in the emulator via {@link #startNativeTracing()}.
+ * </p>
+ *
+ * @param tracePath Path to the trace log file to create. If {@code null},
+ * this will default to "dmtrace.trace". If the file already
+ * exists, it will be truncated. If the path given does not end
+ * in ".trace", it will be appended for you.
+ * @param bufferSize The maximum amount of trace data we gather. If not
+ * given, it defaults to 8MB.
+ * @param flags Flags to control method tracing. The only one that is
+ * currently defined is {@link #TRACE_COUNT_ALLOCS}.
+ */
+ public static void startMethodTracing(String tracePath, int bufferSize, int flags) {
+ VMDebug.startMethodTracing(fixTracePath(tracePath), bufferSize, flags, false, 0);
}
/**
* Start sampling-based method tracing, specifying the trace log file name,
- * the buffer size, and the sampling interval. The trace files will be put
- * under "/sdcard" unless an absolute path is given. See <a
- href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a>
- * for information about reading trace files.
+ * the buffer size, and the sampling interval.
+ * <p>
+ * When a relative file path is given, the trace file will be placed under
+ * your package-specific directory on primary shared/external storage, as
+ * returned by {@link Context#getExternalFilesDir(String)}.
+ * <p>
+ * See <a href="{@docRoot}guide/developing/tools/traceview.html">Traceview:
+ * A Graphical Log Viewer</a> for information about reading trace files.
*
- * @param traceName Name for the trace log file to create.
- * If {@code traceName} is null, this value defaults to "/sdcard/dmtrace.trace".
- * If the files already exist, they will be truncated.
- * If the trace file given does not end in ".trace", it will be appended for you.
- * @param bufferSize The maximum amount of trace data we gather. If not given, it defaults to 8MB.
- * @param intervalUs The amount of time between each sample in microseconds.
+ * @param tracePath Path to the trace log file to create. If {@code null},
+ * this will default to "dmtrace.trace". If the file already
+ * exists, it will be truncated. If the path given does not end
+ * in ".trace", it will be appended for you.
+ * @param bufferSize The maximum amount of trace data we gather. If not
+ * given, it defaults to 8MB.
+ * @param intervalUs The amount of time between each sample in microseconds.
*/
- public static void startMethodTracingSampling(String traceName,
- int bufferSize, int intervalUs) {
- VMDebug.startMethodTracing(fixTraceName(traceName), bufferSize, 0, true, intervalUs);
+ public static void startMethodTracingSampling(String tracePath, int bufferSize,
+ int intervalUs) {
+ VMDebug.startMethodTracing(fixTracePath(tracePath), bufferSize, 0, true, intervalUs);
}
-
+
/**
* Formats name of trace log file for method tracing.
*/
- private static String fixTraceName(String traceName) {
- if (traceName == null)
- traceName = NoPreloadHolder.DEFAULT_TRACE_FILE_PATH;
- if (traceName.charAt(0) != '/')
- traceName = NoPreloadHolder.DEFAULT_TRACE_PATH_PREFIX + traceName;
- if (!traceName.endsWith(DEFAULT_TRACE_EXTENSION))
- traceName = traceName + DEFAULT_TRACE_EXTENSION;
+ private static String fixTracePath(String tracePath) {
+ if (tracePath == null || tracePath.charAt(0) != '/') {
+ final Context context = AppGlobals.getInitialApplication();
+ final File dir;
+ if (context != null) {
+ dir = context.getExternalFilesDir(null);
+ } else {
+ dir = Environment.getExternalStorageDirectory();
+ }
- return traceName;
+ if (tracePath == null) {
+ tracePath = new File(dir, DEFAULT_TRACE_BODY).getAbsolutePath();
+ } else {
+ tracePath = new File(dir, tracePath).getAbsolutePath();
+ }
+ }
+ if (!tracePath.endsWith(DEFAULT_TRACE_EXTENSION)) {
+ tracePath += DEFAULT_TRACE_EXTENSION;
+ }
+ return tracePath;
}
/**
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index bc2566b..c38bf3c 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -76,4 +76,5 @@
PersistableBundle getSeedAccountOptions();
void clearSeedAccountData();
boolean someUserHasSeedAccount(in String accountName, in String accountType);
+ boolean isManagedProfile(int userId);
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 0ff0154..707d5f5 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -822,8 +822,28 @@
*/
@SystemApi
public boolean isManagedProfile() {
- UserInfo user = getUserInfo(UserHandle.myUserId());
- return user != null ? user.isManagedProfile() : false;
+ try {
+ return mService.isManagedProfile(UserHandle.myUserId());
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Checks if the specified user is a managed profile.
+ * Requires {@link android.Manifest.permission#MANAGE_USERS} permission, otherwise the caller
+ * must be in the same profile group of specified user.
+ *
+ * @return whether the specified user is a managed profile.
+ * @hide
+ */
+ @SystemApi
+ public boolean isManagedProfile(@UserIdInt int userId) {
+ try {
+ return mService.isManagedProfile(userId);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
}
/**
@@ -964,8 +984,7 @@
/**
* Returns the UserInfo object describing a specific user.
- * Requires {@link android.Manifest.permission#MANAGE_USERS} permission or the caller is
- * in the same profile group of target user.
+ * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
* @param userHandle the user handle of the user whose information is being requested.
* @return the UserInfo object for a specific user.
* @hide
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index ea0597d..4b70649 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -438,6 +438,10 @@
final Intent intent = new Intent(DocumentsContract.ACTION_BROWSE);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setData(uri);
+
+ // note that docsui treats this as *force* show advanced. So sending
+ // false permits advanced to be shown based on user preferences.
+ intent.putExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, isPrimary());
intent.putExtra(DocumentsContract.EXTRA_SHOW_FILESIZE, true);
return intent;
}
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 4ad7969..4412459 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -93,6 +93,9 @@
public static final String EXTRA_PACKAGE_NAME = "android.content.extra.PACKAGE_NAME";
/** {@hide} */
+ public static final String EXTRA_SHOW_ADVANCED = "android.content.extra.SHOW_ADVANCED";
+
+ /** {@hide} */
public static final String EXTRA_SHOW_FILESIZE = "android.content.extra.SHOW_FILESIZE";
/** {@hide} */
@@ -556,13 +559,22 @@
public static final int FLAG_EMPTY = 1 << 16;
/**
+ * Flag indicating that this root should only be visible to advanced
+ * users.
+ *
+ * @see #COLUMN_FLAGS
+ * @hide
+ */
+ public static final int FLAG_ADVANCED = 1 << 17;
+
+ /**
* Flag indicating that this root has settings.
*
* @see #COLUMN_FLAGS
* @see DocumentsContract#ACTION_DOCUMENT_ROOT_SETTINGS
* @hide
*/
- public static final int FLAG_HAS_SETTINGS = 1 << 17;
+ public static final int FLAG_HAS_SETTINGS = 1 << 18;
/**
* Flag indicating that this root is on removable SD card storage.
@@ -570,7 +582,7 @@
* @see #COLUMN_FLAGS
* @hide
*/
- public static final int FLAG_REMOVABLE_SD = 1 << 18;
+ public static final int FLAG_REMOVABLE_SD = 1 << 19;
/**
* Flag indicating that this root is on removable USB storage.
@@ -578,7 +590,7 @@
* @see #COLUMN_FLAGS
* @hide
*/
- public static final int FLAG_REMOVABLE_USB = 1 << 19;
+ public static final int FLAG_REMOVABLE_USB = 1 << 20;
}
/**
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 30607dd..60f05448 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -417,6 +417,7 @@
<protected-broadcast android:name="android.os.action.ACTION_EFFECTS_SUPPRESSOR_CHANGED" />
<protected-broadcast android:name="android.os.action.LIGHT_DEVICE_IDLE_MODE_CHANGED" />
<protected-broadcast android:name="android.os.storage.action.VOLUME_STATE_CHANGED" />
+ <protected-broadcast android:name="android.os.storage.action.DISK_SCANNED" />
<protected-broadcast android:name="com.android.server.action.UPDATE_TWILIGHT_STATE" />
<protected-broadcast android:name="com.android.server.device_idle.STEP_IDLE_STATE" />
<protected-broadcast android:name="com.android.server.device_idle.STEP_LIGHT_IDLE_STATE" />
diff --git a/docs/html/guide/topics/data/data-storage.jd b/docs/html/guide/topics/data/data-storage.jd
index 46db371..0d3bb4d 100644
--- a/docs/html/guide/topics/data/data-storage.jd
+++ b/docs/html/guide/topics/data/data-storage.jd
@@ -178,6 +178,19 @@
android.content.Context#MODE_WORLD_READABLE}, and {@link
android.content.Context#MODE_WORLD_WRITEABLE}.</p>
+<p class="note"><strong>Note:</strong> The constants {@link
+android.content.Context#MODE_WORLD_READABLE} and {@link
+android.content.Context#MODE_WORLD_WRITEABLE} have been deprecated since API level 17. Since
+API level 24 their use will result in a {@link java.lang.SecurityException} to be thrown.
+This means that apps targeting API level 24 and higher
+cannot share private files by name, and attempts to share a "file://" URI will result in a
+{@link android.os.FileUriExposedException} to be thrown. If your app needs to share private
+files with other apps, it may use a {@link android.support.v4.content.FileProvider} with
+the {@link android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION}.
+See also <a
+href="{@docRoot}training/secure-file-sharing/index.html">Sharing Files</a>.
+</p>
+
<p>To read a file from internal storage:</p>
<ol>
diff --git a/docs/html/training/basics/data-storage/files.jd b/docs/html/training/basics/data-storage/files.jd
index 49a9169..983d59a 100644
--- a/docs/html/training/basics/data-storage/files.jd
+++ b/docs/html/training/basics/data-storage/files.jd
@@ -59,7 +59,7 @@
<p><b>Internal storage:</b></p>
<ul>
<li>It's always available.</li>
-<li>Files saved here are accessible by only your app by default.</li>
+<li>Files saved here are accessible by only your app.</li>
<li>When the user uninstalls your app, the system removes all your app's files from
internal storage.</li>
</ul>
@@ -83,6 +83,12 @@
with other apps or allow the user to access with a computer.</p>
</div>
+<p class="note">
+<strong>Note:</strong> Before API level 24, internal files could be made accessible to other
+apps by means of relaxing file system permissions. This is no longer the case. If you wish
+to make the content of a private file accessible to other apps, your app may use the
+{@link android.support.v4.content.FileProvider}. See <a
+href="{@docRoot}training/secure-file-sharing/index.html">Sharing Files</a>.</p>
<p class="note" style="clear:both">
<strong>Tip:</strong> Although apps are installed onto the internal storage by
diff --git a/packages/DocumentsUI/Android.mk b/packages/DocumentsUI/Android.mk
index d5e48b5..3197abd 100644
--- a/packages/DocumentsUI/Android.mk
+++ b/packages/DocumentsUI/Android.mk
@@ -31,9 +31,13 @@
--extra-packages android.support.v7.recyclerview
LOCAL_JACK_FLAGS := \
- -D jack.assert.policy=enable \
-D jack.optimization.inner-class.accessors=true
+# Only enable asserts on userdebug/eng builds
+ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT)))
+LOCAL_JACK_FLAGS += -D jack.assert.policy=enable
+endif
+
LOCAL_PACKAGE_NAME := DocumentsUI
LOCAL_CERTIFICATE := platform
diff --git a/packages/DocumentsUI/res/values/config.xml b/packages/DocumentsUI/res/values/config.xml
index ebb3969..408603e 100644
--- a/packages/DocumentsUI/res/values/config.xml
+++ b/packages/DocumentsUI/res/values/config.xml
@@ -24,5 +24,6 @@
<!-- Indicates if the home directory should be hidden in the roots list, that is presented
in the drawer/left side panel ) -->
<bool name="home_root_hidden">true</bool>
-
+ <!-- Indicates if the advanced roots like internal storage should be hidden in the roots list) -->
+ <bool name="advanced_roots_hidden">true</bool>
</resources>
diff --git a/packages/DocumentsUI/res/values/styles.xml b/packages/DocumentsUI/res/values/styles.xml
index a548d89..b16554c 100644
--- a/packages/DocumentsUI/res/values/styles.xml
+++ b/packages/DocumentsUI/res/values/styles.xml
@@ -36,6 +36,8 @@
<item name="android:windowActionBar">false</item>
<item name="android:windowActionModeOverlay">true</item>
<item name="android:windowNoTitle">true</item>
+ <item name="android:windowTranslucentStatus">true</item>
+ <item name="android:fitsSystemWindows">false</item>
<item name="android:windowSoftInputMode">stateUnspecified|adjustUnspecified</item>
</style>
@@ -43,7 +45,7 @@
<style name="TrimmedHorizontalProgressBar" parent="android:Widget.Material.ProgressBar.Horizontal">
<item name="android:indeterminateDrawable">@drawable/progress_indeterminate_horizontal_material_trimmed</item>
<item name="android:minHeight">3dp</item>
- <item name="android:maxHeight">3dp</item>
+ <item name="android:maxHeight">3dp</item>
</style>
</resources>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index fe61094..3b300d0 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -127,6 +127,7 @@
mSearchManager = new SearchViewManager(this, icicle);
DocumentsToolbar toolbar = (DocumentsToolbar) findViewById(R.id.toolbar);
+ Display.adjustToolbar(toolbar, this);
setActionBar(toolbar);
mNavigator = new NavigationView(
mDrawer,
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Display.java b/packages/DocumentsUI/src/com/android/documentsui/Display.java
index bae2d58..d46a3ea 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Display.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Display.java
@@ -20,13 +20,15 @@
import android.content.Context;
import android.graphics.Point;
import android.util.TypedValue;
+import android.view.WindowManager;
+import android.widget.Toolbar;
/*
* Convenience class for getting display related attributes
*/
public final class Display {
/*
- * Returns the screen width in pixels.
+ * Returns the screen width in raw pixels.
*/
public static float screenWidth(Activity activity) {
Point size = new Point();
@@ -42,15 +44,44 @@
}
/*
- * Returns action bar height in pixels.
+ * Returns action bar height in raw pixels.
*/
public static float actionBarHeight(Context context) {
- int actionBarHeight = 0;
+ int height = 0;
TypedValue tv = new TypedValue();
if (context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
- actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data,
+ height = TypedValue.complexToDimensionPixelSize(tv.data,
context.getResources().getDisplayMetrics());
}
- return actionBarHeight;
+ return height;
+ }
+
+ /*
+ * Returns status bar height in raw pixels.
+ */
+ private static int statusBarHeight(Context context) {
+ int height = 0;
+ int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen",
+ "android");
+ if (resourceId > 0) {
+ height = context.getResources().getDimensionPixelSize(resourceId);
+ }
+ return height;
+ }
+
+ /*
+ * Adjusts toolbar for the layout with translucent status bar. Increases the
+ * height of the toolbar and adds padding at the top to accommodate status bar visible above
+ * toolbar.
+ */
+ public static void adjustToolbar(Toolbar toolbar, Activity activity) {
+ if ((activity.getWindow().getAttributes().flags
+ & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) != 0) {
+ int statusBarHeight = Display.statusBarHeight(activity);
+ toolbar.getLayoutParams().height = (int) (Display.actionBarHeight(activity)
+ + statusBarHeight);
+ toolbar.setPadding(toolbar.getPaddingLeft(), statusBarHeight, toolbar.getPaddingRight(),
+ toolbar.getPaddingBottom());
+ }
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java b/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java
index 020f2c0..2dbb730 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java
@@ -55,7 +55,7 @@
View drawer = activity.findViewById(R.id.drawer_roots);
Toolbar toolbar = (Toolbar) activity.findViewById(R.id.roots_toolbar);
-
+ Display.adjustToolbar(toolbar, activity);
drawer.getLayoutParams().width = calculateDrawerWidth(activity);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
index 54e6287..1864431 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
@@ -320,6 +320,8 @@
if (root.isHome() && isHomeRootHidden(context)) {
continue;
+ } else if (root.isAdvanced() && areAdvancedRootsHidden(context)) {
+ continue;
} else if (root.isLibrary()) {
if (DEBUG) Log.d(TAG, "Adding " + root + " as library.");
libraries.add(item);
@@ -377,6 +379,13 @@
return context.getResources().getBoolean(R.bool.home_root_hidden);
}
+ /*
+ * Indicates if the advanced roots should be hidden.
+ */
+ private boolean areAdvancedRootsHidden(Context context) {
+ return context.getResources().getBoolean(R.bool.advanced_roots_hidden);
+ }
+
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final Item item = getItem(position);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
index 3960475..0709652 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
@@ -298,6 +298,10 @@
return (flags & Root.FLAG_SUPPORTS_SEARCH) != 0;
}
+ public boolean isAdvanced() {
+ return (flags & Root.FLAG_ADVANCED) != 0;
+ }
+
public boolean isLocalOnly() {
return (flags & Root.FLAG_LOCAL_ONLY) != 0;
}
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 9a51b05..62f33bf 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -196,6 +196,7 @@
if (volume.isPrimary()) {
// save off the primary volume for subsequent "Home" dir initialization.
primaryVolume = volume;
+ root.flags |= Root.FLAG_ADVANCED;
}
// Dunno when this would NOT be the case, but never hurts to be correct.
if (volume.isMountedWritable()) {
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 1aee490..a2a3fd3 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -793,4 +793,23 @@
<!-- Label for length of time until battery is charged [CHAR LIMIT=20] -->
<string name="remaining_length_format"><xliff:g name="time" example="3 hours">%1$s</xliff:g> left</string>
+ <!-- Hint text for the IP address -->
+ <string name="wifi_ip_address_hint" translatable="false">192.168.1.128</string>
+ <!-- Hint text for DNS -->
+ <string name="wifi_dns1_hint" translatable="false">8.8.8.8</string>
+ <!-- Hint text for DNS -->
+ <string name="wifi_dns2_hint" translatable="false">8.8.4.4</string>
+ <!-- Hint text for the gateway -->
+ <string name="wifi_gateway_hint" translatable="false">192.168.1.1</string>
+ <!-- Hint text for network prefix length -->
+ <string name="wifi_network_prefix_length_hint" translatable="false">24</string>
+ <!-- HTTP proxy settings. The hint text field for port. -->
+ <string name="proxy_port_hint" translatable="false">8080</string>
+ <!-- HTTP proxy settings. Hint for Proxy-Auto Config URL. -->
+ <string name="proxy_url_hint" translatable="false">https://www.example.com/proxy.pac</string>
+ <!-- HTTP proxy settings. The hint text for proxy exclusion list. -->
+ <string name="proxy_exclusionlist_hint" translatable="false">example.com,mycomp.test.com,localhost</string>
+ <!-- HTTP proxy settings. The hint text field for the hostname. -->
+ <string name="proxy_hostname_hint" translatable="false">proxy.example.com</string>
+
</resources>
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 7fae0ee..c9582ea 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -149,6 +149,10 @@
// Passed to Message.obtain() when msg.arg2 is not used.
private static final int UNUSED_ARG2 = -2;
+ // Maximum progress displayed (like 99.00%).
+ private static final int CAPPED_PROGRESS = 9900;
+ private static final int CAPPED_MAX = 10000;
+
/**
* Delay before a screenshot is taken.
* <p>
@@ -427,7 +431,7 @@
final NumberFormat nf = NumberFormat.getPercentInstance();
nf.setMinimumFractionDigits(2);
nf.setMaximumFractionDigits(2);
- final String percentText = nf.format((double) info.progress / info.max);
+ final String percentageText = nf.format((double) info.progress / info.max);
final Action cancelAction = new Action.Builder(null, mContext.getString(
com.android.internal.R.string.cancel), newCancelIntent(mContext, info)).build();
final Intent infoIntent = new Intent(mContext, BugreportProgressService.class);
@@ -458,7 +462,7 @@
.setContentTitle(title)
.setTicker(title)
.setContentText(name)
- .setContentInfo(percentText)
+ .setContentInfo(percentageText)
.setProgress(info.max, info.progress, false)
.setOngoing(true)
.setContentIntent(infoPendingIntent)
@@ -472,7 +476,7 @@
}
if (DEBUG) {
Log.d(TAG, "Sending 'Progress' notification for id " + info.id + "(pid " + info.pid
- + "): " + percentText);
+ + "): " + percentageText);
}
NotificationManager.from(mContext).notify(TAG, info.id, notification);
}
@@ -545,25 +549,47 @@
}
activeProcesses++;
final String progressKey = DUMPSTATE_PREFIX + pid + PROGRESS_SUFFIX;
- final int progress = SystemProperties.getInt(progressKey, 0);
- if (progress == 0) {
+ info.realProgress = SystemProperties.getInt(progressKey, 0);
+ if (info.realProgress == 0) {
Log.v(TAG, "System property " + progressKey + " is not set yet");
}
- final int max = SystemProperties.getInt(DUMPSTATE_PREFIX + pid + MAX_SUFFIX, 0);
- final boolean maxChanged = max > 0 && max != info.max;
- final boolean progressChanged = progress > 0 && progress != info.progress;
+ final String maxKey = DUMPSTATE_PREFIX + pid + MAX_SUFFIX;
+ info.realMax = SystemProperties.getInt(maxKey, info.max);
+ if (info.realMax <= 0 ) {
+ Log.w(TAG, "Property " + maxKey + " is not positive: " + info.max);
+ continue;
+ }
+ /*
+ * Checks whether the progress changed in a way that should be displayed to the user:
+ * - info.progress / info.max represents the displayed progress
+ * - info.realProgress / info.realMax represents the real progress
+ * - since the real progress can decrease, the displayed progress is only updated if it
+ * increases
+ * - the displayed progress is capped at a maximum (like 99%)
+ */
+ final int oldPercentage = (CAPPED_MAX * info.progress) / info.max;
+ int newPercentage = (CAPPED_MAX * info.realProgress) / info.realMax;
+ int max = info.realMax;
+ int progress = info.realProgress;
- if (progressChanged || maxChanged) {
- if (progressChanged) {
- if (DEBUG) Log.v(TAG, "Updating progress for PID " + pid + "(id: " + id
- + ") from " + info.progress + " to " + progress);
- info.progress = progress;
+ if (newPercentage > CAPPED_PROGRESS) {
+ progress = newPercentage = CAPPED_PROGRESS;
+ max = CAPPED_MAX;
+ }
+
+ if (newPercentage > oldPercentage) {
+ if (DEBUG) {
+ if (progress != info.progress) {
+ Log.v(TAG, "Updating progress for PID " + pid + "(id: " + id + ") from "
+ + info.progress + " to " + progress);
+ }
+ if (max != info.max) {
+ Log.v(TAG, "Updating max progress for PID " + pid + "(id: " + id + ") from "
+ + info.max + " to " + max);
+ }
}
- if (maxChanged) {
- Log.i(TAG, "Updating max progress for PID " + pid + "(id: " + id
- + ") from " + info.max + " to " + max);
- info.max = max;
- }
+ info.progress = progress;
+ info.max = max;
info.lastUpdate = System.currentTimeMillis();
updateProgress(info);
} else {
@@ -1450,16 +1476,26 @@
String description;
/**
- * Maximum progress of the bugreport generation.
+ * Maximum progress of the bugreport generation as displayed by the UI.
*/
int max;
/**
- * Current progress of the bugreport generation.
+ * Current progress of the bugreport generation as displayed by the UI.
*/
int progress;
/**
+ * Maximum progress of the bugreport generation as reported by dumpstate.
+ */
+ int realMax;
+
+ /**
+ * Current progress of the bugreport generation as reported by dumpstate.
+ */
+ int realProgress;
+
+ /**
* Time of the last progress update.
*/
long lastUpdate = System.currentTimeMillis();
@@ -1568,10 +1604,12 @@
@Override
public String toString() {
final float percent = ((float) progress * 100 / max);
+ final float realPercent = ((float) realProgress * 100 / realMax);
return "id: " + id + ", pid: " + pid + ", name: " + name + ", finished: " + finished
+ "\n\ttitle: " + title + "\n\tdescription: " + description
+ "\n\tfile: " + bugreportFile + "\n\tscreenshots: " + screenshotFiles
+ "\n\tprogress: " + progress + "/" + max + " (" + percent + ")"
+ + "\n\treal progress: " + realProgress + "/" + realMax + " (" + realPercent + ")"
+ "\n\tlast_update: " + getFormattedLastUpdate()
+ "\naddingDetailsToZip: " + addingDetailsToZip
+ " addedDetailsToZip: " + addedDetailsToZip;
@@ -1587,6 +1625,8 @@
description = in.readString();
max = in.readInt();
progress = in.readInt();
+ realMax = in.readInt();
+ realProgress = in.readInt();
lastUpdate = in.readLong();
formattedLastUpdate = in.readString();
bugreportFile = readFile(in);
@@ -1609,6 +1649,8 @@
dest.writeString(description);
dest.writeInt(max);
dest.writeInt(progress);
+ dest.writeInt(realMax);
+ dest.writeInt(realProgress);
dest.writeLong(lastUpdate);
dest.writeString(getFormattedLastUpdate());
writeFile(dest, bugreportFile);
diff --git a/packages/Shell/src/com/android/shell/BugreportStorageProvider.java b/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
index 49759c5..814aa8c 100644
--- a/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
+++ b/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
@@ -56,7 +56,7 @@
final MatrixCursor result = new MatrixCursor(resolveRootProjection(projection));
final RowBuilder row = result.newRow();
row.add(Root.COLUMN_ROOT_ID, DOC_ID_ROOT);
- row.add(Root.COLUMN_FLAGS, Root.FLAG_LOCAL_ONLY);
+ row.add(Root.COLUMN_FLAGS, Root.FLAG_LOCAL_ONLY | Root.FLAG_ADVANCED);
row.add(Root.COLUMN_ICON, android.R.mipmap.sym_def_app_icon);
row.add(Root.COLUMN_TITLE, getContext().getString(R.string.bugreport_storage_title));
row.add(Root.COLUMN_DOCUMENT_ID, DOC_ID_ROOT);
diff --git a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
index 17f6f6b..e1e0c3b 100644
--- a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
+++ b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
@@ -26,6 +26,7 @@
import static com.android.shell.BugreportProgressService.EXTRA_SCREENSHOT;
import static com.android.shell.BugreportProgressService.INTENT_BUGREPORT_FINISHED;
import static com.android.shell.BugreportProgressService.INTENT_BUGREPORT_STARTED;
+import static com.android.shell.BugreportProgressService.POLLING_FREQUENCY;
import static com.android.shell.BugreportProgressService.SCREENSHOT_DELAY_SECONDS;
import java.io.BufferedOutputStream;
@@ -92,7 +93,7 @@
private static final String TAG = "BugreportReceiverTest";
// Timeout for UI operations, in milliseconds.
- private static final int TIMEOUT = (int) BugreportProgressService.POLLING_FREQUENCY * 4;
+ private static final int TIMEOUT = (int) POLLING_FREQUENCY * 4;
// Timeout for when waiting for a screenshot to finish.
private static final int SAFE_SCREENSHOT_DELAY = SCREENSHOT_DELAY_SECONDS + 10;
@@ -190,8 +191,30 @@
SystemProperties.set(PROGRESS_PROPERTY, "500");
assertProgressNotification(NAME, nf.format(0.50));
+ SystemProperties.set(PROGRESS_PROPERTY, "950");
+ assertProgressNotification(NAME, nf.format(0.95));
+
+ // Make sure progress never goes back...
SystemProperties.set(MAX_PROPERTY, "2000");
- assertProgressNotification(NAME, nf.format(0.25));
+ Thread.sleep(POLLING_FREQUENCY + DateUtils.SECOND_IN_MILLIS);
+ assertProgressNotification(NAME, nf.format(0.95));
+
+ SystemProperties.set(PROGRESS_PROPERTY, "1000");
+ assertProgressNotification(NAME, nf.format(0.95));
+
+ // ...only forward...
+ SystemProperties.set(PROGRESS_PROPERTY, "1902");
+ assertProgressNotification(NAME, nf.format(0.9510));
+
+ SystemProperties.set(PROGRESS_PROPERTY, "1960");
+ assertProgressNotification(NAME, nf.format(0.98));
+
+ // ...but never more than the capped value.
+ SystemProperties.set(PROGRESS_PROPERTY, "2000");
+ assertProgressNotification(NAME, nf.format(0.99));
+
+ SystemProperties.set(PROGRESS_PROPERTY, "3000");
+ assertProgressNotification(NAME, nf.format(0.99));
Bundle extras =
sendBugreportFinishedAndGetSharedIntent(ID, mPlainTextPath, mScreenshotPath);
diff --git a/packages/Shell/tests/src/com/android/shell/UiBot.java b/packages/Shell/tests/src/com/android/shell/UiBot.java
index 384c3da..5bfe1a0 100644
--- a/packages/Shell/tests/src/com/android/shell/UiBot.java
+++ b/packages/Shell/tests/src/com/android/shell/UiBot.java
@@ -32,7 +32,7 @@
final class UiBot {
private static final String TAG = "UiBot";
- private static final String SYSTEMUI_PACKAGED = "com.android.systemui";
+ private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
private final UiDevice mDevice;
private final int mTimeout;
@@ -51,8 +51,8 @@
public UiObject getNotification(String text) {
boolean opened = mDevice.openNotification();
Log.v(TAG, "openNotification(): " + opened);
- boolean gotIt = mDevice.wait(Until.hasObject(By.pkg(SYSTEMUI_PACKAGED)), mTimeout);
- assertTrue("could not get system ui (" + SYSTEMUI_PACKAGED + ")", gotIt);
+ boolean gotIt = mDevice.wait(Until.hasObject(By.pkg(SYSTEMUI_PACKAGE)), mTimeout);
+ assertTrue("could not get system ui (" + SYSTEMUI_PACKAGE + ")", gotIt);
return getObject(text);
}
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index 425569c..9beaba3 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -1387,6 +1387,27 @@
}
/**
+ * Name of the file that holds the object cache.
+ */
+ private static String mCachePath;
+
+ /**
+ * Gets the path to the code cache.
+ */
+ static synchronized String getCachePath() {
+ if (mCachePath == null) {
+ final String CACHE_PATH = "com.android.renderscript.cache";
+ if (RenderScriptCacheDir.mCacheDir == null) {
+ throw new RSRuntimeException("RenderScript code cache directory uninitialized.");
+ }
+ File f = new File(RenderScriptCacheDir.mCacheDir, CACHE_PATH);
+ mCachePath = f.getAbsolutePath();
+ f.mkdirs();
+ }
+ return mCachePath;
+ }
+
+ /**
* Create a RenderScript context.
*
* @param ctx The context.
@@ -1415,11 +1436,7 @@
}
// set up cache directory for entire context
- final String CACHE_PATH = "com.android.renderscript.cache";
- File f = new File(RenderScriptCacheDir.mCacheDir, CACHE_PATH);
- String mCachePath = f.getAbsolutePath();
- f.mkdirs();
- rs.nContextSetCacheDir(mCachePath);
+ rs.nContextSetCacheDir(RenderScript.getCachePath());
rs.mMessageThread = new MessageThread(rs);
rs.mMessageThread.start();
diff --git a/rs/java/android/renderscript/ScriptC.java b/rs/java/android/renderscript/ScriptC.java
index bf706c1..00ebe57 100644
--- a/rs/java/android/renderscript/ScriptC.java
+++ b/rs/java/android/renderscript/ScriptC.java
@@ -84,13 +84,6 @@
setID(id);
}
- /**
- * Name of the file that holds the object cache.
- */
- private static final String CACHE_PATH = "com.android.renderscript.cache";
-
- static String mCachePath;
-
private static synchronized long internalCreate(RenderScript rs, Resources resources, int resourceID) {
byte[] pgm;
int pgmLength;
@@ -122,26 +115,12 @@
String resName = resources.getResourceEntryName(resourceID);
- // Create the RS cache path if we haven't done so already.
- if (mCachePath == null) {
- File f = new File(RenderScriptCacheDir.mCacheDir, CACHE_PATH);
- mCachePath = f.getAbsolutePath();
- f.mkdirs();
- }
// Log.v(TAG, "Create script for resource = " + resName);
- return rs.nScriptCCreate(resName, mCachePath, pgm, pgmLength);
+ return rs.nScriptCCreate(resName, RenderScript.getCachePath(), pgm, pgmLength);
}
private static synchronized long internalStringCreate(RenderScript rs, String resName, byte[] bitcode) {
- // Create the RS cache path if we haven't done so already.
- if (mCachePath == null) {
- File f = new File(RenderScriptCacheDir.mCacheDir, CACHE_PATH);
- mCachePath = f.getAbsolutePath();
- f.mkdirs();
- }
// Log.v(TAG, "Create script for resource = " + resName);
- return rs.nScriptCCreate(resName, mCachePath, bitcode, bitcode.length);
+ return rs.nScriptCCreate(resName, RenderScript.getCachePath(), bitcode, bitcode.length);
}
-
-
}
diff --git a/rs/java/android/renderscript/ScriptGroup.java b/rs/java/android/renderscript/ScriptGroup.java
index 9bbacbc..9357c3bb 100644
--- a/rs/java/android/renderscript/ScriptGroup.java
+++ b/rs/java/android/renderscript/ScriptGroup.java
@@ -396,7 +396,7 @@
for (int i = 0; i < closureIDs.length; i++) {
closureIDs[i] = closures.get(i).getID(rs);
}
- long id = rs.nScriptGroup2Create(name, ScriptC.mCachePath, closureIDs);
+ long id = rs.nScriptGroup2Create(name, RenderScript.getCachePath(), closureIDs);
setID(id);
}
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index a94c8b8..e7db2a8 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -447,12 +447,8 @@
int[] ops) {
mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
Binder.getCallingPid(), Binder.getCallingUid(), null);
- String resolvedPackageName = resolvePackageName(uid, packageName);
- if (resolvedPackageName == null) {
- return Collections.emptyList();
- }
synchronized (this) {
- Ops pkgOps = getOpsRawLocked(uid, resolvedPackageName, false);
+ Ops pkgOps = getOpsLocked(uid, packageName, false);
if (pkgOps == null) {
return null;
}
@@ -470,7 +466,7 @@
private void pruneOp(Op op, int uid, String packageName) {
if (op.time == 0 && op.rejectTime == 0) {
- Ops ops = getOpsRawLocked(uid, packageName, false);
+ Ops ops = getOpsLocked(uid, packageName, false);
if (ops != null) {
ops.remove(op.op);
if (ops.size() <= 0) {
@@ -884,12 +880,8 @@
public int checkOperation(int code, int uid, String packageName) {
verifyIncomingUid(uid);
verifyIncomingOp(code);
- String resolvedPackageName = resolvePackageName(uid, packageName);
- if (resolvedPackageName == null) {
- return AppOpsManager.MODE_IGNORED;
- }
synchronized (this) {
- if (isOpRestricted(uid, code, resolvedPackageName)) {
+ if (isOpRestricted(uid, code, packageName)) {
return AppOpsManager.MODE_IGNORED;
}
code = AppOpsManager.opToSwitch(code);
@@ -900,7 +892,7 @@
return uidMode;
}
}
- Op op = getOpLocked(code, uid, resolvedPackageName, false);
+ Op op = getOpLocked(code, uid, packageName, false);
if (op == null) {
return AppOpsManager.opToDefaultMode(code);
}
@@ -976,7 +968,6 @@
@Override
public int checkPackage(int uid, String packageName) {
- Preconditions.checkNotNull(packageName);
synchronized (this) {
if (getOpsRawLocked(uid, packageName, true) != null) {
return AppOpsManager.MODE_ALLOWED;
@@ -990,39 +981,26 @@
public int noteProxyOperation(int code, String proxyPackageName,
int proxiedUid, String proxiedPackageName) {
verifyIncomingOp(code);
- final int proxyUid = Binder.getCallingUid();
- String resolveProxyPackageName = resolvePackageName(proxyUid, proxyPackageName);
- if (resolveProxyPackageName == null) {
- return AppOpsManager.MODE_IGNORED;
- }
- final int proxyMode = noteOperationUnchecked(code, proxyUid,
- resolveProxyPackageName, -1, null);
+ final int proxyMode = noteOperationUnchecked(code, Binder.getCallingUid(),
+ proxyPackageName, -1, null);
if (proxyMode != AppOpsManager.MODE_ALLOWED || Binder.getCallingUid() == proxiedUid) {
return proxyMode;
}
- String resolveProxiedPackageName = resolvePackageName(proxiedUid, proxiedPackageName);
- if (resolveProxiedPackageName == null) {
- return AppOpsManager.MODE_IGNORED;
- }
- return noteOperationUnchecked(code, proxiedUid, resolveProxiedPackageName,
- proxyMode, resolveProxyPackageName);
+ return noteOperationUnchecked(code, proxiedUid, proxiedPackageName,
+ Binder.getCallingUid(), proxyPackageName);
}
@Override
public int noteOperation(int code, int uid, String packageName) {
verifyIncomingUid(uid);
verifyIncomingOp(code);
- String resolvedPackageName = resolvePackageName(uid, packageName);
- if (resolvedPackageName == null) {
- return AppOpsManager.MODE_IGNORED;
- }
- return noteOperationUnchecked(code, uid, resolvedPackageName, 0, null);
+ return noteOperationUnchecked(code, uid, packageName, 0, null);
}
private int noteOperationUnchecked(int code, int uid, String packageName,
int proxyUid, String proxyPackageName) {
synchronized (this) {
- Ops ops = getOpsRawLocked(uid, packageName, true);
+ Ops ops = getOpsLocked(uid, packageName, true);
if (ops == null) {
if (DEBUG) Log.d(TAG, "noteOperation: no op for code " + code + " uid " + uid
+ " package " + packageName);
@@ -1070,20 +1048,16 @@
public int startOperation(IBinder token, int code, int uid, String packageName) {
verifyIncomingUid(uid);
verifyIncomingOp(code);
- String resolvedPackageName = resolvePackageName(uid, packageName);
- if (resolvedPackageName == null) {
- return AppOpsManager.MODE_IGNORED;
- }
ClientState client = (ClientState)token;
synchronized (this) {
- Ops ops = getOpsRawLocked(uid, resolvedPackageName, true);
+ Ops ops = getOpsLocked(uid, packageName, true);
if (ops == null) {
if (DEBUG) Log.d(TAG, "startOperation: no op for code " + code + " uid " + uid
- + " package " + resolvedPackageName);
+ + " package " + packageName);
return AppOpsManager.MODE_ERRORED;
}
Op op = getOpLocked(ops, code, true);
- if (isOpRestricted(uid, code, resolvedPackageName)) {
+ if (isOpRestricted(uid, code, packageName)) {
return AppOpsManager.MODE_IGNORED;
}
final int switchCode = AppOpsManager.opToSwitch(code);
@@ -1093,7 +1067,7 @@
if (uidMode != AppOpsManager.MODE_ALLOWED) {
if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code "
+ switchCode + " (" + code + ") uid " + uid + " package "
- + resolvedPackageName);
+ + packageName);
op.rejectTime = System.currentTimeMillis();
return uidMode;
}
@@ -1101,13 +1075,12 @@
final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
if (DEBUG) Log.d(TAG, "startOperation: reject #" + op.mode + " for code "
- + switchCode + " (" + code + ") uid " + uid + " package "
- + resolvedPackageName);
+ + switchCode + " (" + code + ") uid " + uid + " package " + packageName);
op.rejectTime = System.currentTimeMillis();
return switchOp.mode;
}
if (DEBUG) Log.d(TAG, "startOperation: allowing code " + code + " uid " + uid
- + " package " + resolvedPackageName);
+ + " package " + packageName);
if (op.nesting == 0) {
op.time = System.currentTimeMillis();
op.rejectTime = 0;
@@ -1125,16 +1098,9 @@
public void finishOperation(IBinder token, int code, int uid, String packageName) {
verifyIncomingUid(uid);
verifyIncomingOp(code);
- String resolvedPackageName = resolvePackageName(uid, packageName);
- if (resolvedPackageName == null) {
- return;
- }
- if (!(token instanceof ClientState)) {
- return;
- }
- ClientState client = (ClientState) token;
+ ClientState client = (ClientState)token;
synchronized (this) {
- Op op = getOpLocked(code, uid, resolvedPackageName, true);
+ Op op = getOpLocked(code, uid, packageName, true);
if (op == null) {
return;
}
@@ -1150,9 +1116,6 @@
@Override
public int permissionToOpCode(String permission) {
- if (permission == null) {
- return AppOpsManager.OP_NONE;
- }
return AppOpsManager.permissionToOpCode(permission);
}
@@ -1202,6 +1165,15 @@
return uidState;
}
+ private Ops getOpsLocked(int uid, String packageName, boolean edit) {
+ if (uid == 0) {
+ packageName = "root";
+ } else if (uid == Process.SHELL_UID) {
+ packageName = "com.android.shell";
+ }
+ return getOpsRawLocked(uid, packageName, edit);
+ }
+
private Ops getOpsRawLocked(int uid, String packageName, boolean edit) {
UidState uidState = getUidStateLocked(uid, edit);
if (uidState == null) {
@@ -1287,7 +1259,7 @@
}
private Op getOpLocked(int code, int uid, String packageName, boolean edit) {
- Ops ops = getOpsRawLocked(uid, packageName, edit);
+ Ops ops = getOpsLocked(uid, packageName, edit);
if (ops == null) {
return null;
}
@@ -1345,7 +1317,7 @@
if (AppOpsManager.opAllowSystemBypassRestriction(code)) {
// If we are the system, bypass user restrictions for certain codes
synchronized (this) {
- Ops ops = getOpsRawLocked(uid, packageName, true);
+ Ops ops = getOpsLocked(uid, packageName, true);
if ((ops != null) && ops.isPrivileged) {
return false;
}
@@ -1610,7 +1582,7 @@
out.startTag(null, "uid");
out.attribute(null, "n", Integer.toString(pkg.getUid()));
synchronized (this) {
- Ops ops = getOpsRawLocked(pkg.getUid(), pkg.getPackageName(), false);
+ Ops ops = getOpsLocked(pkg.getUid(), pkg.getPackageName(), false);
// Should always be present as the list of PackageOps is generated
// from Ops.
if (ops != null) {
@@ -2131,7 +2103,6 @@
@Override
public void setUserRestrictions(Bundle restrictions, IBinder token, int userHandle) {
checkSystemUid("setUserRestrictions");
- Preconditions.checkNotNull(restrictions);
Preconditions.checkNotNull(token);
final boolean[] opRestrictions = getOrCreateUserRestrictionsForToken(token, userHandle);
for (int i = 0; i < opRestrictions.length; ++i) {
@@ -2346,15 +2317,6 @@
}
}
- private static String resolvePackageName(int uid, String packageName) {
- if (uid == 0) {
- return "root";
- } else if (uid == Process.SHELL_UID) {
- return "com.android.shell";
- }
- return packageName;
- }
-
private static String[] getPackagesForUid(int uid) {
String[] packageNames = null;
try {
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index a3622b5..715f1e5 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1,3 +1,4 @@
+
/*
* Copyright (C) 2011 The Android Open Source Project
*
@@ -650,18 +651,27 @@
@Override
public UserInfo getUserInfo(int userId) {
+ checkManageUsersPermission("query user");
+ synchronized (mUsersLock) {
+ return getUserInfoLU(userId);
+ }
+ }
+
+ @Override
+ public boolean isManagedProfile(int userId) {
int callingUserId = UserHandle.getCallingUserId();
if (callingUserId != userId && !hasManageUsersPermission()) {
synchronized (mPackagesLock) {
if (!isSameProfileGroupLP(callingUserId, userId)) {
throw new SecurityException(
- "You need MANAGE_USERS permission to: query users outside profile" +
- " group");
+ "You need MANAGE_USERS permission to: check if specified user a " +
+ "managed profile outside your profile group");
}
}
}
synchronized (mUsersLock) {
- return getUserInfoLU(userId);
+ UserInfo userInfo = getUserInfoLU(userId);
+ return userInfo != null && userInfo.isManagedProfile();
}
}