diff --git a/Android.mk b/Android.mk
index bdb45550fa16d837e1c75ece8675b5590bd02aa0..7f06a7a02ad5bdeb40e909294bf329c7384991df 100644
--- a/Android.mk
+++ b/Android.mk
@@ -203,6 +203,7 @@ LOCAL_SRC_FILES += \
core/java/android/net/IIpConnectivityMetrics.aidl \
core/java/android/net/IEthernetManager.aidl \
core/java/android/net/IEthernetServiceListener.aidl \
+ core/java/android/net/INetdEventCallback.aidl \
core/java/android/net/INetworkManagementEventObserver.aidl \
core/java/android/net/INetworkPolicyListener.aidl \
core/java/android/net/INetworkPolicyManager.aidl \
@@ -577,6 +578,9 @@ aidl_files := \
frameworks/base/graphics/java/android/graphics/drawable/Icon.aidl \
frameworks/base/core/java/android/accounts/AuthenticatorDescription.aidl \
frameworks/base/core/java/android/accounts/Account.aidl \
+ frameworks/base/core/java/android/app/admin/ConnectEvent.aidl \
+ frameworks/base/core/java/android/app/admin/DnsEvent.aidl \
+ frameworks/base/core/java/android/app/admin/NetworkEvent.aidl \
frameworks/base/core/java/android/app/admin/SystemUpdatePolicy.aidl \
frameworks/base/core/java/android/print/PrintDocumentInfo.aidl \
frameworks/base/core/java/android/print/PageRange.aidl \
diff --git a/api/test-current.txt b/api/test-current.txt
index d74526b72150fbd8013a3c0e7006632486267319..fcbd1b519268bec551bcdec9855c689d978ea4e1 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -9790,6 +9790,7 @@ package android.content.pm {
method public abstract android.content.res.XmlResourceParser getXml(java.lang.String, int, android.content.pm.ApplicationInfo);
method public abstract boolean hasSystemFeature(java.lang.String);
method public abstract boolean hasSystemFeature(java.lang.String, int);
+ method public abstract boolean isPermissionReviewModeEnabled();
method public abstract boolean isPermissionRevokedByPolicy(java.lang.String, java.lang.String);
method public abstract boolean isSafeMode();
method public abstract java.util.List queryBroadcastReceivers(android.content.Intent, int);
@@ -38217,6 +38218,7 @@ package android.test.mock {
method public android.content.res.XmlResourceParser getXml(java.lang.String, int, android.content.pm.ApplicationInfo);
method public boolean hasSystemFeature(java.lang.String);
method public boolean hasSystemFeature(java.lang.String, int);
+ method public boolean isPermissionReviewModeEnabled();
method public boolean isPermissionRevokedByPolicy(java.lang.String, java.lang.String);
method public boolean isSafeMode();
method public java.util.List queryBroadcastReceivers(android.content.Intent, int);
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index d6c00589e7c2ab414b58d587d909cd36f001236d..618a7ed34708f3219a1812e4759c0747cdf8aca5 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -48,7 +48,9 @@ import android.content.pm.InstrumentationInfo;
import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
+import android.content.res.AssetManager;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.graphics.Rect;
import android.os.Binder;
import android.os.Build;
@@ -64,6 +66,7 @@ import android.os.UserHandle;
import android.text.TextUtils;
import android.util.AndroidException;
import android.util.ArrayMap;
+import android.util.DisplayMetrics;
import android.view.IWindowManager;
import com.android.internal.os.BaseCommand;
@@ -145,7 +148,7 @@ public class Am extends BaseCommand {
" am clear-debug-app\n" +
" am set-watch-heap \n" +
" am clear-watch-heap\n" +
- " am bug-report [--progress]\n" +
+ " am bug-report [--progress | --telephony]\n" +
" am monitor [--gdb ]\n" +
" am hang [--allow-restart]\n" +
" am restart\n" +
@@ -271,6 +274,7 @@ public class Am extends BaseCommand {
"am bug-report: request bug report generation; will launch a notification\n" +
" when done to select where it should be delivered. Options are: \n" +
" --progress: will launch a notification right away to show its progress.\n" +
+ " --telephony: will dump only telephony sections.\n" +
"\n" +
"am monitor: start monitoring for crashes or ANRs.\n" +
" --gdb: start gdbserv on the given port at crash/ANR\n" +
@@ -361,6 +365,8 @@ public class Am extends BaseCommand {
"am send-trim-memory: send a memory trim event to a .\n" +
"\n" +
"am get-current-user: returns id of the current foreground user.\n" +
+ "\n" +
+ "am supports-multiwindow: returns true if the device supports multiwindow.\n" +
"\n"
);
Intent.printIntentArgsHelp(pw, "");
@@ -458,6 +464,8 @@ public class Am extends BaseCommand {
runSendTrimMemory();
} else if (op.equals("get-current-user")) {
runGetCurrentUser();
+ } else if (op.equals("supports-multiwindow")) {
+ runSupportsMultiwindow();
} else {
showError("Error: unknown command '" + op + "'");
}
@@ -1144,6 +1152,8 @@ public class Am extends BaseCommand {
while ((opt=nextOption()) != null) {
if (opt.equals("--progress")) {
bugreportType = ActivityManager.BUGREPORT_OPTION_INTERACTIVE;
+ } else if (opt.equals("--telephony")) {
+ bugreportType = ActivityManager.BUGREPORT_OPTION_TELEPHONY;
} else {
System.err.println("Error: Unknown option: " + opt);
return;
@@ -2534,6 +2544,21 @@ public class Am extends BaseCommand {
System.out.println(currentUser.id);
}
+ private void runSupportsMultiwindow() throws Exception {
+ // system resources does not contain all the device configuration, construct it manually.
+ Configuration config = mAm.getConfiguration();
+ if (config == null) {
+ throw new AndroidException("Activity manager has no configuration");
+ }
+
+ final DisplayMetrics metrics = new DisplayMetrics();
+ metrics.setToDefaults();
+
+ Resources res = new Resources(AssetManager.getSystem(), metrics, config);
+
+ System.out.println(res.getBoolean(com.android.internal.R.bool.config_supportsMultiWindow));
+ }
+
/**
* Open the given file for sending into the system process. This verifies
* with SELinux that the system will have access to the file.
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index d4a9326fc0d446b60c083664b1a4f284ef92122b..82c12e63f33af8d2608bff8c649338c2685cb0a0 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -71,15 +71,26 @@ static const char SYSTEM_ENCRYPTED_BOOTANIMATION_FILE[] = "/system/media/bootani
static const char SYSTEM_DATA_DIR_PATH[] = "/data/system";
static const char SYSTEM_TIME_DIR_NAME[] = "time";
static const char SYSTEM_TIME_DIR_PATH[] = "/data/system/time";
+static const char CLOCK_FONT_ASSET[] = "images/clock_font.png";
+static const char CLOCK_FONT_ZIP_NAME[] = "clock_font.png";
static const char LAST_TIME_CHANGED_FILE_NAME[] = "last_time_change";
static const char LAST_TIME_CHANGED_FILE_PATH[] = "/data/system/time/last_time_change";
static const char ACCURATE_TIME_FLAG_FILE_NAME[] = "time_is_accurate";
static const char ACCURATE_TIME_FLAG_FILE_PATH[] = "/data/system/time/time_is_accurate";
+static const char TIME_FORMAT_12_HOUR_FLAG_FILE_PATH[] = "/data/system/time/time_format_12_hour";
// Java timestamp format. Don't show the clock if the date is before 2000-01-01 00:00:00.
static const long long ACCURATE_TIME_EPOCH = 946684800000;
+static constexpr char FONT_BEGIN_CHAR = ' ';
+static constexpr char FONT_END_CHAR = '~' + 1;
+static constexpr size_t FONT_NUM_CHARS = FONT_END_CHAR - FONT_BEGIN_CHAR + 1;
+static constexpr size_t FONT_NUM_COLS = 16;
+static constexpr size_t FONT_NUM_ROWS = FONT_NUM_CHARS / FONT_NUM_COLS;
+static const int TEXT_CENTER_VALUE = INT_MAX;
+static const int TEXT_MISSING_VALUE = INT_MIN;
static const char EXIT_PROP_NAME[] = "service.bootanim.exit";
static const char PLAY_SOUND_PROP_NAME[] = "persist.sys.bootanim.play_sound";
static const int ANIM_ENTRY_NAME_MAX = 256;
+static constexpr size_t TEXT_POS_LEN_MAX = 16;
static const char BOOT_COMPLETED_PROP_NAME[] = "sys.boot_completed";
static const char BOOTREASON_PROP_NAME[] = "ro.boot.bootreason";
// bootreasons list in "system/core/bootstat/bootstat.cpp".
@@ -92,7 +103,7 @@ static const std::vector PLAY_SOUND_BOOTREASON_BLACKLIST {
// ---------------------------------------------------------------------------
BootAnimation::BootAnimation() : Thread(false), mClockEnabled(true), mTimeIsAccurate(false),
- mTimeCheckThread(NULL) {
+ mTimeFormat12Hour(false), mTimeCheckThread(NULL) {
mSession = new SurfaceComposerClient();
// If the system has already booted, the animation is not being used for a boot.
@@ -178,15 +189,14 @@ status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets,
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
return NO_ERROR;
}
-status_t BootAnimation::initTexture(const Animation::Frame& frame)
+status_t BootAnimation::initTexture(FileMap* map, int* width, int* height)
{
- //StopWatch watch("blah");
-
SkBitmap bitmap;
- SkMemoryStream stream(frame.map->getDataPtr(), frame.map->getDataLength());
+ SkMemoryStream stream(map->getDataPtr(), map->getDataLength());
SkImageDecoder* codec = SkImageDecoder::Factory(&stream);
if (codec != NULL) {
codec->setDitherImage(false);
@@ -199,7 +209,7 @@ status_t BootAnimation::initTexture(const Animation::Frame& frame)
// FileMap memory is never released until application exit.
// Release it now as the texture is already loaded and the memory used for
// the packed resource can be released.
- delete frame.map;
+ delete map;
// ensure we can call getPixels(). No need to call unlock, since the
// bitmap will go out of scope when we return from this method.
@@ -245,6 +255,9 @@ status_t BootAnimation::initTexture(const Animation::Frame& frame)
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
+ *width = w;
+ *height = h;
+
return NO_ERROR;
}
@@ -436,7 +449,6 @@ bool BootAnimation::android()
return false;
}
-
void BootAnimation::checkExit() {
// Allow surface flinger to gracefully request shutdown
char value[PROPERTY_VALUE_MAX];
@@ -447,6 +459,47 @@ void BootAnimation::checkExit() {
}
}
+bool BootAnimation::validClock(const Animation::Part& part) {
+ return part.clockPosX != TEXT_MISSING_VALUE && part.clockPosY != TEXT_MISSING_VALUE;
+}
+
+bool parseTextCoord(const char* str, int* dest) {
+ if (strcmp("c", str) == 0) {
+ *dest = TEXT_CENTER_VALUE;
+ return true;
+ }
+
+ char* end;
+ int val = (int) strtol(str, &end, 0);
+ if (end == str || *end != '\0' || val == INT_MAX || val == INT_MIN) {
+ return false;
+ }
+ *dest = val;
+ return true;
+}
+
+// Parse two position coordinates. If only string is non-empty, treat it as the y value.
+void parsePosition(const char* str1, const char* str2, int* x, int* y) {
+ bool success = false;
+ if (strlen(str1) == 0) { // No values were specified
+ // success = false
+ } else if (strlen(str2) == 0) { // we have only one value
+ if (parseTextCoord(str1, y)) {
+ *x = TEXT_CENTER_VALUE;
+ success = true;
+ }
+ } else {
+ if (parseTextCoord(str1, x) && parseTextCoord(str2, y)) {
+ success = true;
+ }
+ }
+
+ if (!success) {
+ *x = TEXT_MISSING_VALUE;
+ *y = TEXT_MISSING_VALUE;
+ }
+}
+
// Parse a color represented as an HTML-style 'RRGGBB' string: each pair of
// characters in str is a hex number in [0, 255], which are converted to
// floating point values in the range [0.0, 1.0] and placed in the
@@ -493,69 +546,108 @@ static bool readFile(ZipFileRO* zip, const char* name, String8& outString)
return true;
}
-// The time glyphs are stored in a single image of height 64 pixels. Each digit is 40 pixels wide,
-// and the colon character is half that at 20 pixels. The glyph order is '0123456789:'.
-// We render 24 hour time.
-void BootAnimation::drawTime(const Texture& clockTex, const int yPos) {
- static constexpr char TIME_FORMAT[] = "%H:%M";
- static constexpr int TIME_LENGTH = sizeof(TIME_FORMAT);
+// The font image should be a 96x2 array of character images. The
+// columns are the printable ASCII characters 0x20 - 0x7f. The
+// top row is regular text; the bottom row is bold.
+status_t BootAnimation::initFont(Font* font, const char* fallback) {
+ status_t status = NO_ERROR;
- static constexpr int DIGIT_HEIGHT = 64;
- static constexpr int DIGIT_WIDTH = 40;
- static constexpr int COLON_WIDTH = DIGIT_WIDTH / 2;
- static constexpr int TIME_WIDTH = (DIGIT_WIDTH * 4) + COLON_WIDTH;
+ if (font->map != nullptr) {
+ glGenTextures(1, &font->texture.name);
+ glBindTexture(GL_TEXTURE_2D, font->texture.name);
- if (clockTex.h < DIGIT_HEIGHT || clockTex.w < (10 * DIGIT_WIDTH + COLON_WIDTH)) {
- ALOGE("Clock texture is too small; abandoning boot animation clock");
- mClockEnabled = false;
- return;
+ status = initTexture(font->map, &font->texture.w, &font->texture.h);
+
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ } else if (fallback != nullptr) {
+ status = initTexture(&font->texture, mAssets, fallback);
+ } else {
+ return NO_INIT;
}
- time_t rawtime;
- time(&rawtime);
- struct tm* timeInfo = localtime(&rawtime);
+ if (status == NO_ERROR) {
+ font->char_width = font->texture.w / FONT_NUM_COLS;
+ font->char_height = font->texture.h / FONT_NUM_ROWS / 2; // There are bold and regular rows
+ }
- char timeBuff[TIME_LENGTH];
- size_t length = strftime(timeBuff, TIME_LENGTH, TIME_FORMAT, timeInfo);
+ return status;
+}
- if (length != TIME_LENGTH - 1) {
- ALOGE("Couldn't format time; abandoning boot animation clock");
- mClockEnabled = false;
- return;
+void BootAnimation::drawText(const char* str, const Font& font, bool bold, int* x, int* y) {
+ glEnable(GL_BLEND); // Allow us to draw on top of the animation
+ glBindTexture(GL_TEXTURE_2D, font.texture.name);
+
+ const int len = strlen(str);
+ const int strWidth = font.char_width * len;
+
+ if (*x == TEXT_CENTER_VALUE) {
+ *x = (mWidth - strWidth) / 2;
+ } else if (*x < 0) {
+ *x = mWidth + *x - strWidth;
+ }
+ if (*y == TEXT_CENTER_VALUE) {
+ *y = (mHeight - font.char_height) / 2;
+ } else if (*y < 0) {
+ *y = mHeight + *y - font.char_height;
}
- glEnable(GL_BLEND); // Allow us to draw on top of the animation
- glBindTexture(GL_TEXTURE_2D, clockTex.name);
+ int cropRect[4] = { 0, 0, font.char_width, -font.char_height };
- int xPos = (mWidth - TIME_WIDTH) / 2;
- int cropRect[4] = { 0, DIGIT_HEIGHT, DIGIT_WIDTH, -DIGIT_HEIGHT };
+ for (int i = 0; i < len; i++) {
+ char c = str[i];
- for (int i = 0; i < TIME_LENGTH - 1; i++) {
- char c = timeBuff[i];
- int width = DIGIT_WIDTH;
- int pos = c - '0'; // Position in the character list
- if (pos < 0 || pos > 10) {
- continue;
- }
- if (c == ':') {
- width = COLON_WIDTH;
+ if (c < FONT_BEGIN_CHAR || c > FONT_END_CHAR) {
+ c = '?';
}
// Crop the texture to only the pixels in the current glyph
- int left = pos * DIGIT_WIDTH;
- cropRect[0] = left;
- cropRect[2] = width;
+ const int charPos = (c - FONT_BEGIN_CHAR); // Position in the list of valid characters
+ const int row = charPos / FONT_NUM_COLS;
+ const int col = charPos % FONT_NUM_COLS;
+ cropRect[0] = col * font.char_width; // Left of column
+ cropRect[1] = row * font.char_height * 2; // Top of row
+ // Move down to bottom of regular (one char_heigh) or bold (two char_heigh) line
+ cropRect[1] += bold ? 2 * font.char_height : font.char_height;
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect);
- glDrawTexiOES(xPos, yPos, 0, width, DIGIT_HEIGHT);
+ glDrawTexiOES(*x, *y, 0, font.char_width, font.char_height);
- xPos += width;
+ *x += font.char_width;
}
glDisable(GL_BLEND); // Return to the animation's default behaviour
glBindTexture(GL_TEXTURE_2D, 0);
}
+// We render 12 or 24 hour time.
+void BootAnimation::drawClock(const Font& font, const int xPos, const int yPos) {
+ static constexpr char TIME_FORMAT_12[] = "%l:%M";
+ static constexpr char TIME_FORMAT_24[] = "%H:%M";
+ static constexpr int TIME_LENGTH = 6;
+
+ time_t rawtime;
+ time(&rawtime);
+ struct tm* timeInfo = localtime(&rawtime);
+
+ char timeBuff[TIME_LENGTH];
+ const char* timeFormat = mTimeFormat12Hour ? TIME_FORMAT_12 : TIME_FORMAT_24;
+ size_t length = strftime(timeBuff, TIME_LENGTH, timeFormat, timeInfo);
+
+ if (length != TIME_LENGTH - 1) {
+ ALOGE("Couldn't format time; abandoning boot animation clock");
+ mClockEnabled = false;
+ return;
+ }
+
+ char* out = timeBuff[0] == ' ' ? &timeBuff[1] : &timeBuff[0];
+ int x = xPos;
+ int y = yPos;
+ drawText(out, font, false, &x, &y);
+}
+
bool BootAnimation::parseAnimationDesc(Animation& animation)
{
String8 desString;
@@ -576,9 +668,10 @@ bool BootAnimation::parseAnimationDesc(Animation& animation)
int height = 0;
int count = 0;
int pause = 0;
- int clockPosY = -1;
char path[ANIM_ENTRY_NAME_MAX];
char color[7] = "000000"; // default to black if unspecified
+ char clockPos1[TEXT_POS_LEN_MAX + 1] = "";
+ char clockPos2[TEXT_POS_LEN_MAX + 1] = "";
char pathType;
if (sscanf(l, "%d %d %d", &width, &height, &fps) == 3) {
@@ -586,15 +679,15 @@ bool BootAnimation::parseAnimationDesc(Animation& animation)
animation.width = width;
animation.height = height;
animation.fps = fps;
- } else if (sscanf(l, " %c %d %d %s #%6s %d",
- &pathType, &count, &pause, path, color, &clockPosY) >= 4) {
- // ALOGD("> type=%c, count=%d, pause=%d, path=%s, color=%s, clockPosY=%d", pathType, count, pause, path, color, clockPosY);
+ } else if (sscanf(l, " %c %d %d %s #%6s %16s %16s",
+ &pathType, &count, &pause, path, color, clockPos1, clockPos2) >= 4) {
+ //ALOGD("> type=%c, count=%d, pause=%d, path=%s, color=%s, clockPos1=%s, clockPos2=%s",
+ // pathType, count, pause, path, color, clockPos1, clockPos2);
Animation::Part part;
part.playUntilComplete = pathType == 'c';
part.count = count;
part.pause = pause;
part.path = path;
- part.clockPosY = clockPosY;
part.audioData = NULL;
part.animation = NULL;
if (!parseColor(color, part.backgroundColor)) {
@@ -603,6 +696,7 @@ bool BootAnimation::parseAnimationDesc(Animation& animation)
part.backgroundColor[1] = 0.0f;
part.backgroundColor[2] = 0.0f;
}
+ parsePosition(clockPos1, clockPos2, &part.clockPosX, &part.clockPosY);
animation.parts.add(part);
}
else if (strcmp(l, "$SYSTEM") == 0) {
@@ -646,6 +740,14 @@ bool BootAnimation::preloadZip(Animation& animation)
const String8 path(entryName.getPathDir());
const String8 leaf(entryName.getPathLeaf());
if (leaf.size() > 0) {
+ if (entryName == CLOCK_FONT_ZIP_NAME) {
+ FileMap* map = zip->createEntryFileMap(entry);
+ if (map) {
+ animation.clockFont.map = map;
+ }
+ continue;
+ }
+
for (size_t j = 0; j < pcount; j++) {
if (path == animation.parts[j].path) {
uint16_t method;
@@ -730,7 +832,7 @@ bool BootAnimation::movie()
bool anyPartHasClock = false;
for (size_t i=0; i < animation->parts.size(); i++) {
- if(animation->parts[i].clockPosY >= 0) {
+ if(validClock(animation->parts[i])) {
anyPartHasClock = true;
break;
}
@@ -768,10 +870,11 @@ bool BootAnimation::movie()
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- bool clockTextureInitialized = false;
+ bool clockFontInitialized = false;
if (mClockEnabled) {
- clockTextureInitialized = (initTexture(&mClock, mAssets, "images/clock64.png") == NO_ERROR);
- mClockEnabled = clockTextureInitialized;
+ clockFontInitialized =
+ (initFont(&animation->clockFont, CLOCK_FONT_ASSET) == NO_ERROR);
+ mClockEnabled = clockFontInitialized;
}
if (mClockEnabled && !updateIsTimeAccurate()) {
@@ -788,8 +891,8 @@ bool BootAnimation::movie()
releaseAnimation(animation);
- if (clockTextureInitialized) {
- glDeleteTextures(1, &mClock.name);
+ if (clockFontInitialized) {
+ glDeleteTextures(1, &animation->clockFont.texture.name);
}
return false;
@@ -845,7 +948,8 @@ bool BootAnimation::playAnimation(const Animation& animation)
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
- initTexture(frame);
+ int w, h;
+ initTexture(frame.map, &w, &h);
}
const int xc = animationX + frame.trimX;
@@ -867,8 +971,8 @@ bool BootAnimation::playAnimation(const Animation& animation)
// which is equivalent to mHeight - (yc + frame.trimHeight)
glDrawTexiOES(xc, mHeight - (yc + frame.trimHeight),
0, frame.trimWidth, frame.trimHeight);
- if (mClockEnabled && mTimeIsAccurate && part.clockPosY >= 0) {
- drawTime(mClock, part.clockPosY);
+ if (mClockEnabled && mTimeIsAccurate && validClock(part)) {
+ drawClock(animation.clockFont, part.clockPosX, part.clockPosY);
}
eglSwapBuffers(mDisplay, mSurface);
@@ -947,6 +1051,7 @@ BootAnimation::Animation* BootAnimation::loadAnimation(const String8& fn)
Animation *animation = new Animation;
animation->fileName = fn;
animation->zip = zip;
+ animation->clockFont.map = nullptr;
mLoadedFiles.add(animation->fileName);
parseAnimationDesc(*animation);
@@ -992,6 +1097,11 @@ bool BootAnimation::updateIsTimeAccurate() {
}
struct stat statResult;
+
+ if(stat(TIME_FORMAT_12_HOUR_FLAG_FILE_PATH, &statResult) == 0) {
+ mTimeFormat12Hour = true;
+ }
+
if(stat(ACCURATE_TIME_FLAG_FILE_PATH, &statResult) == 0) {
mTimeIsAccurate = true;
return true;
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index c0ae6b6edb101892710240fd70a333e48afa8b8b..26b25cd89d1a929db2a779f22715601962c08b3e 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -74,6 +74,13 @@ private:
GLuint name;
};
+ struct Font {
+ FileMap* map;
+ Texture texture;
+ int char_width;
+ int char_height;
+ };
+
struct Animation {
struct Frame {
String8 name;
@@ -90,8 +97,12 @@ private:
struct Part {
int count; // The number of times this part should repeat, 0 for infinite
int pause; // The number of frames to pause for at the end of this part
- int clockPosY; // The y position of the clock, in pixels, from the bottom of the
- // display (the clock is centred horizontally). -1 to disable the clock
+ int clockPosX; // The x position of the clock, in pixels. Positive values offset from
+ // the left of the screen, negative values offset from the right.
+ int clockPosY; // The y position of the clock, in pixels. Positive values offset from
+ // the bottom of the screen, negative values offset from the top.
+ // If either of the above are INT_MIN the clock is disabled, if INT_MAX
+ // the clock is centred on that axis.
String8 path;
String8 trimData;
SortedVector frames;
@@ -108,6 +119,7 @@ private:
String8 audioConf;
String8 fileName;
ZipFileRO* zip;
+ Font clockFont;
};
/**
@@ -118,10 +130,13 @@ private:
enum ImageID { IMG_OEM = 0, IMG_SYS = 1, IMG_ENC = 2 };
const char *getAnimationFileName(ImageID image);
status_t initTexture(Texture* texture, AssetManager& asset, const char* name);
- status_t initTexture(const Animation::Frame& frame);
+ status_t initTexture(FileMap* map, int* width, int* height);
+ status_t initFont(Font* font, const char* fallback);
bool android();
bool movie();
- void drawTime(const Texture& clockTex, const int yPos);
+ void drawText(const char* str, const Font& font, bool bold, int* x, int* y);
+ void drawClock(const Font& font, const int xPos, const int yPos);
+ bool validClock(const Animation::Part& part);
Animation* loadAnimation(const String8&);
bool playAnimation(const Animation&);
void releaseAnimation(Animation*) const;
@@ -134,7 +149,6 @@ private:
sp mSession;
AssetManager mAssets;
Texture mAndroid[2];
- Texture mClock;
int mWidth;
int mHeight;
bool mUseNpotTextures = false;
@@ -145,6 +159,7 @@ private:
sp mFlingerSurface;
bool mClockEnabled;
bool mTimeIsAccurate;
+ bool mTimeFormat12Hour;
bool mSystemBoot;
String8 mZipFileName;
SortedVector mLoadedFiles;
diff --git a/cmds/svc/src/com/android/commands/svc/NfcCommand.java b/cmds/svc/src/com/android/commands/svc/NfcCommand.java
index 8e9791f8b731fc20ed0d48ab9890baa0290b99ca..02a92b9c19ff6145289ca00fd31b16e0574304a9 100644
--- a/cmds/svc/src/com/android/commands/svc/NfcCommand.java
+++ b/cmds/svc/src/com/android/commands/svc/NfcCommand.java
@@ -58,7 +58,8 @@ public class NfcCommand extends Svc.Command {
IPackageManager pm = IPackageManager.Stub.asInterface(
ServiceManager.getService("package"));
try {
- if (pm.hasSystemFeature(PackageManager.FEATURE_NFC, 0)) {
+ if (pm.hasSystemFeature(PackageManager.FEATURE_NFC, 0) ||
+ pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION, 0)) {
INfcAdapter nfc = INfcAdapter.Stub
.asInterface(ServiceManager.getService(Context.NFC_SERVICE));
try {
diff --git a/cmds/svc/src/com/android/commands/svc/UsbCommand.java b/cmds/svc/src/com/android/commands/svc/UsbCommand.java
index a6ef25fc4479d8640427b2419d54b2a2205c934a..4dcb05e4f85dafbbddfbcb56eb976cbc98ebd3a1 100644
--- a/cmds/svc/src/com/android/commands/svc/UsbCommand.java
+++ b/cmds/svc/src/com/android/commands/svc/UsbCommand.java
@@ -50,7 +50,7 @@ public class UsbCommand extends Svc.Command {
IUsbManager usbMgr = IUsbManager.Stub.asInterface(ServiceManager.getService(
Context.USB_SERVICE));
try {
- usbMgr.setCurrentFunction((args.length >=3 ? args[2] : null));
+ usbMgr.setCurrentFunction((args.length >=3 ? args[2] : null), false);
} catch (RemoteException e) {
System.err.println("Error communicating with UsbManager: " + e);
}
diff --git a/cmds/svc/src/com/android/commands/svc/WifiCommand.java b/cmds/svc/src/com/android/commands/svc/WifiCommand.java
index 94214ff9694fb80c84d4cd607319f7f99c0c1e44..633dd9787cb116bf37ca145842be2cf75d1eea5a 100644
--- a/cmds/svc/src/com/android/commands/svc/WifiCommand.java
+++ b/cmds/svc/src/com/android/commands/svc/WifiCommand.java
@@ -52,7 +52,7 @@ public class WifiCommand extends Svc.Command {
IWifiManager wifiMgr
= IWifiManager.Stub.asInterface(ServiceManager.getService(Context.WIFI_SERVICE));
try {
- wifiMgr.setWifiEnabled(flag);
+ wifiMgr.setWifiEnabled("com.android.shell", flag);
}
catch (RemoteException e) {
System.err.println("Wi-Fi operation failed: " + e);
diff --git a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiObject.java b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiObject.java
index 751bbe825bca3eed0c70efa5435375c878127255..ef6d55ffb4830fea5a67710822ce880cde2d481f 100644
--- a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiObject.java
+++ b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiObject.java
@@ -808,7 +808,7 @@ public class UiObject {
*
* @return Rect
* @throws UiObjectNotFoundException
- * @see {@link #getBounds()}
+ * @see #getBounds()
* @since API Level 17
*/
public Rect getVisibleBounds() throws UiObjectNotFoundException {
diff --git a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/UiAutomationShellWrapper.java b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/UiAutomationShellWrapper.java
index ddeb8e78627104506123cf3ce279d34e2183b5ed..19aa11a3b1aaacd7d4aedab0b7c1e7e60a3ff007 100644
--- a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/UiAutomationShellWrapper.java
+++ b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/UiAutomationShellWrapper.java
@@ -41,7 +41,7 @@ public class UiAutomationShellWrapper {
* actions such as dialing 911 or posting messages to public forums, etc.
*
* @param isSet True to set as monkey test. False to set as regular functional test (default).
- * @see {@link ActivityManager#isUserAMonkey()}
+ * @see ActivityManager#isUserAMonkey()
*/
public void setRunAsMonkey(boolean isSet) {
IActivityManager am = ActivityManagerNative.getDefault();
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 163e7d2661b91bca0185eef7ea81d75acc228158..b311c218de30faa61af6caa6b263393cee8b5f60 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -334,7 +334,8 @@ public abstract class AccessibilityService extends Service {
public static final int GLOBAL_ACTION_HOME = 2;
/**
- * Action to toggle showing the overview of recent apps
+ * Action to toggle showing the overview of recent apps. Will fail on platforms that don't
+ * show recent apps.
*/
public static final int GLOBAL_ACTION_RECENTS = 3;
diff --git a/core/java/android/accounts/AbstractAccountAuthenticator.java b/core/java/android/accounts/AbstractAccountAuthenticator.java
index 4dca8e24d4357babcf868747020280f313cc9129..a291ef5cbb1e757c0e297ac46176fe09e60b6a4a 100644
--- a/core/java/android/accounts/AbstractAccountAuthenticator.java
+++ b/core/java/android/accounts/AbstractAccountAuthenticator.java
@@ -707,7 +707,7 @@ public abstract class AbstractAccountAuthenticator {
* @param account the account to clone, will never be null
* @return a Bundle result or null if the result is to be returned via the response.
* @throws NetworkErrorException
- * @see {@link #addAccountFromCredentials(AccountAuthenticatorResponse, Account, Bundle)}
+ * @see #addAccountFromCredentials(AccountAuthenticatorResponse, Account, Bundle)
*/
public Bundle getAccountCredentialsForCloning(final AccountAuthenticatorResponse response,
final Account account) throws NetworkErrorException {
@@ -732,7 +732,7 @@ public abstract class AbstractAccountAuthenticator {
* provided by {@link #getAccountCredentialsForCloning(AccountAuthenticatorResponse, Account)}.
* @return a Bundle result or null if the result is to be returned via the response.
* @throws NetworkErrorException
- * @see {@link #getAccountCredentialsForCloning(AccountAuthenticatorResponse, Account)}
+ * @see #getAccountCredentialsForCloning(AccountAuthenticatorResponse, Account)
*/
public Bundle addAccountFromCredentials(final AccountAuthenticatorResponse response,
Account account,
diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java
index 0c21c4ff55e7a7c0907af540d4c968db4febf645..4707bed3ee1438bc6a641463cd6c4552c9bae907 100644
--- a/core/java/android/animation/ObjectAnimator.java
+++ b/core/java/android/animation/ObjectAnimator.java
@@ -38,8 +38,8 @@ import java.lang.ref.WeakReference;
*
* {@sample development/samples/ApiDemos/res/anim/object_animator.xml ObjectAnimatorResources}
*
- *
When using resource files, it is possible to use {@link PropertyValuesHolder} and
- * {@link Keyframe} to create more complex animations. Using PropertyValuesHolders
+ *
Starting from API 23, it is possible to use {@link PropertyValuesHolder} and
+ * {@link Keyframe} in resource files to create more complex animations. Using PropertyValuesHolders
* allows animators to animate several properties in parallel, as shown in this sample:
It is also possible to use a combination of {@link PropertyValuesHolder} and
- * {@link Keyframe} resource tags to create a multi-step animation.
+ *
Starting from API 23, it is also possible to use a combination of {@link PropertyValuesHolder}
+ * and {@link Keyframe} resource tags to create a multi-step animation.
* Note that you can specify explicit fractional values (from 0 to 1) for
* each keyframe to determine when, in the overall duration, the animation should arrive at that
* value. Alternatively, you can leave the fractions off and the keyframes will be equally
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index e4880b0f6a43b817c18585a1492c23b9249b8058..3cb3b0b96eae0f768c0a394e762265ef7643a7c2 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2946,8 +2946,11 @@ public class Activity extends ContextThemeWrapper
* @hide
*/
@Override
- public void onWindowDismissed(boolean finishTask) {
+ public void onWindowDismissed(boolean finishTask, boolean suppressWindowTransition) {
finish(finishTask ? FINISH_TASK_WITH_ACTIVITY : DONT_FINISH_TASK_WITH_ACTIVITY);
+ if (suppressWindowTransition) {
+ overridePendingTransition(0, 0);
+ }
}
@@ -4210,7 +4213,7 @@ public class Activity extends ContextThemeWrapper
* @param requestCode If >= 0, this code will be returned in
* onActivityResult() when the activity exits.
* @param options Additional options for how the Activity should be started.
- * See {@link android.content.Context#startActivity(Intent, Bundle)
+ * See {@link android.content.Context#startActivity(Intent, Bundle)}
* Context.startActivity(Intent, Bundle)} for more details.
*
* @throws android.content.ActivityNotFoundException
@@ -4419,7 +4422,7 @@ public class Activity extends ContextThemeWrapper
* flagsMask
* @param extraFlags Always set to 0.
* @param options Additional options for how the Activity should be started.
- * See {@link android.content.Context#startActivity(Intent, Bundle)
+ * See {@link android.content.Context#startActivity(Intent, Bundle)}
* Context.startActivity(Intent, Bundle)} for more details. If options
* have also been supplied by the IntentSender, options given here will
* override any that conflict with those given by the IntentSender.
@@ -4504,7 +4507,7 @@ public class Activity extends ContextThemeWrapper
*
* @param intent The intent to start.
* @param options Additional options for how the Activity should be started.
- * See {@link android.content.Context#startActivity(Intent, Bundle)
+ * See {@link android.content.Context#startActivity(Intent, Bundle)}
* Context.startActivity(Intent, Bundle)} for more details.
*
* @throws android.content.ActivityNotFoundException
@@ -4553,7 +4556,7 @@ public class Activity extends ContextThemeWrapper
*
* @param intents The intents to start.
* @param options Additional options for how the Activity should be started.
- * See {@link android.content.Context#startActivity(Intent, Bundle)
+ * See {@link android.content.Context#startActivity(Intent, Bundle)}
* Context.startActivity(Intent, Bundle)} for more details.
*
* @throws android.content.ActivityNotFoundException
@@ -4602,7 +4605,7 @@ public class Activity extends ContextThemeWrapper
* flagsMask
* @param extraFlags Always set to 0.
* @param options Additional options for how the Activity should be started.
- * See {@link android.content.Context#startActivity(Intent, Bundle)
+ * See {@link android.content.Context#startActivity(Intent, Bundle)}
* Context.startActivity(Intent, Bundle)} for more details. If options
* have also been supplied by the IntentSender, options given here will
* override any that conflict with those given by the IntentSender.
@@ -4662,7 +4665,7 @@ public class Activity extends ContextThemeWrapper
* onActivityResult() when the activity exits, as described in
* {@link #startActivityForResult}.
* @param options Additional options for how the Activity should be started.
- * See {@link android.content.Context#startActivity(Intent, Bundle)
+ * See {@link android.content.Context#startActivity(Intent, Bundle)}
* Context.startActivity(Intent, Bundle)} for more details.
*
* @return If a new activity was launched then true is returned; otherwise
@@ -4739,7 +4742,7 @@ public class Activity extends ContextThemeWrapper
* your own activity; the only changes you can make are to the extras
* inside of it.
* @param options Additional options for how the Activity should be started.
- * See {@link android.content.Context#startActivity(Intent, Bundle)
+ * See {@link android.content.Context#startActivity(Intent, Bundle)}
* Context.startActivity(Intent, Bundle)} for more details.
*
* @return Returns a boolean indicating whether there was another Activity
@@ -4794,7 +4797,7 @@ public class Activity extends ContextThemeWrapper
* @param intent The intent to start.
* @param requestCode Reply request code. < 0 if reply is not requested.
* @param options Additional options for how the Activity should be started.
- * See {@link android.content.Context#startActivity(Intent, Bundle)
+ * See {@link android.content.Context#startActivity(Intent, Bundle)}
* Context.startActivity(Intent, Bundle)} for more details.
*
* @throws android.content.ActivityNotFoundException
@@ -4847,7 +4850,7 @@ public class Activity extends ContextThemeWrapper
* @param intent The intent to start.
* @param requestCode Reply request code. < 0 if reply is not requested.
* @param options Additional options for how the Activity should be started.
- * See {@link android.content.Context#startActivity(Intent, Bundle)
+ * See {@link android.content.Context#startActivity(Intent, Bundle)}
* Context.startActivity(Intent, Bundle)} for more details.
*
* @throws android.content.ActivityNotFoundException
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index fd962d9110b6cbd54574265e3f62407426dbc531..da7d711194deddaff8ab96d4960ea5ac4f737a84 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -75,7 +75,39 @@ import java.util.ArrayList;
import java.util.List;
/**
- * Interact with the overall activities running in the system.
+ *
+ * This class gives information about, and interacts
+ * with, activities, services, and the containing
+ * process.
+ *
+ *
+ *
+ * A number of the methods in this class are for
+ * debugging or informational purposes and they should
+ * not be used to affect any runtime behavior of
+ * your app. These methods are called out as such in
+ * the method level documentation.
+ *
+ *
+ *
+ * Most application developers should not have the need to
+ * use this class, most of whose methods are for specialized
+ * use cases. However, a few methods are more broadly applicable.
+ * For instance, {@link android.app.ActivityManager#isLowRamDevice() isLowRamDevice()}
+ * enables your app to detect whether it is running on a low-memory device,
+ * and behave accordingly.
+ * {@link android.app.ActivityManager#clearApplicationUserData() clearApplicationUserData()}
+ * is for apps with reset-data functionality.
+ *
+ *
+ *
+ * In some special use cases, where an app interacts with
+ * its Task stack, the app may use the
+ * {@link android.app.ActivityManager.AppTask} and
+ * {@link android.app.ActivityManager.RecentTaskInfo} inner
+ * classes. However, in general, the methods in this class should
+ * be used for testing and debugging purposes only.
+ *
*/
public class ActivityManager {
private static String TAG = "ActivityManager";
@@ -94,7 +126,8 @@ public class ActivityManager {
BUGREPORT_OPTION_FULL,
BUGREPORT_OPTION_INTERACTIVE,
BUGREPORT_OPTION_REMOTE,
- BUGREPORT_OPTION_WEAR
+ BUGREPORT_OPTION_WEAR,
+ BUGREPORT_OPTION_TELEPHONY
})
public @interface BugreportMode {}
/**
@@ -121,6 +154,13 @@ public class ActivityManager {
*/
public static final int BUGREPORT_OPTION_WEAR = 3;
+ /**
+ * Takes a lightweight version of bugreport that only includes a few, urgent sections
+ * used to report telephony bugs.
+ * @hide
+ */
+ public static final int BUGREPORT_OPTION_TELEPHONY = 4;
+
/**
* {@code
* } name for a 'home' Activity that declares a package that is to be
@@ -2158,13 +2198,13 @@ public class ActivityManager {
public static final int FLAG_FOREGROUND = 1<<1;
/**
- * Bit for {@link #flags): set if the service is running in a
+ * Bit for {@link #flags}: set if the service is running in a
* core system process.
*/
public static final int FLAG_SYSTEM_PROCESS = 1<<2;
/**
- * Bit for {@link #flags): set if the service is running in a
+ * Bit for {@link #flags}: set if the service is running in a
* persistent process.
*/
public static final int FLAG_PERSISTENT_PROCESS = 1<<3;
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index d4f80a01ea53451fe033b6575f47756fe037f556..28f84771e10ce8df0976889503321f02671467d5 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -60,6 +60,13 @@ public abstract class ActivityManagerInternal {
*/
public static final int APP_TRANSITION_TIMEOUT = 3;
+ /**
+ * Grant Uri permissions from one app to another. This method only extends
+ * permission grants if {@code callingUid} has permission to them.
+ */
+ public abstract void grantUriPermissionFromIntent(int callingUid, String targetPkg,
+ Intent intent, int targetUserId);
+
/**
* Verify that calling app has access to the given provider.
*/
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 2d22f26069f331a07f4b7ab837b1bf473f4236f5..9d2ef9147388799d3a0d592675457aa6f3118b44 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -62,6 +62,7 @@ import android.os.Bundle;
import android.os.Debug;
import android.os.DropBoxManager;
import android.os.Environment;
+import android.os.GraphicsEnvironment;
import android.os.Handler;
import android.os.IBinder;
import android.os.LocaleList;
@@ -5012,7 +5013,7 @@ public final class ActivityThread {
WindowManagerGlobal.getInstance().trimMemory(level);
}
- private void setupGraphicsSupport(LoadedApk info, File cacheDir) {
+ private void setupGraphicsSupport(Context context, File cacheDir) {
if (Process.isIsolated()) {
// Isolated processes aren't going to do UI.
return;
@@ -5025,6 +5026,7 @@ public final class ActivityThread {
if (packages != null) {
ThreadedRenderer.setupDiskCache(cacheDir);
RenderScriptCacheDir.setupDiskCache(cacheDir);
+ GraphicsEnvironment.setupGraphicsEnvironment(context);
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -5319,7 +5321,7 @@ public final class ActivityThread {
final Context deviceContext = appContext.createDeviceProtectedStorageContext();
final File codeCacheDir = deviceContext.getCodeCacheDir();
if (codeCacheDir != null) {
- setupGraphicsSupport(data.info, codeCacheDir);
+ setupGraphicsSupport(appContext, codeCacheDir);
} else {
Log.e(TAG, "Unable to setupGraphicsSupport due to missing code-cache directory");
}
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 66ab8ec0662ee170a0f49c82aba5bdce271daa50..43c4eedcdabf270cfdc14ede350c9db7385fdf63 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -443,8 +443,8 @@ public class AppOpsManager {
OP_WRITE_SMS,
OP_RECEIVE_SMS,
OP_RECEIVE_SMS,
- OP_RECEIVE_SMS,
- OP_RECEIVE_SMS,
+ OP_RECEIVE_MMS,
+ OP_RECEIVE_WAP_PUSH,
OP_SEND_SMS,
OP_READ_SMS,
OP_WRITE_SMS,
diff --git a/core/java/android/app/ApplicationErrorReport.java b/core/java/android/app/ApplicationErrorReport.java
index 9fa8a5d2faee06e9c597a4626afab450954c0ea4..eb5613a05fb8a4bfcc0f397a53f23fecd68a23e8 100644
--- a/core/java/android/app/ApplicationErrorReport.java
+++ b/core/java/android/app/ApplicationErrorReport.java
@@ -378,6 +378,11 @@ public class ApplicationErrorReport implements Parcelable {
exceptionMessage = sanitizeString(exceptionMessage);
}
+ /** {@hide} */
+ public void appendStackTrace(String tr) {
+ stackTrace = sanitizeString(stackTrace + tr);
+ }
+
/**
* Ensure that the string is of reasonable size, truncating from the middle if needed.
*/
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 9cea49102925428d202e3db45a22a95c75adfff5..320d8408cb6630ab89d82367c6a5a6321d6cb916 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -291,6 +291,12 @@ public class ApplicationPackageManager extends PackageManager {
throw new NameNotFoundException(group);
}
+ @Override
+ public boolean isPermissionReviewModeEnabled() {
+ return mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_permissionReviewRequired);
+ }
+
@Override
public PermissionGroupInfo getPermissionGroupInfo(String name,
int flags) throws NameNotFoundException {
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 6e2c464e9a371bfc50eb6e85d5c0b9380ab43bb9..72ccf72d2d05087418faed43cd8cf1182b623079 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -185,6 +185,11 @@ public class Dialog implements DialogInterface, Window.Callback,
mWindow = w;
w.setCallback(this);
w.setOnWindowDismissedCallback(this);
+ w.setOnWindowSwipeDismissedCallback(() -> {
+ if (mCancelable) {
+ cancel();
+ }
+ });
w.setWindowManager(mWindowManager, null, null);
w.setGravity(Gravity.CENTER);
@@ -200,6 +205,7 @@ public class Dialog implements DialogInterface, Window.Callback,
@Nullable Message cancelCallback) {
this(context);
mCancelable = cancelable;
+ updateWindowForCancelable();
mCancelMessage = cancelCallback;
}
@@ -207,6 +213,7 @@ public class Dialog implements DialogInterface, Window.Callback,
@Nullable OnCancelListener cancelListener) {
this(context);
mCancelable = cancelable;
+ updateWindowForCancelable();
setOnCancelListener(cancelListener);
}
@@ -742,7 +749,7 @@ public class Dialog implements DialogInterface, Window.Callback,
/** @hide */
@Override
- public void onWindowDismissed(boolean finishTask) {
+ public void onWindowDismissed(boolean finishTask, boolean suppressWindowTransition) {
dismiss();
}
@@ -1187,6 +1194,7 @@ public class Dialog implements DialogInterface, Window.Callback,
*/
public void setCancelable(boolean flag) {
mCancelable = flag;
+ updateWindowForCancelable();
}
/**
@@ -1200,6 +1208,7 @@ public class Dialog implements DialogInterface, Window.Callback,
public void setCanceledOnTouchOutside(boolean cancel) {
if (cancel && !mCancelable) {
mCancelable = true;
+ updateWindowForCancelable();
}
mWindow.setCloseOnTouchOutside(cancel);
@@ -1351,4 +1360,8 @@ public class Dialog implements DialogInterface, Window.Callback,
}
}
}
+
+ private void updateWindowForCancelable() {
+ mWindow.setCloseOnSwipeEnabled(mCancelable);
+ }
}
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 5dead2850942dc21118fe86c6b6565a38b5996ba..6b2838626ded06677598a7885d91d80c87441e2d 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -1115,7 +1115,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
*
* @param intent The intent to start.
* @param options Additional options for how the Activity should be started.
- * See {@link android.content.Context#startActivity(Intent, Bundle)
+ * See {@link android.content.Context#startActivity(Intent, Bundle)}
* Context.startActivity(Intent, Bundle)} for more details.
*/
public void startActivity(Intent intent, Bundle options) {
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index 391065787683d2af1b84789da681a2db89404f31..1850cebf4f079455de74de73dc40559f5db7434c 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -21,18 +21,20 @@ import android.annotation.RequiresPermission;
import android.app.trust.ITrustManager;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.UserInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.os.Binder;
-import android.os.RemoteException;
import android.os.IBinder;
import android.os.IUserManager;
+import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
-import android.os.UserManager;
-import android.view.IWindowManager;
import android.view.IOnKeyguardExitResult;
+import android.view.IWindowManager;
import android.view.WindowManagerGlobal;
+import java.util.List;
+
/**
* Class that can be used to lock and unlock the keyboard. Get an instance of this
* class by calling {@link android.content.Context#getSystemService(java.lang.String)}
@@ -44,6 +46,7 @@ public class KeyguardManager {
private IWindowManager mWM;
private ITrustManager mTrustManager;
private IUserManager mUserManager;
+ private Context mContext;
/**
* Intent used to prompt user for device credentials.
@@ -86,8 +89,9 @@ public class KeyguardManager {
Intent intent = new Intent(ACTION_CONFIRM_DEVICE_CREDENTIAL);
intent.putExtra(EXTRA_TITLE, title);
intent.putExtra(EXTRA_DESCRIPTION, description);
- // For security reasons, only allow this to come from system settings.
- intent.setPackage("com.android.settings");
+
+ // explicitly set the package for security
+ intent.setPackage(getSettingsPackageForIntent(intent));
return intent;
}
@@ -108,11 +112,23 @@ public class KeyguardManager {
intent.putExtra(EXTRA_TITLE, title);
intent.putExtra(EXTRA_DESCRIPTION, description);
intent.putExtra(Intent.EXTRA_USER_ID, userId);
- // For security reasons, only allow this to come from system settings.
- intent.setPackage("com.android.settings");
+
+ // explicitly set the package for security
+ intent.setPackage(getSettingsPackageForIntent(intent));
+
return intent;
}
+ private String getSettingsPackageForIntent(Intent intent) {
+ List resolveInfos = mContext.getPackageManager()
+ .queryIntentActivities(intent, PackageManager.MATCH_SYSTEM_ONLY);
+ for (int i = 0; i < resolveInfos.size(); i++) {
+ return resolveInfos.get(i).activityInfo.packageName;
+ }
+
+ return "com.android.settings";
+ }
+
/**
* @deprecated Use {@link android.view.WindowManager.LayoutParams#FLAG_DISMISS_KEYGUARD}
* and/or {@link android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED}
@@ -191,7 +207,8 @@ public class KeyguardManager {
}
- KeyguardManager() {
+ KeyguardManager(Context context) {
+ mContext = context;
mWM = WindowManagerGlobal.getWindowManagerService();
mTrustManager = ITrustManager.Stub.asInterface(
ServiceManager.getService(Context.TRUST_SERVICE));
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 55744b935f51795bd0ba5620e204597cef81cded..4c9b9778d7b54fb529902d07363f3d3b93fb3073 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -320,10 +320,10 @@ final class SystemServiceRegistry {
}});
registerService(Context.KEYGUARD_SERVICE, KeyguardManager.class,
- new StaticServiceFetcher() {
+ new CachedServiceFetcher() {
@Override
- public KeyguardManager createService() {
- return new KeyguardManager();
+ public KeyguardManager createService(ContextImpl ctx) {
+ return new KeyguardManager(ctx);
}});
registerService(Context.LAYOUT_INFLATER_SERVICE, LayoutInflater.class,
diff --git a/core/java/android/app/TaskStackBuilder.java b/core/java/android/app/TaskStackBuilder.java
index 0077db1eb31767e2da749012826aace9e428ae9e..bab993f855e9b272e5d251bd15ba8d51f3f5389c 100644
--- a/core/java/android/app/TaskStackBuilder.java
+++ b/core/java/android/app/TaskStackBuilder.java
@@ -226,7 +226,7 @@ public class TaskStackBuilder {
* Start the task stack constructed by this builder.
*
* @param options Additional options for how the Activity should be started.
- * See {@link android.content.Context#startActivity(Intent, Bundle)
+ * See {@link android.content.Context#startActivity(Intent, Bundle)}
* Context.startActivity(Intent, Bundle)} for more details.
*/
public void startActivities(Bundle options) {
@@ -259,7 +259,7 @@ public class TaskStackBuilder {
* {@link Intent#fillIn(Intent, int)} to control which unspecified parts of the
* intent that can be supplied when the actual send happens.
* @param options Additional options for how the Activity should be started.
- * See {@link android.content.Context#startActivity(Intent, Bundle)
+ * See {@link android.content.Context#startActivity(Intent, Bundle)}
* Context.startActivity(Intent, Bundle)} for more details.
*
* @return The obtained PendingIntent
diff --git a/core/java/android/app/admin/ConnectEvent.aidl b/core/java/android/app/admin/ConnectEvent.aidl
new file mode 100644
index 0000000000000000000000000000000000000000..bab40f5add384fe5dd45916c6256746f719270b3
--- /dev/null
+++ b/core/java/android/app/admin/ConnectEvent.aidl
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.admin;
+
+/** {@hide} */
+parcelable ConnectEvent;
+
diff --git a/core/java/android/app/admin/ConnectEvent.java b/core/java/android/app/admin/ConnectEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..b6b14f24a096d45466a259733ac075d42907aa88
--- /dev/null
+++ b/core/java/android/app/admin/ConnectEvent.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.admin;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A class that represents a connect library call event.
+ * @hide
+ */
+public final class ConnectEvent extends NetworkEvent implements Parcelable {
+
+ /** The destination IP address. */
+ private final String ipAddress;
+
+ /** The destination port number. */
+ private final int port;
+
+ /** @hide */
+ public ConnectEvent(String ipAddress, int port, String packageName, long timestamp) {
+ super(packageName, timestamp);
+ this.ipAddress = ipAddress;
+ this.port = port;
+ }
+
+ private ConnectEvent(Parcel in) {
+ this.ipAddress = in.readString();
+ this.port = in.readInt();
+ this.packageName = in.readString();
+ this.timestamp = in.readLong();
+ }
+
+ public String getIpAddress() {
+ return ipAddress;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("ConnectEvent(%s, %d, %d, %s)", ipAddress, port, timestamp,
+ packageName);
+ }
+
+ public static final Parcelable.Creator CREATOR
+ = new Parcelable.Creator() {
+ @Override
+ public ConnectEvent createFromParcel(Parcel in) {
+ if (in.readInt() != PARCEL_TOKEN_CONNECT_EVENT) {
+ return null;
+ }
+ return new ConnectEvent(in);
+ }
+
+ @Override
+ public ConnectEvent[] newArray(int size) {
+ return new ConnectEvent[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ // write parcel token first
+ out.writeInt(PARCEL_TOKEN_CONNECT_EVENT);
+ out.writeString(ipAddress);
+ out.writeInt(port);
+ out.writeString(packageName);
+ out.writeLong(timestamp);
+ }
+}
+
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index dd70b5dfd1f049dd605cee3b43cf2cdb201c3c0a..cbd5a6d548328b0af0bcbedc50724c4527723755 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -275,6 +275,36 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
public static final String ACTION_SECURITY_LOGS_AVAILABLE
= "android.app.action.SECURITY_LOGS_AVAILABLE";
+ /**
+ * Broadcast action: notify that a new batch of network logs is ready to be collected.
+ * @see DeviceAdminReceiver#onNetworkLogsAvailable
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_NETWORK_LOGS_AVAILABLE
+ = "android.app.action.NETWORK_LOGS_AVAILABLE";
+
+ /**
+ * A {@code long} containing a token of the current batch of network logs, that has to be used
+ * to retrieve the batch of logs by the device owner.
+ *
+ * @see #ACTION_NETWORK_LOGS_AVAILABLE
+ * @see DevicePolicyManager#retrieveNetworkLogs
+ * @hide
+ */
+ public static final String EXTRA_NETWORK_LOGS_TOKEN =
+ "android.app.extra.EXTRA_NETWORK_LOGS_TOKEN";
+
+ /**
+ * An {@code int} count representing a total count of network logs inside the current batch of
+ * network logs.
+ *
+ * @see #ACTION_NETWORK_LOGS_AVAILABLE
+ * @hide
+ */
+ public static final String EXTRA_NETWORK_LOGS_COUNT =
+ "android.app.extra.EXTRA_NETWORK_LOGS_COUNT";
+
/**
* A string containing the SHA-256 hash of the bugreport file.
*
@@ -634,6 +664,25 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
public void onSecurityLogsAvailable(Context context, Intent intent) {
}
+ /**
+ * Called each time a new batch of network logs can be retrieved. This callback method will only
+ * ever be called when network logging is enabled. The logs can only be retrieved while network
+ * logging is enabled.
+ *
+ *
This callback is only applicable to device owners.
+ *
+ * @param context The running context as per {@link #onReceive}.
+ * @param intent The received intent as per {@link #onReceive}.
+ * @param batchToken The token representing the current batch of network logs.
+ * @param networkLogsCount The total count of events in the current batch of network logs.
+ * @see DevicePolicyManager#retrieveNetworkLogs(ComponentName)
+ *
+ * @hide
+ */
+ public void onNetworkLogsAvailable(Context context, Intent intent, long batchToken,
+ int networkLogsCount) {
+ }
+
/**
* Intercept standard device administrator broadcasts. Implementations
* should not override this method; it is better to implement the
@@ -688,6 +737,10 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
onBugreportFailed(context, intent, failureCode);
} else if (ACTION_SECURITY_LOGS_AVAILABLE.equals(action)) {
onSecurityLogsAvailable(context, intent);
+ } else if (ACTION_NETWORK_LOGS_AVAILABLE.equals(action)) {
+ long batchToken = intent.getLongExtra(EXTRA_NETWORK_LOGS_TOKEN, -1);
+ int networkLogsCount = intent.getIntExtra(EXTRA_NETWORK_LOGS_COUNT, 0);
+ onNetworkLogsAvailable(context, intent, batchToken, networkLogsCount);
}
}
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index df497b7564ab46bebfabf9b69ecc612d22c05b14..592026cda79b8940bf6e6ed5b1319b1e07158fb1 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -25,6 +25,7 @@ import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.UserIdInt;
import android.app.Activity;
+import android.app.admin.NetworkEvent;
import android.app.admin.SecurityLog.SecurityEvent;
import android.content.ComponentName;
import android.content.Context;
@@ -360,7 +361,7 @@ public class DevicePolicyManager {
* @hide
*/
public static final String ACTION_BUGREPORT_SHARING_ACCEPTED =
- "com.android.server.action.BUGREPORT_SHARING_ACCEPTED";
+ "com.android.server.action.REMOTE_BUGREPORT_SHARING_ACCEPTED";
/**
* Action: Bugreport sharing with device owner has been declined by the user.
@@ -368,7 +369,7 @@ public class DevicePolicyManager {
* @hide
*/
public static final String ACTION_BUGREPORT_SHARING_DECLINED =
- "com.android.server.action.BUGREPORT_SHARING_DECLINED";
+ "com.android.server.action.REMOTE_BUGREPORT_SHARING_DECLINED";
/**
* Action: Bugreport has been collected and is dispatched to {@link DevicePolicyManagerService}.
@@ -948,6 +949,15 @@ public class DevicePolicyManager {
public static final String ACTION_SET_NEW_PARENT_PROFILE_PASSWORD
= "android.app.action.SET_NEW_PARENT_PROFILE_PASSWORD";
+ /**
+ * Broadcast action: Tell the status bar to open the device monitoring dialog, e.g. when
+ * Network logging was enabled and the user tapped the notification.
+ *
This is a protected intent that can only be sent by the system.
+ * @hide
+ */
+ public static final String ACTION_SHOW_DEVICE_MONITORING_DIALOG
+ = "android.app.action.SHOW_DEVICE_MONITORING_DIALOG";
+
/**
* Flag used by {@link #addCrossProfileIntentFilter} to allow activities in
* the parent profile to access intents sent from the managed profile.
@@ -6625,6 +6635,83 @@ public class DevicePolicyManager {
}
}
+ /**
+ * Called by a device owner to control the network logging feature. Logging can only be
+ * enabled on single user devices where the sole user is managed by the device owner. If a new
+ * user is added on the device, logging is disabled.
+ *
+ *
Network logs contain DNS lookup and connect() library call events.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param enabled whether network logging should be enabled or not.
+ * @throws {@link SecurityException} if {@code admin} is not a device owner.
+ * @see #retrieveNetworkLogs
+ *
+ * @hide
+ */
+ public void setNetworkLoggingEnabled(@NonNull ComponentName admin, boolean enabled) {
+ throwIfParentInstance("setNetworkLoggingEnabled");
+ try {
+ mService.setNetworkLoggingEnabled(admin, enabled);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Return whether network logging is enabled by a device owner.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Can only
+ * be {@code null} if the caller has MANAGE_USERS permission.
+ * @return {@code true} if network logging is enabled by device owner, {@code false} otherwise.
+ * @throws {@link SecurityException} if {@code admin} is not a device owner and caller has
+ * no MANAGE_USERS permission
+ *
+ * @hide
+ */
+ public boolean isNetworkLoggingEnabled(@Nullable ComponentName admin) {
+ throwIfParentInstance("isNetworkLoggingEnabled");
+ try {
+ return mService.isNetworkLoggingEnabled(admin);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Called by device owner to retrieve the most recent batch of network logging events.
+ * A device owner has to provide a batchToken provided as part of
+ * {@link DeviceAdminReceiver#onNetworkLogsAvailable} callback. If the token doesn't match the
+ * token of the most recent available batch of logs, {@code null} will be returned.
+ *
+ *
{@link NetworkEvent} can be one of {@link DnsEvent} or {@link ConnectEvent}.
+ *
+ *
The list of network events is sorted chronologically, and contains at most 1200 events.
+ *
+ *
Access to the logs is rate limited and this method will only return a new batch of logs
+ * after the device device owner has been notified via
+ * {@link DeviceAdminReceiver#onNetworkLogsAvailable}.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param batchToken A token of the batch to retrieve
+ * @return A new batch of network logs which is a list of {@link NetworkEvent}. Returns
+ * {@code null} if the batch represented by batchToken is no longer available or if
+ * logging is disabled.
+ * @throws {@link SecurityException} if {@code admin} is not a device owner.
+ * @see DeviceAdminReceiver#onNetworkLogsAvailable
+ *
+ * @hide
+ */
+ public @Nullable List retrieveNetworkLogs(@NonNull ComponentName admin,
+ long batchToken) {
+ throwIfParentInstance("retrieveNetworkLogs");
+ try {
+ return mService.retrieveNetworkLogs(admin, batchToken);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
/**
* CM: check if secure keyguard is required
* @hide
diff --git a/core/java/android/app/admin/DnsEvent.aidl b/core/java/android/app/admin/DnsEvent.aidl
new file mode 100644
index 0000000000000000000000000000000000000000..6da962a0a828b4c28455987574d32a0236079b98
--- /dev/null
+++ b/core/java/android/app/admin/DnsEvent.aidl
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.admin;
+
+/** {@hide} */
+parcelable DnsEvent;
+
diff --git a/core/java/android/app/admin/DnsEvent.java b/core/java/android/app/admin/DnsEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..4ff8e1cba53153bd78533bcd8bcba9d9670877ff
--- /dev/null
+++ b/core/java/android/app/admin/DnsEvent.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.admin;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A class that represents a DNS lookup event.
+ * @hide
+ */
+public final class DnsEvent extends NetworkEvent implements Parcelable {
+
+ /** The hostname that was looked up. */
+ private final String hostname;
+
+ /** Contains (possibly a subset of) the IP addresses returned. */
+ private final String[] ipAddresses;
+
+ /**
+ * The number of IP addresses returned from the DNS lookup event. May be different from the
+ * length of ipAddresses if there were too many addresses to log.
+ */
+ private final int ipAddressesCount;
+
+ /** @hide */
+ public DnsEvent(String hostname, String[] ipAddresses, int ipAddressesCount,
+ String packageName, long timestamp) {
+ super(packageName, timestamp);
+ this.hostname = hostname;
+ this.ipAddresses = ipAddresses;
+ this.ipAddressesCount = ipAddressesCount;
+ }
+
+ private DnsEvent(Parcel in) {
+ this.hostname = in.readString();
+ this.ipAddresses = in.createStringArray();
+ this.ipAddressesCount = in.readInt();
+ this.packageName = in.readString();
+ this.timestamp = in.readLong();
+ }
+
+ /** Returns the hostname that was looked up. */
+ public String getHostname() {
+ return hostname;
+ }
+
+ /** Returns (possibly a subset of) the IP addresses returned. */
+ public String[] getIpAddresses() {
+ return ipAddresses;
+ }
+
+ /**
+ * Returns the number of IP addresses returned from the DNS lookup event. May be different from
+ * the length of ipAddresses if there were too many addresses to log.
+ */
+ public int getIpAddressesCount() {
+ return ipAddressesCount;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ if (ipAddresses != null) {
+ for (int i = 0; i < ipAddresses.length; i++) {
+ sb.append(ipAddresses[i]);
+ if (i < ipAddresses.length - 1) {
+ sb.append(" ");
+ }
+ }
+ } else {
+ sb.append("NONE");
+ }
+ return String.format("DnsEvent(%s, %s, %d, %d, %s)", hostname, sb.toString(),
+ ipAddressesCount, timestamp, packageName);
+ }
+
+ public static final Parcelable.Creator CREATOR
+ = new Parcelable.Creator() {
+ @Override
+ public DnsEvent createFromParcel(Parcel in) {
+ if (in.readInt() != PARCEL_TOKEN_DNS_EVENT) {
+ return null;
+ }
+ return new DnsEvent(in);
+ }
+
+ @Override
+ public DnsEvent[] newArray(int size) {
+ return new DnsEvent[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ // write parcel token first
+ out.writeInt(PARCEL_TOKEN_DNS_EVENT);
+ out.writeString(hostname);
+ out.writeStringArray(ipAddresses);
+ out.writeInt(ipAddressesCount);
+ out.writeString(packageName);
+ out.writeLong(timestamp);
+ }
+}
+
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 9051d2b5d289d73c25a053b20ca6e83477c05099..c00cf57d3d7b82bde93ef8f2600e9da106134a89 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -17,6 +17,7 @@
package android.app.admin;
+import android.app.admin.NetworkEvent;
import android.app.admin.SystemUpdatePolicy;
import android.content.ComponentName;
import android.content.Intent;
@@ -313,5 +314,9 @@ interface IDevicePolicyManager {
void setBackupServiceEnabled(in ComponentName admin, boolean enabled);
boolean isBackupServiceEnabled(in ComponentName admin);
+ void setNetworkLoggingEnabled(in ComponentName admin, boolean enabled);
+ boolean isNetworkLoggingEnabled(in ComponentName admin);
+ List retrieveNetworkLogs(in ComponentName admin, long batchToken);
+
boolean requireSecureKeyguard(int userHandle);
}
diff --git a/core/java/android/app/admin/NetworkEvent.aidl b/core/java/android/app/admin/NetworkEvent.aidl
new file mode 100644
index 0000000000000000000000000000000000000000..5fa5dbfabb5f8351f977550783f7e9940762e40a
--- /dev/null
+++ b/core/java/android/app/admin/NetworkEvent.aidl
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.admin;
+
+/** {@hide} */
+parcelable NetworkEvent;
+
diff --git a/core/java/android/app/admin/NetworkEvent.java b/core/java/android/app/admin/NetworkEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..0de2665f90a8ddf797da12697a422831d0c3e8a1
--- /dev/null
+++ b/core/java/android/app/admin/NetworkEvent.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.admin;
+
+import android.content.pm.PackageManager;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.ParcelFormatException;
+
+/**
+ * An abstract class that represents a network event.
+ * @hide
+ */
+public abstract class NetworkEvent implements Parcelable {
+
+ static final int PARCEL_TOKEN_DNS_EVENT = 1;
+ static final int PARCEL_TOKEN_CONNECT_EVENT = 2;
+
+ /** The package name of the UID that performed the query. */
+ String packageName;
+
+ /** The timestamp of the event being reported in milliseconds. */
+ long timestamp;
+
+ /** @hide */
+ NetworkEvent() {
+ //empty constructor
+ }
+
+ /** @hide */
+ NetworkEvent(String packageName, long timestamp) {
+ this.packageName = packageName;
+ this.timestamp = timestamp;
+ }
+
+ /**
+ * Returns the package name of the UID that performed the query, as returned by
+ * {@link PackageManager#getNameForUid}.
+ */
+ public String getPackageName() {
+ return packageName;
+ }
+
+ /**
+ * Returns the timestamp of the event being reported in milliseconds, the difference between
+ * the time the event was reported and midnight, January 1, 1970 UTC.
+ */
+ public long getTimestamp() {
+ return timestamp;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Parcelable.Creator CREATOR
+ = new Parcelable.Creator() {
+ public NetworkEvent createFromParcel(Parcel in) {
+ final int initialPosition = in.dataPosition();
+ final int parcelToken = in.readInt();
+ // we need to move back to the position from before we read parcelToken
+ in.setDataPosition(initialPosition);
+ switch (parcelToken) {
+ case PARCEL_TOKEN_DNS_EVENT:
+ return DnsEvent.CREATOR.createFromParcel(in);
+ case PARCEL_TOKEN_CONNECT_EVENT:
+ return ConnectEvent.CREATOR.createFromParcel(in);
+ default:
+ throw new ParcelFormatException("Unexpected NetworkEvent token in parcel: "
+ + parcelToken);
+ }
+ }
+
+ public NetworkEvent[] newArray(int size) {
+ return new NetworkEvent[size];
+ }
+ };
+
+ @Override
+ public abstract void writeToParcel(Parcel out, int flags);
+}
+
diff --git a/core/java/android/app/admin/SecurityLog.java b/core/java/android/app/admin/SecurityLog.java
index 2858991fbdf4df5ade6590ec29ef47901fb07297..91b87d74694d4be9fce1168688e8a334d29b592d 100644
--- a/core/java/android/app/admin/SecurityLog.java
+++ b/core/java/android/app/admin/SecurityLog.java
@@ -144,8 +144,7 @@ public class SecurityLog {
}
/**
- * Returns the payload contained in this log. Each call to this method will
- * retrieve the next payload item. If no more payload exists, it returns {@code null}.
+ * Returns the payload contained in this log entry or {@code null} if there is no payload.
*/
public Object getData() {
return mEvent.getData();
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index a793d0c12ee9627765f814430664bdf8dbe8811d..d3a14853cf1ee61691da02eb7c5d0d7bc7e4b628 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -493,7 +493,7 @@ public abstract class BackupAgent extends ContextWrapper {
*
Attempting to back up files in directories that are ignored by
* the backup system will have no effect. For example, if the app calls this method
* with a file inside the {@link #getNoBackupFilesDir()} directory, it will be ignored.
- * See {@link #onFullBackup(FullBackupDataOutput) for details on what directories
+ * See {@link #onFullBackup(FullBackupDataOutput)} for details on what directories
* are excluded from backups.
*
* @param file The file to be backed up. The file must exist and be readable by
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index bb5f7a1d606ee35d6a67a75ff16b9c7afbe39a71..5d99ada9a0245f6f7bd43385a0ca8c4de56818f2 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -347,8 +347,9 @@ public class AppWidgetHostView extends FrameLayout {
}
/**
- * Sets an executor which can be used for asynchronously inflating and applying the remoteviews.
- * @see {@link RemoteViews#applyAsync(Context, ViewGroup, RemoteViews.OnViewAppliedListener, Executor)}
+ * Sets an executor which can be used for asynchronously inflating. CPU intensive tasks like
+ * view inflation or loading images will be performed on the executor. The updates will still
+ * be applied on the UI thread.
*
* @param executor the executor to use or null.
* @hide
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 4d2c547d30a3ceddafdbdde474cbd133fdc401da..50f7096855eb79e7774723a1b96ce4bac3dbbf3b 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -202,6 +202,23 @@ public final class BluetoothAdapter {
*/
public static final int STATE_BLE_TURNING_OFF = 16;
+ /**
+ * Human-readable string helper for AdapterState
+ * @hide
+ */
+ public static String nameForState(@AdapterState int state) {
+ switch(state) {
+ case STATE_OFF: return "OFF";
+ case STATE_TURNING_ON: return "TURNING_ON";
+ case STATE_ON: return "ON";
+ case STATE_TURNING_OFF: return "TURNING_OFF";
+ case STATE_BLE_TURNING_ON: return "BLE_TURNING_ON";
+ case STATE_BLE_ON: return "BLE_ON";
+ case STATE_BLE_TURNING_OFF: return "BLE_TURNING_OFF";
+ default: return "?!?!? (" + state + ")";
+ }
+ }
+
/**
* Activity Action: Show a system activity that requests discoverable mode.
* This activity will also request the user to turn on Bluetooth if it
@@ -257,6 +274,29 @@ public final class BluetoothAdapter {
public static final String ACTION_REQUEST_ENABLE =
"android.bluetooth.adapter.action.REQUEST_ENABLE";
+ /**
+ * Activity Action: Show a system activity that allows the user to turn off
+ * Bluetooth. This is used only if permission review is enabled which is for
+ * apps targeting API less than 23 require a permission review before any of
+ * the app's components can run.
+ *
This system activity will return once Bluetooth has completed turning
+ * off, or the user has decided not to turn Bluetooth off.
+ *
Notification of the result of this activity is posted using the
+ * {@link android.app.Activity#onActivityResult} callback. The
+ * resultCode
+ * will be {@link android.app.Activity#RESULT_OK} if Bluetooth has been
+ * turned off or {@link android.app.Activity#RESULT_CANCELED} if the user
+ * has rejected the request or an error has occurred.
+ *
Applications can also listen for {@link #ACTION_STATE_CHANGED}
+ * for global notification whenever Bluetooth is turned on or off.
+ *
Requires {@link android.Manifest.permission#BLUETOOTH}
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_REQUEST_DISABLE =
+ "android.bluetooth.adapter.action.REQUEST_DISABLE";
+
/**
* Activity Action: Show a system activity that allows user to enable BLE scans even when
* Bluetooth is turned off.
@@ -643,42 +683,12 @@ public final class BluetoothAdapter {
@SystemApi
public boolean isLeEnabled() {
final int state = getLeState();
- if (state == BluetoothAdapter.STATE_ON) {
- if (DBG) Log.d (TAG, "STATE_ON");
- } else if (state == BluetoothAdapter.STATE_BLE_ON) {
- if (DBG) Log.d (TAG, "STATE_BLE_ON");
- } else {
- if (DBG) Log.d (TAG, "STATE_OFF");
- return false;
- }
- return true;
- }
-
- /**
- * Performs action based on user action to turn BT ON
- * or OFF if BT is in BLE_ON state
- */
- private void notifyUserAction(boolean enable) {
- try {
- mServiceLock.readLock().lock();
- if (mService == null) {
- Log.e(TAG, "mService is null");
- return;
- }
- if (enable) {
- mService.onLeServiceUp(); //NA:TODO implementation pending
- } else {
- mService.onBrEdrDown(); //NA:TODO implementation pending
- }
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
+ if (DBG) Log.d(TAG, "isLeEnabled(): " + BluetoothAdapter.nameForState(state));
+ return (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_BLE_ON);
}
/**
- * Turns off Bluetooth LE which was earlier turned on by calling EnableBLE().
+ * Turns off Bluetooth LE which was earlier turned on by calling enableBLE().
*
*
If the internal Adapter state is STATE_BLE_ON, this would trigger the transition
* to STATE_OFF and completely shut-down Bluetooth
@@ -708,61 +718,50 @@ public final class BluetoothAdapter {
if (!isBleScanAlwaysAvailable()) return false;
int state = getLeState();
- if (state == BluetoothAdapter.STATE_ON) {
- if (DBG) Log.d (TAG, "STATE_ON: shouldn't disable");
+ if (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_BLE_ON) {
+ String packageName = ActivityThread.currentPackageName();
+ if (DBG) Log.d (TAG, "disableBLE(): de-registering " + packageName);
try {
- mManagerService.updateBleAppCount(mToken, false);
+ mManagerService.updateBleAppCount(mToken, false, packageName);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
return true;
-
- } else if (state == BluetoothAdapter.STATE_BLE_ON) {
- if (DBG) Log.d (TAG, "STATE_BLE_ON");
- int bleAppCnt = 0;
- try {
- bleAppCnt = mManagerService.updateBleAppCount(mToken, false);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- if (bleAppCnt == 0) {
- // Disable only if there are no other clients
- notifyUserAction(false);
- }
- return true;
}
- if (DBG) Log.d (TAG, "STATE_OFF: Already disabled");
+ if (DBG) Log.d (TAG, "disableBLE(): Already disabled");
return false;
}
/**
- * Special Applications who want to only turn on Bluetooth Low Energy (BLE) would
- * EnableBLE, EnableBLE brings-up Bluetooth so that application can access
- * only LE related feature (Bluetooth GATT layers interfaces using the respective class)
- * EnableBLE in turn registers the existance of a special App which wants to
- * turn on Bluetooth Low enrgy part without making it visible at the settings UI
- * as Bluetooth ON.
- *
Invoking EnableBLE when Bluetooth is already in ON state, would just registers
- * the existance of special Application and doesn't do anything to current BT state.
- * when user turn OFF Bluetooth from UI, if there is an existance of special app, Bluetooth
- * would stay in BLE_ON state so that LE features are still acessible to the special
- * Applications.
+ * Applications who want to only use Bluetooth Low Energy (BLE) can call enableBLE.
*
- *
This is an asynchronous call: it will return immediately, and
+ * enableBLE registers the existence of an app using only LE functions.
+ *
+ * enableBLE may enable Bluetooth to an LE only mode so that an app can use
+ * LE related features (BluetoothGatt or BluetoothGattServer classes)
+ *
+ * If the user disables Bluetooth while an app is registered to use LE only features,
+ * Bluetooth will remain on in LE only mode for the app.
+ *
+ * When Bluetooth is in LE only mode, it is not shown as ON to the UI.
+ *
+ *
This is an asynchronous call: it returns immediately, and
* clients should listen for {@link #ACTION_BLE_STATE_CHANGED}
- * to be notified of subsequent adapter state changes. If this call returns
- * true, then the adapter state will immediately transition from {@link
- * #STATE_OFF} to {@link #STATE_BLE_TURNING_ON}, and some time
- * later transition to either {@link #STATE_OFF} or {@link
- * #STATE_BLE_ON}. If this call returns false then there was an
- * immediate problem that will prevent the adapter from being turned on -
- * such as Airplane mode, or the adapter is already turned on.
- * (@link #ACTION_BLE_STATE_CHANGED) returns the Bluetooth Adapter's various
+ * to be notified of adapter state changes.
+ *
+ * If this call returns * true, then the adapter state is either in a mode where
+ * LE is available, or will transition from {@link #STATE_OFF} to {@link #STATE_BLE_TURNING_ON},
+ * and some time later transition to either {@link #STATE_OFF} or {@link #STATE_BLE_ON}.
+ *
+ * If this call returns false then there was an immediate problem that prevents the
+ * adapter from being turned on - such as Airplane mode.
+ *
+ * {@link #ACTION_BLE_STATE_CHANGED} returns the Bluetooth Adapter's various
* states, It includes all the classic Bluetooth Adapter states along with
* internal BLE only states
*
- * @return true to indicate Bluetooth LE start-up has begun, or false on
+ * @return true to indicate Bluetooth LE will be available, or false on
* immediate error
* @hide
*/
@@ -771,13 +770,14 @@ public final class BluetoothAdapter {
if (!isBleScanAlwaysAvailable()) return false;
try {
- mManagerService.updateBleAppCount(mToken, true);
+ String packageName = ActivityThread.currentPackageName();
+ mManagerService.updateBleAppCount(mToken, true, packageName);
if (isLeEnabled()) {
if (DBG) Log.d(TAG, "enableBLE(): Bluetooth already enabled");
return true;
}
if (DBG) Log.d(TAG, "enableBLE(): Calling enable");
- return mManagerService.enable(ActivityThread.currentPackageName());
+ return mManagerService.enable(packageName);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -817,10 +817,10 @@ public final class BluetoothAdapter {
if (state == BluetoothAdapter.STATE_BLE_ON
|| state == BluetoothAdapter.STATE_BLE_TURNING_ON
|| state == BluetoothAdapter.STATE_BLE_TURNING_OFF) {
- if (VDBG) Log.d(TAG, "Consider internal state as OFF");
+ if (VDBG) Log.d(TAG, "Consider " + BluetoothAdapter.nameForState(state) + " state as OFF");
state = BluetoothAdapter.STATE_OFF;
}
- if (VDBG) Log.d(TAG, "" + hashCode() + ": getState(). Returning " + state);
+ if (VDBG) Log.d(TAG, "" + hashCode() + ": getState(). Returning " + BluetoothAdapter.nameForState(state));
return state;
}
@@ -857,12 +857,12 @@ public final class BluetoothAdapter {
mServiceLock.readLock().unlock();
}
- if (VDBG) Log.d(TAG,"getLeState() returning " + state);
+ if (VDBG) Log.d(TAG,"getLeState() returning " + BluetoothAdapter.nameForState(state));
return state;
}
boolean getLeAccess() {
- if(getLeState() == STATE_ON)
+ if (getLeState() == STATE_ON)
return true;
else if (getLeState() == STATE_BLE_ON)
@@ -901,8 +901,8 @@ public final class BluetoothAdapter {
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean enable() {
android.util.SeempLog.record(56);
- if (isEnabled() == true) {
- if (DBG) Log.d(TAG, "enable(): BT is already enabled..!");
+ if (isEnabled()) {
+ if (DBG) Log.d(TAG, "enable(): BT already enabled!");
return true;
}
try {
@@ -939,7 +939,7 @@ public final class BluetoothAdapter {
public boolean disable() {
android.util.SeempLog.record(57);
try {
- return mManagerService.disable(true);
+ return mManagerService.disable(ActivityThread.currentPackageName(), true);
} catch (RemoteException e) {Log.e(TAG, "", e);}
return false;
}
@@ -958,7 +958,7 @@ public final class BluetoothAdapter {
android.util.SeempLog.record(57);
try {
- return mManagerService.disable(persist);
+ return mManagerService.disable(ActivityThread.currentPackageName(), persist);
} catch (RemoteException e) {Log.e(TAG, "", e);}
return false;
}
@@ -1502,6 +1502,37 @@ public final class BluetoothAdapter {
return null;
}
+ /**
+ * Gets the currently supported profiles by the adapter.
+ *
+ *
This can be used to check whether a profile is supported before attempting
+ * to connect to its respective proxy.
+ *
+ * @return a list of integers indicating the ids of supported profiles as defined in
+ * {@link BluetoothProfile}.
+ * @hide
+ */
+ public List getSupportedProfiles() {
+ final ArrayList supportedProfiles = new ArrayList();
+
+ try {
+ synchronized (mManagerCallback) {
+ if (mService != null) {
+ final long supportedProfilesBitMask = mService.getSupportedProfiles();
+
+ for (int i = 0; i <= BluetoothProfile.MAX_PROFILE_ID; i++) {
+ if ((supportedProfilesBitMask & (1 << i)) != 0) {
+ supportedProfiles.add(i);
+ }
+ }
+ }
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "getSupportedProfiles:", e);
+ }
+ return supportedProfiles;
+ }
+
/**
* Get the current connection state of the local Bluetooth adapter.
* This can be used to check whether the local Bluetooth adapter is connected
@@ -1880,34 +1911,6 @@ public final class BluetoothAdapter {
* @hide
*/
public Pair readOutOfBandData() {
- if (getState() != STATE_ON) return null;
- //TODO(BT
- /*
- try {
- byte[] hash;
- byte[] randomizer;
-
- byte[] ret = null;
- mServiceLock.readLock().lock();
- if (mService != null) mService.readOutOfBandData();
-
- if (ret == null || ret.length != 32) return null;
-
- hash = Arrays.copyOfRange(ret, 0, 16);
- randomizer = Arrays.copyOfRange(ret, 16, 32);
-
- if (DBG) {
- Log.d(TAG, "readOutOfBandData:" + Arrays.toString(hash) +
- ":" + Arrays.toString(randomizer));
- }
- return new Pair(hash, randomizer);
-
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- */
return null;
}
@@ -2061,7 +2064,7 @@ public final class BluetoothAdapter {
if (cb != null) {
cb.onBluetoothServiceUp(bluetoothService);
} else {
- Log.d(TAG, "onBluetoothServiceUp: cb is null!!!");
+ Log.d(TAG, "onBluetoothServiceUp: cb is null!");
}
} catch (Exception e) {
Log.e(TAG,"",e);
@@ -2091,7 +2094,7 @@ public final class BluetoothAdapter {
if (cb != null) {
cb.onBluetoothServiceDown();
} else {
- Log.d(TAG, "onBluetoothServiceDown: cb is null!!!");
+ Log.d(TAG, "onBluetoothServiceDown: cb is null!");
}
} catch (Exception e) { Log.e(TAG,"",e);}
}
@@ -2100,7 +2103,7 @@ public final class BluetoothAdapter {
}
public void onBrEdrDown() {
- if (DBG) Log.i(TAG, "onBrEdrDown:");
+ if (VDBG) Log.i(TAG, "onBrEdrDown: " + mService);
}
};
@@ -2111,11 +2114,11 @@ public final class BluetoothAdapter {
*/
public boolean enableNoAutoConnect() {
if (isEnabled() == true){
- if (DBG) Log.d(TAG, "enableNoAutoConnect(): BT is already enabled..!");
+ if (DBG) Log.d(TAG, "enableNoAutoConnect(): BT already enabled!");
return true;
}
try {
- return mManagerService.enableNoAutoConnect();
+ return mManagerService.enableNoAutoConnect(ActivityThread.currentPackageName());
} catch (RemoteException e) {Log.e(TAG, "", e);}
return false;
}
@@ -2151,22 +2154,6 @@ public final class BluetoothAdapter {
*/
public boolean changeApplicationBluetoothState(boolean on,
BluetoothStateChangeCallback callback) {
- if (callback == null) return false;
-
- //TODO(BT)
- /*
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.changeApplicationBluetoothState(on, new
- StateChangeCallbackWrapper(callback), new Binder());
- }
- } catch (RemoteException e) {
- Log.e(TAG, "changeBluetoothState", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- */
return false;
}
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 552c8d3b0143dc390d4bd17298aae4c4d9a7582d..0eca4d670d3d6fd8c2682ef684cd996cbce8786d 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -44,14 +44,18 @@ public final class BluetoothGatt implements BluetoothProfile {
private IBluetoothGatt mService;
private BluetoothGattCallback mCallback;
private int mClientIf;
- private boolean mAuthRetry = false;
private BluetoothDevice mDevice;
private boolean mAutoConnect;
+ private int mAuthRetryState;
private int mConnState;
private final Object mStateLock = new Object();
private Boolean mDeviceBusy = false;
private int mTransport;
+ private static final int AUTH_RETRY_STATE_IDLE = 0;
+ private static final int AUTH_RETRY_STATE_NO_MITM = 1;
+ private static final int AUTH_RETRY_STATE_MITM = 2;
+
private static final int CONN_STATE_IDLE = 0;
private static final int CONN_STATE_CONNECTING = 1;
private static final int CONN_STATE_CONNECTED = 2;
@@ -262,17 +266,19 @@ public final class BluetoothGatt implements BluetoothProfile {
if ((status == GATT_INSUFFICIENT_AUTHENTICATION
|| status == GATT_INSUFFICIENT_ENCRYPTION)
- && mAuthRetry == false) {
+ && (mAuthRetryState != AUTH_RETRY_STATE_MITM)) {
try {
- mAuthRetry = true;
- mService.readCharacteristic(mClientIf, address, handle, AUTHENTICATION_MITM);
+ final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE) ?
+ AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM;
+ mService.readCharacteristic(mClientIf, address, handle, authReq);
+ mAuthRetryState++;
return;
} catch (RemoteException e) {
Log.e(TAG,"",e);
}
}
- mAuthRetry = false;
+ mAuthRetryState = AUTH_RETRY_STATE_IDLE;
BluetoothGattCharacteristic characteristic = getCharacteristicById(mDevice, handle);
if (characteristic == null) {
@@ -311,19 +317,20 @@ public final class BluetoothGatt implements BluetoothProfile {
if ((status == GATT_INSUFFICIENT_AUTHENTICATION
|| status == GATT_INSUFFICIENT_ENCRYPTION)
- && mAuthRetry == false) {
+ && (mAuthRetryState != AUTH_RETRY_STATE_MITM)) {
try {
- mAuthRetry = true;
+ final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE) ?
+ AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM;
mService.writeCharacteristic(mClientIf, address, handle,
- characteristic.getWriteType(), AUTHENTICATION_MITM,
- characteristic.getValue());
+ characteristic.getWriteType(), authReq, characteristic.getValue());
+ mAuthRetryState++;
return;
} catch (RemoteException e) {
Log.e(TAG,"",e);
}
}
- mAuthRetry = false;
+ mAuthRetryState = AUTH_RETRY_STATE_IDLE;
try {
mCallback.onCharacteristicWrite(BluetoothGatt.this, characteristic, status);
@@ -378,17 +385,19 @@ public final class BluetoothGatt implements BluetoothProfile {
if ((status == GATT_INSUFFICIENT_AUTHENTICATION
|| status == GATT_INSUFFICIENT_ENCRYPTION)
- && mAuthRetry == false) {
+ && (mAuthRetryState != AUTH_RETRY_STATE_MITM)) {
try {
- mAuthRetry = true;
- mService.readDescriptor(mClientIf, address, handle, AUTHENTICATION_MITM);
+ final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE) ?
+ AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM;
+ mService.readDescriptor(mClientIf, address, handle, authReq);
+ mAuthRetryState++;
return;
} catch (RemoteException e) {
Log.e(TAG,"",e);
}
}
- mAuthRetry = true;
+ mAuthRetryState = AUTH_RETRY_STATE_IDLE;
try {
mCallback.onDescriptorRead(BluetoothGatt.this, descriptor, status);
@@ -417,19 +426,21 @@ public final class BluetoothGatt implements BluetoothProfile {
if ((status == GATT_INSUFFICIENT_AUTHENTICATION
|| status == GATT_INSUFFICIENT_ENCRYPTION)
- && mAuthRetry == false) {
+ && (mAuthRetryState != AUTH_RETRY_STATE_MITM)) {
try {
- mAuthRetry = true;
+ final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE) ?
+ AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM;
mService.writeDescriptor(mClientIf, address, handle,
BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT,
- AUTHENTICATION_MITM, descriptor.getValue());
+ authReq, descriptor.getValue());
+ mAuthRetryState++;
return;
} catch (RemoteException e) {
Log.e(TAG,"",e);
}
}
- mAuthRetry = false;
+ mAuthRetryState = AUTH_RETRY_STATE_IDLE;
try {
mCallback.onDescriptorWrite(BluetoothGatt.this, descriptor, status);
@@ -503,6 +514,7 @@ public final class BluetoothGatt implements BluetoothProfile {
mServices = new ArrayList();
mConnState = CONN_STATE_IDLE;
+ mAuthRetryState = AUTH_RETRY_STATE_IDLE;
}
/**
@@ -516,6 +528,7 @@ public final class BluetoothGatt implements BluetoothProfile {
unregisterApp();
mConnState = CONN_STATE_CLOSED;
+ mAuthRetryState = AUTH_RETRY_STATE_IDLE;
}
/**
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index da79b586cf66d52c94c09935d4663831bff78cff..3b9ee291d6051f8da87e623264a229f04966670a 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -136,6 +136,13 @@ public interface BluetoothProfile {
*/
public static final int PBAP_CLIENT = 17;
+ /**
+ * Max profile ID. This value should be updated whenever a new profile is added to match
+ * the largest value assigned to a profile.
+ * @hide
+ */
+ public static final int MAX_PROFILE_ID = 17;
+
/**
* DUN
* @hide
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index 3049255f81ac2351d64cdf8f596299014300307c..54c68d368e850756bb19af3b0ccd36eed69daf81 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -62,6 +62,7 @@ interface IBluetooth
boolean cancelBondProcess(in BluetoothDevice device);
boolean removeBond(in BluetoothDevice device);
int getBondState(in BluetoothDevice device);
+ long getSupportedProfiles();
int getConnectionState(in BluetoothDevice device);
String getRemoteName(in BluetoothDevice device);
diff --git a/core/java/android/bluetooth/IBluetoothManager.aidl b/core/java/android/bluetooth/IBluetoothManager.aidl
index dd6f23699b6a9b818f490db9419d8d9d9d2f5f5a..5afd77418222963f754d520c6a717a76720767f5 100644
--- a/core/java/android/bluetooth/IBluetoothManager.aidl
+++ b/core/java/android/bluetooth/IBluetoothManager.aidl
@@ -34,9 +34,9 @@ interface IBluetoothManager
void registerStateChangeCallback(in IBluetoothStateChangeCallback callback);
void unregisterStateChangeCallback(in IBluetoothStateChangeCallback callback);
boolean isEnabled();
- boolean enable(String callingPackage);
- boolean enableNoAutoConnect();
- boolean disable(boolean persist);
+ boolean enable(String packageName);
+ boolean enableNoAutoConnect(String packageName);
+ boolean disable(String packageName, boolean persist);
int getState();
IBluetoothGatt getBluetoothGatt();
@@ -47,6 +47,6 @@ interface IBluetoothManager
String getName();
boolean isBleScanAlwaysAvailable();
- int updateBleAppCount(IBinder b, boolean enable);
+ int updateBleAppCount(IBinder b, boolean enable, String packageName);
boolean isBleAppPresent();
}
diff --git a/core/java/android/bluetooth/OobData.java b/core/java/android/bluetooth/OobData.java
index 8e659e04d705308658ada65bfb33080fd20bcfee..9e87230c686e4d6f2e15a60b648ae387d23aee8d 100644
--- a/core/java/android/bluetooth/OobData.java
+++ b/core/java/android/bluetooth/OobData.java
@@ -30,7 +30,23 @@ import android.util.Log;
* @hide
*/
public class OobData implements Parcelable {
+ private byte[] leBluetoothDeviceAddress;
private byte[] securityManagerTk;
+ private byte[] leSecureConnectionsConfirmation;
+ private byte[] leSecureConnectionsRandom;
+
+ public byte[] getLeBluetoothDeviceAddress() {
+ return leBluetoothDeviceAddress;
+ }
+
+ /**
+ * Sets the LE Bluetooth Device Address value to be used during LE pairing.
+ * The value shall be 7 bytes. Please see Bluetooth CSSv6, Part A 1.16 for
+ * a detailed description.
+ */
+ public void setLeBluetoothDeviceAddress(byte[] leBluetoothDeviceAddress) {
+ this.leBluetoothDeviceAddress = leBluetoothDeviceAddress;
+ }
public byte[] getSecurityManagerTk() {
return securityManagerTk;
@@ -45,10 +61,29 @@ public class OobData implements Parcelable {
this.securityManagerTk = securityManagerTk;
}
+ public byte[] getLeSecureConnectionsConfirmation() {
+ return leSecureConnectionsConfirmation;
+ }
+
+ public void setLeSecureConnectionsConfirmation(byte[] leSecureConnectionsConfirmation) {
+ this.leSecureConnectionsConfirmation = leSecureConnectionsConfirmation;
+ }
+
+ public byte[] getLeSecureConnectionsRandom() {
+ return leSecureConnectionsRandom;
+ }
+
+ public void setLeSecureConnectionsRandom(byte[] leSecureConnectionsRandom) {
+ this.leSecureConnectionsRandom = leSecureConnectionsRandom;
+ }
+
public OobData() { }
private OobData(Parcel in) {
+ leBluetoothDeviceAddress = in.createByteArray();
securityManagerTk = in.createByteArray();
+ leSecureConnectionsConfirmation = in.createByteArray();
+ leSecureConnectionsRandom = in.createByteArray();
}
public int describeContents() {
@@ -57,7 +92,10 @@ public class OobData implements Parcelable {
@Override
public void writeToParcel(Parcel out, int flags) {
+ out.writeByteArray(leBluetoothDeviceAddress);
out.writeByteArray(securityManagerTk);
+ out.writeByteArray(leSecureConnectionsConfirmation);
+ out.writeByteArray(leSecureConnectionsRandom);
}
public static final Parcelable.Creator CREATOR
diff --git a/core/java/android/content/BroadcastReceiver.java b/core/java/android/content/BroadcastReceiver.java
index 10e6fb23324913db561555970d3f75f22df9d82e..a7a86158edeecd36d46b51912822f5c76e2e6ada 100644
--- a/core/java/android/content/BroadcastReceiver.java
+++ b/core/java/android/content/BroadcastReceiver.java
@@ -27,189 +27,25 @@ import android.util.Log;
import android.util.Slog;
/**
- * Base class for code that will receive intents sent by sendBroadcast().
- *
- *
If you don't need to send broadcasts across applications, consider using
- * this class with {@link android.support.v4.content.LocalBroadcastManager} instead
- * of the more general facilities described below. This will give you a much
- * more efficient implementation (no cross-process communication needed) and allow
- * you to avoid thinking about any security issues related to other applications
- * being able to receive or send your broadcasts.
+ * Base class for code that receives and handles broadcast intents sent by
+ * {@link android.content.Context#sendBroadcast(Intent)}.
*
*
You can either dynamically register an instance of this class with
* {@link Context#registerReceiver Context.registerReceiver()}
- * or statically publish an implementation through the
+ * or statically declare an implementation with the
* {@link android.R.styleable#AndroidManifestReceiver <receiver>}
* tag in your AndroidManifest.xml.
- *
- *
Note:
- * If registering a receiver in your
- * {@link android.app.Activity#onResume() Activity.onResume()}
- * implementation, you should unregister it in
- * {@link android.app.Activity#onPause() Activity.onPause()}.
- * (You won't receive intents when paused,
- * and this will cut down on unnecessary system overhead). Do not unregister in
- * {@link android.app.Activity#onSaveInstanceState(android.os.Bundle) Activity.onSaveInstanceState()},
- * because this won't be called if the user moves back in the history
- * stack.
- *
- *
There are two major classes of broadcasts that can be received:
- *
- *
Normal broadcasts (sent with {@link Context#sendBroadcast(Intent)
- * Context.sendBroadcast}) are completely asynchronous. All receivers of the
- * broadcast are run in an undefined order, often at the same time. This is
- * more efficient, but means that receivers cannot use the result or abort
- * APIs included here.
- *
Ordered broadcasts (sent with {@link Context#sendOrderedBroadcast(Intent, String)
- * Context.sendOrderedBroadcast}) are delivered to one receiver at a time.
- * As each receiver executes in turn, it can propagate a result to the next
- * receiver, or it can completely abort the broadcast so that it won't be passed
- * to other receivers. The order receivers run in can be controlled with the
- * {@link android.R.styleable#AndroidManifestIntentFilter_priority
- * android:priority} attribute of the matching intent-filter; receivers with
- * the same priority will be run in an arbitrary order.
- *
- *
- *
Even in the case of normal broadcasts, the system may in some
- * situations revert to delivering the broadcast one receiver at a time. In
- * particular, for receivers that may require the creation of a process, only
- * one will be run at a time to avoid overloading the system with new processes.
- * In this situation, however, the non-ordered semantics hold: these receivers still
- * cannot return results or abort their broadcast.
- *
- *
Note that, although the Intent class is used for sending and receiving
- * these broadcasts, the Intent broadcast mechanism here is completely separate
- * from Intents that are used to start Activities with
- * {@link Context#startActivity Context.startActivity()}.
- * There is no way for a BroadcastReceiver
- * to see or capture Intents used with startActivity(); likewise, when
- * you broadcast an Intent, you will never find or start an Activity.
- * These two operations are semantically very different: starting an
- * Activity with an Intent is a foreground operation that modifies what the
- * user is currently interacting with; broadcasting an Intent is a background
- * operation that the user is not normally aware of.
- *
- *
The BroadcastReceiver class (when launched as a component through
- * a manifest's {@link android.R.styleable#AndroidManifestReceiver <receiver>}
- * tag) is an important part of an
- * application's overall lifecycle.
For information about how to use this class to receive and resolve intents, read the
- * Intents and Intent Filters
- * developer guide.
- *
- *
- *
- *
Security
- *
- *
Receivers used with the {@link Context} APIs are by their nature a
- * cross-application facility, so you must consider how other applications
- * may be able to abuse your use of them. Some things to consider are:
- *
- *
- *
The Intent namespace is global. Make sure that Intent action names and
- * other strings are written in a namespace you own, or else you may inadvertently
- * conflict with other applications.
- *
When you use {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)},
- * any application may send broadcasts to that registered receiver. You can
- * control who can send broadcasts to it through permissions described below.
- *
When you publish a receiver in your application's manifest and specify
- * intent-filters for it, any other application can send broadcasts to it regardless
- * of the filters you specify. To prevent others from sending to it, make it
- * unavailable to them with android:exported="false".
- *
When you use {@link Context#sendBroadcast(Intent)} or related methods,
- * normally any other application can receive these broadcasts. You can control who
- * can receive such broadcasts through permissions described below. Alternatively,
- * starting with {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH}, you
- * can also safely restrict the broadcast to a single application with
- * {@link Intent#setPackage(String) Intent.setPackage}
- *
+ *
For more information about using BroadcastReceiver, read the
+ * Broadcasts developer guide.
*
- *
None of these issues exist when using
- * {@link android.support.v4.content.LocalBroadcastManager}, since intents
- * broadcast it never go outside of the current process.
- *
- *
Access permissions can be enforced by either the sender or receiver
- * of a broadcast.
- *
- *
To enforce a permission when sending, you supply a non-null
- * permission argument to
- * {@link Context#sendBroadcast(Intent, String)} or
- * {@link Context#sendOrderedBroadcast(Intent, String, BroadcastReceiver, android.os.Handler, int, String, Bundle)}.
- * Only receivers who have been granted this permission
- * (by requesting it with the
- * {@link android.R.styleable#AndroidManifestUsesPermission <uses-permission>}
- * tag in their AndroidManifest.xml) will be able to receive
- * the broadcast.
- *
- *
To enforce a permission when receiving, you supply a non-null
- * permission when registering your receiver -- either when calling
- * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter, String, android.os.Handler)}
- * or in the static
- * {@link android.R.styleable#AndroidManifestReceiver <receiver>}
- * tag in your AndroidManifest.xml. Only broadcasters who have
- * been granted this permission (by requesting it with the
- * {@link android.R.styleable#AndroidManifestUsesPermission <uses-permission>}
- * tag in their AndroidManifest.xml) will be able to send an
- * Intent to the receiver.
- *
- *
See the Security and Permissions
- * document for more information on permissions and security in general.
- *
- *
- *
Receiver Lifecycle
- *
- *
A BroadcastReceiver object is only valid for the duration of the call
- * to {@link #onReceive}. Once your code returns from this function,
- * the system considers the object to be finished and no longer active.
- *
- *
This has important repercussions to what you can do in an
- * {@link #onReceive} implementation: anything that requires asynchronous
- * operation is not available, because you will need to return from the
- * function to handle the asynchronous operation, but at that point the
- * BroadcastReceiver is no longer active and thus the system is free to kill
- * its process before the asynchronous operation completes.
- *
- *
In particular, you may not show a dialog or bind to a service from
- * within a BroadcastReceiver. For the former, you should instead use the
- * {@link android.app.NotificationManager} API. For the latter, you can
- * use {@link android.content.Context#startService Context.startService()} to
- * send a command to the service.
- *
- *
- *
Process Lifecycle
- *
- *
A process that is currently executing a BroadcastReceiver (that is,
- * currently running the code in its {@link #onReceive} method) is
- * considered to be a foreground process and will be kept running by the
- * system except under cases of extreme memory pressure.
- *
- *
Once you return from onReceive(), the BroadcastReceiver is no longer
- * active, and its hosting process is only as important as any other application
- * components that are running in it. This is especially important because if
- * that process was only hosting the BroadcastReceiver (a common case for
- * applications that the user has never or not recently interacted with), then
- * upon returning from onReceive() the system will consider its process
- * to be empty and aggressively kill it so that resources are available for other
- * more important processes.
- *
- *
This means that for longer-running operations you will often use
- * a {@link android.app.Service} in conjunction with a BroadcastReceiver to keep
- * the containing process active for the entire time of your operation.
*/
public abstract class BroadcastReceiver {
private PendingResult mPendingResult;
private boolean mDebugUnregister;
-
+
/**
* State for a result that is pending for a broadcast receiver. Returned
* by {@link BroadcastReceiver#goAsync() goAsync()}
@@ -218,7 +54,7 @@ public abstract class BroadcastReceiver {
* terminate; you must call {@link #finish()} once you are done with the
* broadcast. This allows you to process the broadcast off of the main
* thread of your app.
- *
+ *
*
Note on threading: the state inside of this class is not itself
* thread-safe, however you can use it from any thread if you properly
* sure that you do not have races. Typically this means you will hand
@@ -232,14 +68,14 @@ public abstract class BroadcastReceiver {
public static final int TYPE_REGISTERED = 1;
/** @hide */
public static final int TYPE_UNREGISTERED = 2;
-
+
final int mType;
final boolean mOrderedHint;
final boolean mInitialStickyHint;
final IBinder mToken;
final int mSendingUser;
final int mFlags;
-
+
int mResultCode;
String mResultData;
Bundle mResultExtras;
@@ -259,7 +95,7 @@ public abstract class BroadcastReceiver {
mSendingUser = userId;
mFlags = flags;
}
-
+
/**
* Version of {@link BroadcastReceiver#setResultCode(int)
* BroadcastReceiver.setResultCode(int)} for
@@ -331,7 +167,7 @@ public abstract class BroadcastReceiver {
mResultData = data;
mResultExtras = extras;
}
-
+
/**
* Version of {@link BroadcastReceiver#getAbortBroadcast()
* BroadcastReceiver.getAbortBroadcast()} for
@@ -350,7 +186,7 @@ public abstract class BroadcastReceiver {
checkSynchronousHint();
mAbortBroadcast = true;
}
-
+
/**
* Version of {@link BroadcastReceiver#clearAbortBroadcast()
* BroadcastReceiver.clearAbortBroadcast()} for
@@ -359,7 +195,7 @@ public abstract class BroadcastReceiver {
public final void clearAbortBroadcast() {
mAbortBroadcast = false;
}
-
+
/**
* Finish the broadcast. The current result will be sent and the
* next broadcast will proceed.
@@ -397,14 +233,14 @@ public abstract class BroadcastReceiver {
sendFinished(mgr);
}
}
-
+
/** @hide */
public void setExtrasClassLoader(ClassLoader cl) {
if (mResultExtras != null) {
mResultExtras.setClassLoader(cl);
}
}
-
+
/** @hide */
public void sendFinished(IActivityManager am) {
synchronized (this) {
@@ -412,7 +248,7 @@ public abstract class BroadcastReceiver {
throw new IllegalStateException("Broadcast already finished");
}
mFinished = true;
-
+
try {
if (mResultExtras != null) {
mResultExtras.setAllowFds(false);
@@ -448,7 +284,7 @@ public abstract class BroadcastReceiver {
Log.e("BroadcastReceiver", e.getMessage(), e);
}
}
-
+
public BroadcastReceiver() {
}
@@ -468,14 +304,15 @@ public abstract class BroadcastReceiver {
*
*
If this BroadcastReceiver was launched through a <receiver> tag,
* then the object is no longer alive after returning from this
- * function. This means you should not perform any operations that
- * return a result to you asynchronously -- in particular, for interacting
- * with services, you should use
- * {@link Context#startService(Intent)} instead of
- * {@link Context#bindService(Intent, ServiceConnection, int)}. If you wish
- * to interact with a service that is already running, you can use
- * {@link #peekService}.
- *
+ * function. This means you should not perform any operations that
+ * return a result to you asynchronously. If you need to perform any follow up
+ * background work, schedule a {@link android.app.job.JobService} with
+ * {@link android.app.job.JobScheduler}.
+ *
+ * If you wish to interact with a service that is already running and previously
+ * bound using {@link android.content.Context#bindService(Intent, ServiceConnection, int) bindService()},
+ * you can use {@link #peekService}.
+ *
*
The Intent filters used in {@link android.content.Context#registerReceiver}
* and in application manifests are not guaranteed to be exclusive. They
* are hints to the operating system about how to find suitable recipients. It is
@@ -483,7 +320,7 @@ public abstract class BroadcastReceiver {
* resolution. For this reason, {@link #onReceive(Context, Intent) onReceive()}
* implementations should respond only to known actions, ignoring any unexpected
* Intents that they may receive.
- *
+ *
* @param context The Context in which the receiver is running.
* @param intent The Intent being received.
*/
@@ -496,7 +333,7 @@ public abstract class BroadcastReceiver {
* responsive to the broadcast (finishing it within 10s), but does allow
* the implementation to move work related to it over to another thread
* to avoid glitching the main UI thread due to disk IO.
- *
+ *
* @return Returns a {@link PendingResult} representing the result of
* the active broadcast. The BroadcastRecord itself is no longer active;
* all data and other interaction must go through {@link PendingResult}
@@ -508,15 +345,20 @@ public abstract class BroadcastReceiver {
mPendingResult = null;
return res;
}
-
+
/**
- * Provide a binder to an already-running service. This method is synchronous
+ * Provide a binder to an already-bound service. This method is synchronous
* and will not start the target service if it is not present, so it is safe
* to call from {@link #onReceive}.
- *
+ *
+ * For peekService() to return a non null {@link android.os.IBinder} interface
+ * the service must have published it before. In other words some component
+ * must have called {@link android.content.Context#bindService(Intent, ServiceConnection, int)} on it.
+ *
* @param myContext The Context that had been passed to {@link #onReceive(Context, Intent)}
- * @param service The Intent indicating the service you wish to use. See {@link
- * Context#startService(Intent)} for more information.
+ * @param service Identifies the already-bound service you wish to use. See
+ * {@link android.content.Context#bindService(Intent, ServiceConnection, int)}
+ * for more information.
*/
public IBinder peekService(Context myContext, Intent service) {
IActivityManager am = ActivityManagerNative.getDefault();
@@ -538,13 +380,13 @@ public abstract class BroadcastReceiver {
* Activity {@link android.app.Activity#RESULT_CANCELED} and
* {@link android.app.Activity#RESULT_OK} constants, though the
* actual meaning of this value is ultimately up to the broadcaster.
- *
+ *
*
This method does not work with non-ordered broadcasts such
* as those sent with {@link Context#sendBroadcast(Intent)
* Context.sendBroadcast}
- *
+ *
* @param code The new result code.
- *
+ *
* @see #setResult(int, String, Bundle)
*/
public final void setResultCode(int code) {
@@ -554,7 +396,7 @@ public abstract class BroadcastReceiver {
/**
* Retrieve the current result code, as set by the previous receiver.
- *
+ *
* @return int The current result code.
*/
public final int getResultCode() {
@@ -567,13 +409,13 @@ public abstract class BroadcastReceiver {
* {@link Context#sendOrderedBroadcast(Intent, String)
* Context.sendOrderedBroadcast}. This is an arbitrary
* string whose interpretation is up to the broadcaster.
- *
+ *
*
This method does not work with non-ordered broadcasts such
* as those sent with {@link Context#sendBroadcast(Intent)
* Context.sendBroadcast}
- *
+ *
* @param data The new result data; may be null.
- *
+ *
* @see #setResult(int, String, Bundle)
*/
public final void setResultData(String data) {
@@ -584,7 +426,7 @@ public abstract class BroadcastReceiver {
/**
* Retrieve the current result data, as set by the previous receiver.
* Often this is null.
- *
+ *
* @return String The current result data; may be null.
*/
public final String getResultData() {
@@ -599,13 +441,13 @@ public abstract class BroadcastReceiver {
* holding arbitrary data, whose interpretation is up to the
* broadcaster. Can be set to null. Calling this method completely
* replaces the current map (if any).
- *
+ *
*
This method does not work with non-ordered broadcasts such
* as those sent with {@link Context#sendBroadcast(Intent)
* Context.sendBroadcast}
- *
+ *
* @param extras The new extra data map; may be null.
- *
+ *
* @see #setResult(int, String, Bundle)
*/
public final void setResultExtras(Bundle extras) {
@@ -617,11 +459,11 @@ public abstract class BroadcastReceiver {
* Retrieve the current result extra data, as set by the previous receiver.
* Any changes you make to the returned Map will be propagated to the next
* receiver.
- *
+ *
* @param makeMap If true then a new empty Map will be made for you if the
* current Map is null; if false you should be prepared to
* receive a null Map.
- *
+ *
* @return Map The current extras map.
*/
public final Bundle getResultExtras(boolean makeMap) {
@@ -640,11 +482,11 @@ public abstract class BroadcastReceiver {
* {@link Context#sendOrderedBroadcast(Intent, String)
* Context.sendOrderedBroadcast}. All current result data is replaced
* by the value given to this method.
- *
+ *
*
This method does not work with non-ordered broadcasts such
* as those sent with {@link Context#sendBroadcast(Intent)
* Context.sendBroadcast}
- *
+ *
* @param code The new result code. Often uses the
* Activity {@link android.app.Activity#RESULT_CANCELED} and
* {@link android.app.Activity#RESULT_OK} constants, though the
@@ -662,11 +504,11 @@ public abstract class BroadcastReceiver {
mPendingResult.mResultData = data;
mPendingResult.mResultExtras = extras;
}
-
+
/**
* Returns the flag indicating whether or not this receiver should
* abort the current broadcast.
- *
+ *
* @return True if the broadcast should be aborted.
*/
public final boolean getAbortBroadcast() {
@@ -679,10 +521,10 @@ public abstract class BroadcastReceiver {
* {@link Context#sendOrderedBroadcast(Intent, String)
* Context.sendOrderedBroadcast}. This will prevent
* any other broadcast receivers from receiving the broadcast. It will still
- * call {@link #onReceive} of the BroadcastReceiver that the caller of
+ * call {@link #onReceive} of the BroadcastReceiver that the caller of
* {@link Context#sendOrderedBroadcast(Intent, String)
* Context.sendOrderedBroadcast} passed in.
- *
+ *
*
This method does not work with non-ordered broadcasts such
* as those sent with {@link Context#sendBroadcast(Intent)
* Context.sendBroadcast}
@@ -691,7 +533,7 @@ public abstract class BroadcastReceiver {
checkSynchronousHint();
mPendingResult.mAbortBroadcast = true;
}
-
+
/**
* Clears the flag indicating that this receiver should abort the current
* broadcast.
@@ -701,7 +543,7 @@ public abstract class BroadcastReceiver {
mPendingResult.mAbortBroadcast = false;
}
}
-
+
/**
* Returns true if the receiver is currently processing an ordered
* broadcast.
@@ -709,7 +551,7 @@ public abstract class BroadcastReceiver {
public final boolean isOrderedBroadcast() {
return mPendingResult != null ? mPendingResult.mOrderedHint : false;
}
-
+
/**
* Returns true if the receiver is currently processing the initial
* value of a sticky broadcast -- that is, the value that was last
@@ -719,7 +561,7 @@ public abstract class BroadcastReceiver {
public final boolean isInitialStickyBroadcast() {
return mPendingResult != null ? mPendingResult.mInitialStickyHint : false;
}
-
+
/**
* For internal use, sets the hint about whether this BroadcastReceiver is
* running in ordered mode.
@@ -727,21 +569,21 @@ public abstract class BroadcastReceiver {
public final void setOrderedHint(boolean isOrdered) {
// Accidentally left in the SDK.
}
-
+
/**
* For internal use to set the result data that is active. @hide
*/
public final void setPendingResult(PendingResult result) {
mPendingResult = result;
}
-
+
/**
* For internal use to set the result data that is active. @hide
*/
public final PendingResult getPendingResult() {
return mPendingResult;
}
-
+
/** @hide */
public int getSendingUserId() {
return mPendingResult.mSendingUser;
@@ -761,19 +603,19 @@ public abstract class BroadcastReceiver {
public final void setDebugUnregister(boolean debug) {
mDebugUnregister = debug;
}
-
+
/**
* Return the last value given to {@link #setDebugUnregister}.
*/
public final boolean getDebugUnregister() {
return mDebugUnregister;
}
-
+
void checkSynchronousHint() {
if (mPendingResult == null) {
throw new IllegalStateException("Call while result is not pending");
}
-
+
// Note that we don't assert when receiving the initial sticky value,
// since that may have come from an ordered broadcast. We'll catch
// them later when the real broadcast happens again.
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 3a2f471e96ebcfd767caf99fb89e86661990d815..ab37cd80b81d45b6da7768fc5cbe07495b1c4a0b 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1668,7 +1668,7 @@ public abstract class Context {
*
* @param intents An array of Intents to be started.
* @param options Additional options for how the Activity should be started.
- * See {@link android.content.Context#startActivity(Intent, Bundle)
+ * See {@link android.content.Context#startActivity(Intent, Bundle)}
* Context.startActivity(Intent, Bundle)} for more details.
*
* @throws ActivityNotFoundException
@@ -1696,7 +1696,7 @@ public abstract class Context {
* @param intents An array of Intents to be started.
* @param options Additional options for how the Activity should be started.
* @param userHandle The user for whom to launch the activities
- * See {@link android.content.Context#startActivity(Intent, Bundle)
+ * See {@link android.content.Context#startActivity(Intent, Bundle)}
* Context.startActivity(Intent, Bundle)} for more details.
*
* @throws ActivityNotFoundException
@@ -1745,7 +1745,7 @@ public abstract class Context {
* flagsMask
* @param extraFlags Always set to 0.
* @param options Additional options for how the Activity should be started.
- * See {@link android.content.Context#startActivity(Intent, Bundle)
+ * See {@link android.content.Context#startActivity(Intent, Bundle)}
* Context.startActivity(Intent, Bundle)} for more details. If options
* have also been supplied by the IntentSender, options given here will
* override any that conflict with those given by the IntentSender.
@@ -2474,9 +2474,8 @@ public abstract class Context {
* for high frequency calls.
*
*
- * @param service Identifies the service to be started. The Intent must be either
- * fully explicit (supplying a component name) or specify a specific package
- * name it is targetted to. Additional values
+ * @param service Identifies the service to be started. The Intent must be
+ * fully explicit (supplying a component name). Additional values
* may be included in the Intent extras to supply arguments along with
* this specific start call.
*
@@ -2554,10 +2553,8 @@ public abstract class Context {
* {@link #registerReceiver}, since the lifetime of this BroadcastReceiver
* is tied to another object (the one that registered it).
*
- * @param service Identifies the service to connect to. The Intent may
- * specify either an explicit component name, or a logical
- * description (action, category, etc) to match an
- * {@link IntentFilter} published by a service.
+ * @param service Identifies the service to connect to. The Intent must
+ * specify an explicit component name.
* @param conn Receives information as the service is started and stopped.
* This must be a valid ServiceConnection object; it must not be null.
* @param flags Operation options for the binding. May be 0,
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 861aae5a8794047f0a784baf531bb595e4bb78d4..2142aae2ec74abc34448bd6c3254e4420b43f9cb 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -8145,7 +8145,7 @@ public class Intent implements Parcelable, Cloneable {
* @return Returns a bit mask of {@link #FILL_IN_ACTION},
* {@link #FILL_IN_DATA}, {@link #FILL_IN_CATEGORIES}, {@link #FILL_IN_PACKAGE},
* {@link #FILL_IN_COMPONENT}, {@link #FILL_IN_SOURCE_BOUNDS},
- * {@link #FILL_IN_SELECTOR} and {@link #FILL_IN_CLIP_DATA indicating which fields were
+ * {@link #FILL_IN_SELECTOR} and {@link #FILL_IN_CLIP_DATA} indicating which fields were
* changed.
*/
@FillInFlags
diff --git a/core/java/android/content/SyncRequest.java b/core/java/android/content/SyncRequest.java
index 541ebbd32f11214b265806a64f1b550307a37c1b..74d2f114aae5c25c76e1df17425e4728c0375bb4 100644
--- a/core/java/android/content/SyncRequest.java
+++ b/core/java/android/content/SyncRequest.java
@@ -175,7 +175,7 @@ public class SyncRequest implements Parcelable {
}
/**
- * Builder class for a @link SyncRequest. As you build your SyncRequest this class will also
+ * Builder class for a {@link SyncRequest}. As you build your SyncRequest this class will also
* perform validation.
*/
public static class Builder {
@@ -351,7 +351,7 @@ public class SyncRequest implements Parcelable {
* @param requiresCharging true if sync requires the phone to be plugged in. Default false.
*/
public Builder setRequiresCharging(boolean requiresCharging) {
- mRequiresCharging = true;
+ mRequiresCharging = requiresCharging;
return this;
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 0263431f9950e48902c3809eb9bb1d74662bb226..ce029ab39251358f3881eea3900d5f688785cbcd 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2839,6 +2839,14 @@ public abstract class PackageManager {
public abstract List queryPermissionsByGroup(String group,
@PermissionInfoFlags int flags) throws NameNotFoundException;
+ /**
+ * Returns true if Permission Review Mode is enabled, false otherwise.
+ *
+ * @hide
+ */
+ @TestApi
+ public abstract boolean isPermissionReviewModeEnabled();
+
/**
* Retrieve all of the information we know about a particular group of
* permissions.
@@ -3305,7 +3313,8 @@ public abstract class PackageManager {
* Grant a runtime permission to an application which the application does not
* already have. The permission must have been requested by the application.
* If the application is not allowed to hold the permission, a {@link
- * java.lang.SecurityException} is thrown.
+ * java.lang.SecurityException} is thrown. If the package or permission is
+ * invalid, a {@link java.lang.IllegalArgumentException} is thrown.
*
* Note: Using this API requires holding
* android.permission.GRANT_REVOKE_PERMISSIONS and if the user id is
@@ -3330,7 +3339,8 @@ public abstract class PackageManager {
* #grantRuntimePermission(String, String, android.os.UserHandle)}. The
* permission must have been requested by and granted to the application.
* If the application is not allowed to hold the permission, a {@link
- * java.lang.SecurityException} is thrown.
+ * java.lang.SecurityException} is thrown. If the package or permission is
+ * invalid, a {@link java.lang.IllegalArgumentException} is thrown.
*
* Note: Using this API requires holding
* android.permission.GRANT_REVOKE_PERMISSIONS and if the user id is
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index f5bcf64417a666a9d7e2ec949ab486dbdd0c73d7..9bb212886861d457c825e2f5e7d6feab5fa203b5 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -168,4 +168,17 @@ public abstract class PackageManagerInternal {
* @return Whether was launched.
*/
public abstract boolean wasPackageEverLaunched(String packageName, int userId);
+
+ /**
+ * Retrieve the official name associated with a user id. This name is
+ * guaranteed to never change, though it is possible for the underlying
+ * user id to be changed. That is, if you are storing information about
+ * user ids in persistent storage, you should use the string returned
+ * by this function instead of the raw user-id.
+ *
+ * @param uid The user id for which you would like to retrieve a name.
+ * @return Returns a unique name for the given user id, or null if the
+ * user id is not currently assigned.
+ */
+ public abstract String getNameForUid(int uid);
}
diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java
index a93870ece823a26579fc9df82842416f89168067..f7c4d592b3a92da36611a10ccf8866aff77e180b 100644
--- a/core/java/android/content/pm/ShortcutManager.java
+++ b/core/java/android/content/pm/ShortcutManager.java
@@ -193,7 +193,11 @@ import java.util.List;
* The following list includes descriptions for the different attributes within a static shortcut:
*
*
{@code android:shortcutId}
- *
Mandatory shortcut ID
+ *
Mandatory shortcut ID.
+ *
+ * This must be a string literal.
+ * A resource string, such as @string/foo, cannot be used.
+ *
*
*
{@code android:enabled}
*
Default is {@code true}. Can be set to {@code false} in order
@@ -206,15 +210,24 @@ import java.util.List;
*
*
{@code android:shortcutShortLabel}
*
Mandatory shortcut short label.
- * See {@link ShortcutInfo.Builder#setShortLabel(CharSequence)}.
+ * See {@link ShortcutInfo.Builder#setShortLabel(CharSequence)}.
+ *
+ * This must be a resource string, such as @string/shortcut_label.
+ *
*
*
{@code android:shortcutLongLabel}
*
Shortcut long label.
- * See {@link ShortcutInfo.Builder#setLongLabel(CharSequence)}.
+ * See {@link ShortcutInfo.Builder#setLongLabel(CharSequence)}.
+ *
+ * This must be a resource string, such as @string/shortcut_long_label.
+ *
*
*
{@code android:shortcutDisabledMessage}
*
When {@code android:enabled} is set to
- * {@code false}, this attribute is used to display a custom disabled message.
+ * {@code false}, this attribute is used to display a custom disabled message.
+ *
+ * This must be a resource string, such as @string/shortcut_disabled_message.
+ *
*
*
{@code intent}
*
Intent to launch when the user selects the shortcut.
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 13ba6cc37d225734435258bada9ba3807044de33..c915b18b8a80d6c8512b64f2d11d86d03cf9767c 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -167,6 +167,8 @@ public abstract class DisplayManagerInternal {
public static final int POLICY_DIM = 2;
// Policy: Make the screen bright as usual.
public static final int POLICY_BRIGHT = 3;
+ // Policy: Keep the screen and display optimized for VR mode.
+ public static final int POLICY_VR = 4;
// The basic overall policy to apply: off, doze, dim or bright.
public int policy;
@@ -211,9 +213,6 @@ public abstract class DisplayManagerInternal {
public int dozeScreenBrightness;
public int dozeScreenState;
- // If true, use twilight to affect the brightness.
- public boolean useTwilight;
-
public DisplayPowerRequest() {
policy = POLICY_BRIGHT;
useProximitySensor = false;
@@ -233,6 +232,10 @@ public abstract class DisplayManagerInternal {
return policy == POLICY_BRIGHT || policy == POLICY_DIM;
}
+ public boolean isVr() {
+ return policy == POLICY_VR;
+ }
+
public void copyFrom(DisplayPowerRequest other) {
policy = other.policy;
useProximitySensor = other.useProximitySensor;
@@ -245,7 +248,6 @@ public abstract class DisplayManagerInternal {
boostScreenBrightness = other.boostScreenBrightness;
dozeScreenBrightness = other.dozeScreenBrightness;
dozeScreenState = other.dozeScreenState;
- useTwilight = other.useTwilight;
}
@Override
@@ -266,8 +268,7 @@ public abstract class DisplayManagerInternal {
&& lowPowerMode == other.lowPowerMode
&& boostScreenBrightness == other.boostScreenBrightness
&& dozeScreenBrightness == other.dozeScreenBrightness
- && dozeScreenState == other.dozeScreenState
- && useTwilight == other.useTwilight;
+ && dozeScreenState == other.dozeScreenState;
}
@Override
@@ -287,8 +288,7 @@ public abstract class DisplayManagerInternal {
+ ", lowPowerMode=" + lowPowerMode
+ ", boostScreenBrightness=" + boostScreenBrightness
+ ", dozeScreenBrightness=" + dozeScreenBrightness
- + ", dozeScreenState=" + Display.stateToString(dozeScreenState)
- + ", useTwilight=" + useTwilight;
+ + ", dozeScreenState=" + Display.stateToString(dozeScreenState);
}
public static String policyToString(int policy) {
@@ -301,6 +301,8 @@ public abstract class DisplayManagerInternal {
return "DIM";
case POLICY_BRIGHT:
return "BRIGHT";
+ case POLICY_VR:
+ return "VR";
default:
return Integer.toString(policy);
}
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index f17fd55bd22aaca62c6081f60af4f2d070b64420..c5ae1f54aed6039de63ecb378cddcde0aed4ea77 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -710,7 +710,7 @@ public class FingerprintManager {
/**
* Retrieves the authenticator token for binding keys to the lifecycle
- * of the current set of fingerprints. Used only by internal clients.
+ * of the calling user's fingerprints. Used only by internal clients.
*
* @hide
*/
diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl
index 6e4c9de1c8ef7aa2b3a7aa03b2483e2c32867e2d..00b0bffdd1f5344e37f8a31413158d39962e454e 100644
--- a/core/java/android/hardware/usb/IUsbManager.aidl
+++ b/core/java/android/hardware/usb/IUsbManager.aidl
@@ -87,15 +87,13 @@ interface IUsbManager
/* Returns true if the specified USB function is enabled. */
boolean isFunctionEnabled(String function);
- /* Sets the current USB function. */
- void setCurrentFunction(String function);
-
- /* Sets whether USB data (for example, MTP exposed pictures) should be made
- * available on the USB connection. Unlocking data should only be done with
- * user involvement, since exposing pictures or other data could leak sensitive
- * user information.
+ /* Sets the current USB function as well as whether USB data
+ * (for example, MTP exposed pictures) should be made available
+ * on the USB connection. Unlocking data should only be done with
+ * user involvement, since exposing pictures or other data could
+ * leak sensitive user information.
*/
- void setUsbDataUnlocked(boolean unlock);
+ void setCurrentFunction(String function, boolean usbDataUnlocked);
/* Allow USB debugging from the attached host. If alwaysAllow is true, add the
* the public key to list of host keys that the user has approved.
diff --git a/core/java/android/hardware/usb/UsbEndpoint.java b/core/java/android/hardware/usb/UsbEndpoint.java
index 708d651a58aec92fe05745bd7b158a950a188a66..c346700a979fef398055c9f43247ffe1a92c00b3 100644
--- a/core/java/android/hardware/usb/UsbEndpoint.java
+++ b/core/java/android/hardware/usb/UsbEndpoint.java
@@ -75,8 +75,8 @@ public class UsbEndpoint implements Parcelable {
* if the direction is host to device, and
* {@link UsbConstants#USB_DIR_IN} if the
* direction is device to host.
- * @see {@link UsbConstants#USB_DIR_IN}
- * @see {@link UsbConstants#USB_DIR_OUT}
+ * @see UsbConstants#USB_DIR_IN
+ * @see UsbConstants#USB_DIR_OUT
*
* @return the endpoint's direction
*/
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index cb2720ab98489f080c92a42616138037383a4c6c..3df57bcb704f8ba2760fb148fc290978f1943ce1 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -530,33 +530,23 @@ public class UsbManager {
* {@link #USB_FUNCTION_MIDI}, {@link #USB_FUNCTION_MTP}, {@link #USB_FUNCTION_PTP},
* or {@link #USB_FUNCTION_RNDIS}.
*
+ * Also sets whether USB data (for example, MTP exposed pictures) should be made available
+ * on the USB connection when in device mode. Unlocking usb data should only be done with
+ * user involvement, since exposing pictures or other data could leak sensitive
+ * user information.
+ *
* Note: This function is asynchronous and may fail silently without applying
* the requested changes.
*
*
* @param function name of the USB function, or null to restore the default function
+ * @param usbDataUnlocked whether user data is accessible
*
* {@hide}
*/
- public void setCurrentFunction(String function) {
- try {
- mService.setCurrentFunction(function);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Sets whether USB data (for example, MTP exposed pictures) should be made available
- * on the USB connection when in device mode. Unlocking usb data should only be done with
- * user involvement, since exposing pictures or other data could leak sensitive
- * user information.
- *
- * {@hide}
- */
- public void setUsbDataUnlocked(boolean unlocked) {
+ public void setCurrentFunction(String function, boolean usbDataUnlocked) {
try {
- mService.setUsbDataUnlocked(unlocked);
+ mService.setCurrentFunction(function, usbDataUnlocked);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 353eb885fa6aa4c6bfc735ef63510f3e108d3b60..750d4f9387ed26260646a01763618232116d946e 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -2404,16 +2404,16 @@ public class InputMethodService extends AbstractInputMethodService {
}
return true;
}
-
+
/**
* Return text that can be used as a button label for the given
* {@link EditorInfo#imeOptions EditorInfo.imeOptions}. Returns null
* if there is no action requested. Note that there is no guarantee that
* the returned text will be relatively short, so you probably do not
* want to use it as text on a soft keyboard key label.
- *
- * @param imeOptions The value from @link EditorInfo#imeOptions EditorInfo.imeOptions}.
- *
+ *
+ * @param imeOptions The value from {@link EditorInfo#imeOptions EditorInfo.imeOptions}.
+ *
* @return Returns a label to use, or null if there is no action.
*/
public CharSequence getTextForImeAction(int imeOptions) {
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 7b66ea2a536ec9649dbc09cf5b13c8cf994627e7..0ce579b4e800002f691b4867dd1335b17c0ee7ae 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -89,6 +89,13 @@ public class ConnectivityManager {
* sent as an extra; it should be consulted to see what kind of
* connectivity event occurred.
*
+ * Apps targeting Android 7.0 (API level 24) and higher do not receive this
+ * broadcast if they declare the broadcast receiver in their manifest. Apps
+ * will still receive broadcasts if they register their
+ * {@link android.content.BroadcastReceiver} with
+ * {@link android.content.Context#registerReceiver Context.registerReceiver()}
+ * and that context is still valid.
+ *
* If this is a connection that was the result of failing over from a
* disconnected network, then the FAILOVER_CONNECTION boolean extra is
* set to true.
@@ -224,6 +231,13 @@ public class ConnectivityManager {
*/
public static final String EXTRA_CAPTIVE_PORTAL_URL = "android.net.extra.CAPTIVE_PORTAL_URL";
+ /**
+ * Key for passing a user agent string to the captive portal login activity.
+ * {@hide}
+ */
+ public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT =
+ "android.net.extra.CAPTIVE_PORTAL_USER_AGENT";
+
/**
* Broadcast action to indicate the change of data activity status
* (idle or active) on a network in a recent period.
diff --git a/core/java/android/net/IIpConnectivityMetrics.aidl b/core/java/android/net/IIpConnectivityMetrics.aidl
index 8f634bbf0cc9a113e71da730c8cf96c6eabbeaf4..6f07b31538336f5de6abd0494f594e6f9b6233b4 100644
--- a/core/java/android/net/IIpConnectivityMetrics.aidl
+++ b/core/java/android/net/IIpConnectivityMetrics.aidl
@@ -18,12 +18,23 @@ package android.net;
import android.os.Parcelable;
import android.net.ConnectivityMetricsEvent;
+import android.net.INetdEventCallback;
/** {@hide} */
interface IIpConnectivityMetrics {
/**
- * @return number of remaining available slots in buffer.
+ * @return the number of remaining available slots in buffer,
+ * or -1 if the event was dropped due to rate limiting.
*/
int logEvent(in ConnectivityMetricsEvent event);
+
+ /**
+ * At most one callback can be registered (by DevicePolicyManager).
+ * @return status {@code true} if registering/unregistering of the callback was successful,
+ * {@code false} otherwise (might happen if IIpConnectivityMetrics is not available,
+ * if it happens make sure you call it when the service is up in the caller)
+ */
+ boolean registerNetdEventCallback(in INetdEventCallback callback);
+ boolean unregisterNetdEventCallback();
}
diff --git a/core/java/android/net/INetdEventCallback.aidl b/core/java/android/net/INetdEventCallback.aidl
new file mode 100644
index 0000000000000000000000000000000000000000..49436beadc51b9cd708255ec1b16673fab8f8edb
--- /dev/null
+++ b/core/java/android/net/INetdEventCallback.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+/** {@hide} */
+oneway interface INetdEventCallback {
+
+ /**
+ * Reports a single DNS lookup function call.
+ * This method must not block or perform long-running operations.
+ *
+ * @param hostname the name that was looked up.
+ * @param ipAddresses (possibly a subset of) the IP addresses returned.
+ * At most {@link #DNS_REPORTED_IP_ADDRESSES_LIMIT} addresses are logged.
+ * @param ipAddressesCount the number of IP addresses returned. May be different from the length
+ * of ipAddresses if there were too many addresses to log.
+ * @param timestamp the timestamp at which the query was reported by netd.
+ * @param uid the UID of the application that performed the query.
+ */
+ void onDnsEvent(String hostname, in String[] ipAddresses, int ipAddressesCount, long timestamp,
+ int uid);
+
+ /**
+ * Reports a single connect library call.
+ * This method must not block or perform long-running operations.
+ *
+ * @param ipAddr destination IP address.
+ * @param port destination port number.
+ * @param timestamp the timestamp at which the call was reported by netd.
+ * @param uid the UID of the application that performed the connection.
+ */
+ void onConnectEvent(String ipAddr, int port, long timestamp, int uid);
+}
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index 35e3065b078f05cc418181bdfb47fba9784f2042..a677d7342dadb3dc198b1e9031d94efd803eacfd 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -51,6 +51,17 @@ public class NetworkUtils {
*/
public native static void attachRaFilter(FileDescriptor fd, int packetType) throws SocketException;
+ /**
+ * Attaches a socket filter that accepts L2-L4 signaling traffic required for IP connectivity.
+ *
+ * This includes: all ARP, ICMPv6 RS/RA/NS/NA messages, and DHCPv4 exchanges.
+ *
+ * @param fd the socket's {@link FileDescriptor}.
+ * @param packetType the hardware address type, one of ARPHRD_*.
+ */
+ public native static void attachControlPacketFilter(FileDescriptor fd, int packetType)
+ throws SocketException;
+
/**
* Configures a socket for receiving ICMPv6 router solicitations and sending advertisements.
* @param fd the socket's {@link FileDescriptor}.
diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
index 67378bd0cd81e6bf31ae3148faffa863b88260b0..09af05c0dfbac396c3860eafb943c0d3ccc4c92a 100644
--- a/core/java/android/net/Uri.java
+++ b/core/java/android/net/Uri.java
@@ -1746,8 +1746,8 @@ public abstract class Uri implements Parcelable, Comparable {
* begin with and a scheme component cannot be found.
*
* @return normalized Uri (never null)
- * @see {@link android.content.Intent#setData}
- * @see {@link android.content.Intent#setDataAndNormalize}
+ * @see android.content.Intent#setData
+ * @see android.content.Intent#setDataAndNormalize
*/
public Uri normalizeScheme() {
String scheme = getScheme();
diff --git a/core/java/android/net/metrics/DnsEvent.java b/core/java/android/net/metrics/DnsEvent.java
index 4fc6b7aaf8425815d8a7db460812d048bd52a20f..6176b2c58deb40deb41b299a20509366685dbbb3 100644
--- a/core/java/android/net/metrics/DnsEvent.java
+++ b/core/java/android/net/metrics/DnsEvent.java
@@ -21,7 +21,7 @@ import android.os.Parcel;
import android.os.Parcelable;
/**
- * An event recorded by DnsEventListenerService.
+ * A DNS event recorded by NetdEventListenerService.
* {@hide}
*/
@SystemApi
diff --git a/core/java/android/net/metrics/IpManagerEvent.java b/core/java/android/net/metrics/IpManagerEvent.java
index a5b4eb5aff86f7920c3e28bb5de7b770e5317333..e0a026ed678d1937bd3c868d41b83050a8482791 100644
--- a/core/java/android/net/metrics/IpManagerEvent.java
+++ b/core/java/android/net/metrics/IpManagerEvent.java
@@ -38,9 +38,15 @@ public final class IpManagerEvent implements Parcelable {
public static final int PROVISIONING_OK = 1;
public static final int PROVISIONING_FAIL = 2;
public static final int COMPLETE_LIFECYCLE = 3;
+ /** @hide */ public static final int ERROR_STARTING_IPV4 = 4;
+ /** @hide */ public static final int ERROR_STARTING_IPV6 = 5;
+ /** @hide */ public static final int ERROR_STARTING_IPREACHABILITYMONITOR = 6;
/** {@hide} */
- @IntDef(value = {PROVISIONING_OK, PROVISIONING_FAIL, COMPLETE_LIFECYCLE})
+ @IntDef(value = {
+ PROVISIONING_OK, PROVISIONING_FAIL, COMPLETE_LIFECYCLE,
+ ERROR_STARTING_IPV4, ERROR_STARTING_IPV6, ERROR_STARTING_IPREACHABILITYMONITOR,
+ })
@Retention(RetentionPolicy.SOURCE)
public @interface EventType {}
@@ -95,6 +101,7 @@ public final class IpManagerEvent implements Parcelable {
final static class Decoder {
static final SparseArray constants = MessageUtils.findMessageNames(
- new Class[]{IpManagerEvent.class}, new String[]{"PROVISIONING_", "COMPLETE_"});
+ new Class[]{IpManagerEvent.class},
+ new String[]{"PROVISIONING_", "COMPLETE_", "ERROR_"});
}
}
diff --git a/core/java/android/net/metrics/NetworkEvent.java b/core/java/android/net/metrics/NetworkEvent.java
index 3b3fa6976fc982181a7ee57103b47b62ef00bf93..06674950a044d5a49724b7afece6c8fe6f4c890c 100644
--- a/core/java/android/net/metrics/NetworkEvent.java
+++ b/core/java/android/net/metrics/NetworkEvent.java
@@ -41,6 +41,15 @@ public final class NetworkEvent implements Parcelable {
public static final int NETWORK_UNLINGER = 6;
public static final int NETWORK_DISCONNECTED = 7;
+ /** {@hide} */
+ public static final int NETWORK_FIRST_VALIDATION_SUCCESS = 8;
+ /** {@hide} */
+ public static final int NETWORK_REVALIDATION_SUCCESS = 9;
+ /** {@hide} */
+ public static final int NETWORK_FIRST_VALIDATION_PORTAL_FOUND = 10;
+ /** {@hide} */
+ public static final int NETWORK_REVALIDATION_PORTAL_FOUND = 11;
+
/** {@hide} */
@IntDef(value = {
NETWORK_CONNECTED,
@@ -50,6 +59,10 @@ public final class NetworkEvent implements Parcelable {
NETWORK_LINGER,
NETWORK_UNLINGER,
NETWORK_DISCONNECTED,
+ NETWORK_FIRST_VALIDATION_SUCCESS,
+ NETWORK_REVALIDATION_SUCCESS,
+ NETWORK_FIRST_VALIDATION_PORTAL_FOUND,
+ NETWORK_REVALIDATION_PORTAL_FOUND,
})
@Retention(RetentionPolicy.SOURCE)
public @interface EventType {}
diff --git a/core/java/android/net/metrics/ValidationProbeEvent.java b/core/java/android/net/metrics/ValidationProbeEvent.java
index 1a31b56f1ffb62f8a46d51af360e1ecb17b7ba68..a724ec12ed324b9100f3fe3beba0fb36ab276394 100644
--- a/core/java/android/net/metrics/ValidationProbeEvent.java
+++ b/core/java/android/net/metrics/ValidationProbeEvent.java
@@ -44,10 +44,8 @@ public final class ValidationProbeEvent implements Parcelable {
public static final int DNS_FAILURE = 0;
public static final int DNS_SUCCESS = 1;
- /** {@hide} */
- @IntDef(value = {PROBE_DNS, PROBE_HTTP, PROBE_HTTPS, PROBE_PAC})
- @Retention(RetentionPolicy.SOURCE)
- public @interface ProbeType {}
+ private static final int FIRST_VALIDATION = 1 << 8;
+ private static final int REVALIDATION = 2 << 8;
/** {@hide} */
@IntDef(value = {DNS_FAILURE, DNS_SUCCESS})
@@ -56,12 +54,17 @@ public final class ValidationProbeEvent implements Parcelable {
public final int netId;
public final long durationMs;
- public final @ProbeType int probeType;
+ // probeType byte format (MSB to LSB):
+ // byte 0: unused
+ // byte 1: unused
+ // byte 2: 0 = UNKNOWN, 1 = FIRST_VALIDATION, 2 = REVALIDATION
+ // byte 3: PROBE_* constant
+ public final int probeType;
public final @ReturnCode int returnCode;
/** {@hide} */
public ValidationProbeEvent(
- int netId, long durationMs, @ProbeType int probeType, @ReturnCode int returnCode) {
+ int netId, long durationMs, int probeType, @ReturnCode int returnCode) {
this.netId = netId;
this.durationMs = durationMs;
this.probeType = probeType;
@@ -99,9 +102,19 @@ public final class ValidationProbeEvent implements Parcelable {
}
};
+ /** @hide */
+ public static int makeProbeType(int probeType, boolean firstValidation) {
+ return (probeType & 0xff) | (firstValidation ? FIRST_VALIDATION : REVALIDATION);
+ }
+
/** @hide */
public static String getProbeName(int probeType) {
- return Decoder.constants.get(probeType, "PROBE_???");
+ return Decoder.constants.get(probeType & 0xff, "PROBE_???");
+ }
+
+ /** @hide */
+ public static String getValidationStage(int probeType) {
+ return Decoder.constants.get(probeType & 0xff00, "UNKNOWN");
}
public static void logEvent(int netId, long durationMs, int probeType, int returnCode) {
@@ -109,12 +122,13 @@ public final class ValidationProbeEvent implements Parcelable {
@Override
public String toString() {
- return String.format("ValidationProbeEvent(%d, %s:%d, %dms)",
- netId, getProbeName(probeType), returnCode, durationMs);
+ return String.format("ValidationProbeEvent(%d, %s:%d %s, %dms)", netId,
+ getProbeName(probeType), returnCode, getValidationStage(probeType), durationMs);
}
final static class Decoder {
static final SparseArray constants = MessageUtils.findMessageNames(
- new Class[]{ValidationProbeEvent.class}, new String[]{"PROBE_"});
+ new Class[]{ValidationProbeEvent.class},
+ new String[]{"PROBE_", "FIRST_", "REVALIDATION"});
}
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index a0c2efd407ba0387936c732bf175ab7ec5bd41b3..0bb05b5a22a288a5e1e6f2b82e757ce30840027a 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -182,7 +182,7 @@ public abstract class BatteryStats implements Parcelable {
* New in version 19:
* - Wakelock data (wl) gets current and max times.
*/
- static final String CHECKIN_VERSION = "19";
+ static final String CHECKIN_VERSION = "20";
/**
* Old version, we hit 9 and ran out of room, need to remove.
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
new file mode 100644
index 0000000000000000000000000000000000000000..e4cdbce09796f1cd21aa9c05e94e2299d462cbd3
--- /dev/null
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.opengl.EGL14;
+import android.os.SystemProperties;
+import android.util.Log;
+
+import dalvik.system.VMRuntime;
+
+import java.io.File;
+
+/** @hide */
+public final class GraphicsEnvironment {
+
+ private static final boolean DEBUG = false;
+ private static final String TAG = "GraphicsEnvironment";
+ private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0";
+
+ public static void setupGraphicsEnvironment(Context context) {
+ chooseDriver(context);
+
+ // Now that we've figured out which driver to use for this process, load and initialize it.
+ // This can take multiple frame periods, and it would otherwise happen as part of the first
+ // frame, increasing first-frame latency. Starting it here, as a low-priority background
+ // thread, means that it's usually done long before we start drawing the first frame,
+ // without significantly disrupting other activity launch work.
+ Thread eglInitThread = new Thread(
+ () -> {
+ EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
+ },
+ "EGL Init");
+ eglInitThread.start();
+ }
+
+ private static void chooseDriver(Context context) {
+ String driverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER);
+ if (driverPackageName == null || driverPackageName.isEmpty()) {
+ return;
+ }
+ // To minimize risk of driver updates crippling the device beyond user repair, never use an
+ // updated driver for privileged or non-updated system apps. Presumably pre-installed apps
+ // were tested thoroughly with the pre-installed driver.
+ ApplicationInfo ai = context.getApplicationInfo();
+ if (ai.isPrivilegedApp() || (ai.isSystemApp() && !ai.isUpdatedSystemApp())) {
+ if (DEBUG) Log.v(TAG, "ignoring driver package for privileged/non-updated system app");
+ return;
+ }
+ ApplicationInfo driverInfo;
+ try {
+ driverInfo = context.getPackageManager().getApplicationInfo(driverPackageName,
+ PackageManager.MATCH_SYSTEM_ONLY);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "driver package '" + driverPackageName + "' not installed");
+ return;
+ }
+ String abi = chooseAbi(driverInfo);
+ if (abi == null) {
+ if (DEBUG) {
+ // This is the normal case for the pre-installed empty driver package, don't spam
+ if (driverInfo.isUpdatedSystemApp()) {
+ Log.w(TAG, "updated driver package has no compatible native libraries");
+ }
+ }
+ return;
+ }
+
+ StringBuilder sb = new StringBuilder();
+ sb.append(driverInfo.nativeLibraryDir)
+ .append(File.pathSeparator);
+ sb.append(driverInfo.sourceDir)
+ .append("!/lib/")
+ .append(abi);
+ String paths = sb.toString();
+
+ if (DEBUG) Log.v(TAG, "gfx driver package libs: " + paths);
+ setDriverPath(paths);
+ }
+
+ private static String chooseAbi(ApplicationInfo ai) {
+ String isa = VMRuntime.getCurrentInstructionSet();
+ if (ai.primaryCpuAbi != null &&
+ isa.equals(VMRuntime.getInstructionSet(ai.primaryCpuAbi))) {
+ return ai.primaryCpuAbi;
+ }
+ if (ai.secondaryCpuAbi != null &&
+ isa.equals(VMRuntime.getInstructionSet(ai.secondaryCpuAbi))) {
+ return ai.secondaryCpuAbi;
+ }
+ return null;
+ }
+
+ private static native void setDriverPath(String path);
+
+}
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index eeb641d33c20d4da561c1dc8f577e7b6e89b95a6..394866941d43e74f9f7f5b50f0057b5c2ed680fe 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -82,4 +82,7 @@ interface IUserManager {
boolean someUserHasSeedAccount(in String accountName, in String accountType);
boolean isManagedProfile(int userId);
boolean isDemoUser(int userId);
+ boolean isUserUnlocked(int userId);
+ boolean isUserUnlockingOrUnlocked(int userId);
+ boolean isUserRunning(int userId);
}
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index eba27991c314eec9b45abe7738a45830a77cf3cf..f4ff6a3b6477d2cbfa5418667404eab7e995c775 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -49,23 +49,23 @@ import android.util.Log;
* These levels are mutually exclusive - you may only specify one of them.
*
*
- *
Flag Value
+ *
Flag Value
*
CPU
Screen
Keyboard
*
*
{@link #PARTIAL_WAKE_LOCK}
- *
On*
Off
Off
+ *
On*
Off
Off
*
- *
+ *
*
{@link #SCREEN_DIM_WAKE_LOCK}
- *
On
Dim
Off
+ *
On
Dim
Off
*
*
*
{@link #SCREEN_BRIGHT_WAKE_LOCK}
- *
On
Bright
Off
+ *
On
Bright
Off
*
- *
+ *
*
{@link #FULL_WAKE_LOCK}
- *
On
Bright
Bright
+ *
On
Bright
Bright
*
*
*
@@ -85,13 +85,13 @@ import android.util.Log;
* the illumination to remain on once it turns on (e.g. from user activity). This flag
* will force the screen and/or keyboard to turn on immediately, when the WakeLock is
* acquired. A typical use would be for notifications which are important for the user to
- * see immediately.
+ * see immediately.
*
- *
+ *
*
{@link #ON_AFTER_RELEASE}
*
If this flag is set, the user activity timer will be reset when the WakeLock is
- * released, causing the illumination to remain on a bit longer. This can be used to
- * reduce flicker if you are cycling between wake lock conditions.
+ * released, causing the illumination to remain on a bit longer. This can be used to
+ * reduce flicker if you are cycling between wake lock conditions.
*
*
*
@@ -473,12 +473,32 @@ public final class PowerManager {
}
/**
- * Returns true if the twilight service should be used to adjust screen brightness
- * policy. This setting is experimental and disabled by default.
+ * Gets the minimum supported screen brightness setting for VR Mode.
+ * @hide
+ */
+ public int getMinimumScreenBrightnessForVrSetting() {
+ return mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_screenBrightnessForVrSettingMinimum);
+ }
+
+ /**
+ * Gets the maximum supported screen brightness setting for VR Mode.
+ * The screen may be allowed to become dimmer than this value but
+ * this is the maximum value that can be set by the user.
* @hide
*/
- public static boolean useTwilightAdjustmentFeature() {
- return SystemProperties.getBoolean("persist.power.usetwilightadj", false);
+ public int getMaximumScreenBrightnessForVrSetting() {
+ return mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_screenBrightnessForVrSettingMaximum);
+ }
+
+ /**
+ * Gets the default screen brightness for VR setting.
+ * @hide
+ */
+ public int getDefaultScreenBrightnessForVrSetting() {
+ return mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_screenBrightnessForVrSettingDefault);
}
/**
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index c36b48886f370ae7ded4bf575fb327cbbe4b5417..287092320921b9e5bce1c49db66cb5c9f9cdac01 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -1432,9 +1432,6 @@ public final class StrictMode {
if (violations == null) {
violations = new ArrayList(1);
gatheredViolations.set(violations);
- } else if (violations.size() >= 5) {
- // Too many. In a loop or something? Don't gather them all.
- return;
}
for (ViolationInfo previous : violations) {
if (info.crashInfo.stackTrace.equals(previous.crashInfo.stackTrace)) {
@@ -1931,18 +1928,14 @@ public final class StrictMode {
if (violations == null) {
p.writeInt(0);
} else {
- p.writeInt(violations.size());
- for (int i = 0; i < violations.size(); ++i) {
- int start = p.dataPosition();
- violations.get(i).writeToParcel(p, 0 /* unused flags? */);
- int size = p.dataPosition()-start;
- if (size > 10*1024) {
- Slog.d(TAG, "Wrote violation #" + i + " of " + violations.size() + ": "
- + (p.dataPosition()-start) + " bytes");
- }
+ // To avoid taking up too much transaction space, only include
+ // details for the first 3 violations. Deep inside, CrashInfo
+ // will truncate each stack trace to ~20kB.
+ final int size = Math.min(violations.size(), 3);
+ p.writeInt(size);
+ for (int i = 0; i < size; i++) {
+ violations.get(i).writeToParcel(p, 0);
}
- if (LOG_V) Log.d(TAG, "wrote violations to response parcel; num=" + violations.size());
- violations.clear(); // somewhat redundant, as we're about to null the threadlocal
}
gatheredViolations.set(null);
}
@@ -1956,40 +1949,19 @@ public final class StrictMode {
/* package */ static void readAndHandleBinderCallViolations(Parcel p) {
// Our own stack trace to append
StringWriter sw = new StringWriter();
+ sw.append("# via Binder call with stack:\n");
PrintWriter pw = new FastPrintWriter(sw, false, 256);
new LogStackTrace().printStackTrace(pw);
pw.flush();
String ourStack = sw.toString();
- int policyMask = getThreadPolicyMask();
- boolean currentlyGathering = (policyMask & PENALTY_GATHER) != 0;
-
- int numViolations = p.readInt();
- for (int i = 0; i < numViolations; ++i) {
- if (LOG_V) Log.d(TAG, "strict mode violation stacks read from binder call. i=" + i);
- ViolationInfo info = new ViolationInfo(p, !currentlyGathering);
- if (info.crashInfo.stackTrace != null && info.crashInfo.stackTrace.length() > 30000) {
- String front = info.crashInfo.stackTrace.substring(0, 256);
- // 30000 characters is way too large for this to be any sane kind of
- // strict mode collection of stacks. We've had a problem where we leave
- // strict mode violations associated with the thread, and it keeps tacking
- // more and more stacks on to the violations. Looks like we're in this casse,
- // so we'll report it and bail on all of the current strict mode violations
- // we currently are maintaining for this thread.
- // First, drain the remaining violations from the parcel.
- i++; // Skip the current entry.
- for (; i < numViolations; i++) {
- info = new ViolationInfo(p, !currentlyGathering);
- }
- // Next clear out all gathered violations.
- clearGatheredViolations();
- // Now report the problem.
- Slog.wtfStack(TAG, "Stack is too large: numViolations=" + numViolations
- + " policy=#" + Integer.toHexString(policyMask)
- + " front=" + front);
- return;
- }
- info.crashInfo.stackTrace += "# via Binder call with stack:\n" + ourStack;
+ final int policyMask = getThreadPolicyMask();
+ final boolean currentlyGathering = (policyMask & PENALTY_GATHER) != 0;
+
+ final int size = p.readInt();
+ for (int i = 0; i < size; i++) {
+ final ViolationInfo info = new ViolationInfo(p, !currentlyGathering);
+ info.crashInfo.appendStackTrace(ourStack);
BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
if (policy instanceof AndroidBlockGuardPolicy) {
((AndroidBlockGuardPolicy) policy).handleViolationWithTimingAttempt(info);
@@ -2320,7 +2292,7 @@ public final class StrictMode {
* @hide
*/
public static class ViolationInfo {
- public String message;
+ public final String message;
/**
* Stack and other stuff info.
@@ -2379,6 +2351,7 @@ public final class StrictMode {
* Create an uninitialized instance of ViolationInfo
*/
public ViolationInfo() {
+ message = null;
crashInfo = null;
policy = 0;
}
@@ -2425,7 +2398,9 @@ public final class StrictMode {
@Override
public int hashCode() {
int result = 17;
- result = 37 * result + crashInfo.stackTrace.hashCode();
+ if (crashInfo != null) {
+ result = 37 * result + crashInfo.stackTrace.hashCode();
+ }
if (numAnimationsRunning != 0) {
result *= 37;
}
@@ -2455,7 +2430,11 @@ public final class StrictMode {
*/
public ViolationInfo(Parcel in, boolean unsetGatheringBit) {
message = in.readString();
- crashInfo = new ApplicationErrorReport.CrashInfo(in);
+ if (in.readInt() != 0) {
+ crashInfo = new ApplicationErrorReport.CrashInfo(in);
+ } else {
+ crashInfo = null;
+ }
int rawPolicy = in.readInt();
if (unsetGatheringBit) {
policy = rawPolicy & ~PENALTY_GATHER;
@@ -2476,7 +2455,12 @@ public final class StrictMode {
*/
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(message);
- crashInfo.writeToParcel(dest, flags);
+ if (crashInfo != null) {
+ dest.writeInt(1);
+ crashInfo.writeToParcel(dest, flags);
+ } else {
+ dest.writeInt(0);
+ }
int start = dest.dataPosition();
dest.writeInt(policy);
dest.writeInt(durationMillis);
@@ -2504,7 +2488,9 @@ public final class StrictMode {
* Dump a ViolationInfo instance to a Printer.
*/
public void dump(Printer pw, String prefix) {
- crashInfo.dump(pw, prefix);
+ if (crashInfo != null) {
+ crashInfo.dump(pw, prefix);
+ }
pw.println(prefix + "policy: " + policy);
if (durationMillis != -1) {
pw.println(prefix + "durationMillis: " + durationMillis);
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 9e778cf36970e8536992c71cf9e8daea3015a71c..cad5e9ff31a51279dcf37558bb530edbc63a72dc 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -973,9 +973,8 @@ public class UserManager {
/** {@hide} */
public boolean isUserRunning(int userId) {
- // TODO Switch to using UMS internal isUserRunning
try {
- return ActivityManagerNative.getDefault().isUserRunning(userId, 0);
+ return mService.isUserRunning(userId);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -1072,8 +1071,7 @@ public class UserManager {
/** {@hide} */
public boolean isUserUnlocked(@UserIdInt int userId) {
try {
- return ActivityManagerNative.getDefault().isUserRunning(userId,
- ActivityManager.FLAG_AND_UNLOCKED);
+ return mService.isUserUnlocked(userId);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -1086,10 +1084,8 @@ public class UserManager {
/** {@hide} */
public boolean isUserUnlockingOrUnlocked(@UserIdInt int userId) {
- // TODO Switch to using UMS internal isUserUnlockingOrUnlocked
try {
- return ActivityManagerNative.getDefault().isUserRunning(userId,
- ActivityManager.FLAG_AND_UNLOCKING_OR_UNLOCKED);
+ return mService.isUserUnlockingOrUnlocked(userId);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
diff --git a/core/java/android/os/UserManagerInternal.java b/core/java/android/os/UserManagerInternal.java
index 93afb4376cf293a6add1599caa6837d9a714da46..e42704ca2141cdca947098d2740392f2bed13195 100644
--- a/core/java/android/os/UserManagerInternal.java
+++ b/core/java/android/os/UserManagerInternal.java
@@ -134,6 +134,12 @@ public abstract class UserManagerInternal {
*/
public abstract boolean isUserUnlockingOrUnlocked(int userId);
+ /**
+ * Return whether the given user is running in an
+ * {@code UserState.STATE_RUNNING_UNLOCKED} state.
+ */
+ public abstract boolean isUserUnlocked(int userId);
+
/**
* Return whether the given user is running
*/
diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java
index b1cad0538d312ce193c12456b71fb4205fbee336..ec1e102c92896fb41a5b7bfe84740e8e55bf1851 100644
--- a/core/java/android/preference/Preference.java
+++ b/core/java/android/preference/Preference.java
@@ -719,6 +719,9 @@ public class Preference implements Comparable {
* @see #setIcon(Drawable)
*/
public Drawable getIcon() {
+ if (mIcon == null && mIconResId != 0) {
+ mIcon = getContext().getDrawable(mIconResId);
+ }
return mIcon;
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index dd2a5dea9611cfcbf32d16eef2f5bfd52814b92c..c83bd3e78e97136a20b1cb61d8bba6cfac88b343 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2818,6 +2818,15 @@ public final class Settings {
private static final Validator SCREEN_BRIGHTNESS_VALIDATOR =
new InclusiveIntegerRangeValidator(0, 255);
+ /**
+ * The screen backlight brightness between 0 and 255.
+ * @hide
+ */
+ public static final String SCREEN_BRIGHTNESS_FOR_VR = "screen_brightness_for_vr";
+
+ private static final Validator SCREEN_BRIGHTNESS_FOR_VR_VALIDATOR =
+ new InclusiveIntegerRangeValidator(0, 255);
+
/**
* Control whether to enable automatic brightness mode.
*/
@@ -3873,6 +3882,7 @@ public final class Settings {
VALIDATORS.put(DIM_SCREEN, DIM_SCREEN_VALIDATOR);
VALIDATORS.put(SCREEN_OFF_TIMEOUT, SCREEN_OFF_TIMEOUT_VALIDATOR);
VALIDATORS.put(SCREEN_BRIGHTNESS, SCREEN_BRIGHTNESS_VALIDATOR);
+ VALIDATORS.put(SCREEN_BRIGHTNESS_FOR_VR, SCREEN_BRIGHTNESS_FOR_VR_VALIDATOR);
VALIDATORS.put(SCREEN_BRIGHTNESS_MODE, SCREEN_BRIGHTNESS_MODE_VALIDATOR);
VALIDATORS.put(MODE_RINGER_STREAMS_AFFECTED, MODE_RINGER_STREAMS_AFFECTED_VALIDATOR);
VALIDATORS.put(MUTE_STREAMS_AFFECTED, MUTE_STREAMS_AFFECTED_VALIDATOR);
@@ -5546,6 +5556,13 @@ public final class Settings {
*/
public static final String LONG_PRESS_TIMEOUT = "long_press_timeout";
+ /**
+ * The duration in milliseconds between the first tap's up event and the second tap's
+ * down event for an interaction to be considered part of the same multi-press.
+ * @hide
+ */
+ public static final String MULTI_PRESS_TIMEOUT = "multi_press_timeout";
+
/**
* List of the enabled print services.
*
@@ -6118,6 +6135,36 @@ public final class Settings {
public static final int INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT =
INCALL_POWER_BUTTON_BEHAVIOR_SCREEN_OFF;
+ /**
+ * What happens when the user presses the Back button while in-call
+ * and the screen is on.
+ * Values:
+ * 0 - The Back buttons does nothing different.
+ * 1 - The Back button hangs up the current call.
+ *
+ * @hide
+ */
+ public static final String INCALL_BACK_BUTTON_BEHAVIOR = "incall_back_button_behavior";
+
+ /**
+ * INCALL_BACK_BUTTON_BEHAVIOR value for no action.
+ * @hide
+ */
+ public static final int INCALL_BACK_BUTTON_BEHAVIOR_NONE = 0x0;
+
+ /**
+ * INCALL_BACK_BUTTON_BEHAVIOR value for "hang up".
+ * @hide
+ */
+ public static final int INCALL_BACK_BUTTON_BEHAVIOR_HANGUP = 0x1;
+
+ /**
+ * INCALL_POWER_BUTTON_BEHAVIOR default value.
+ * @hide
+ */
+ public static final int INCALL_BACK_BUTTON_BEHAVIOR_DEFAULT =
+ INCALL_BACK_BUTTON_BEHAVIOR_NONE;
+
/**
* Whether the device should wake when the wake gesture sensor detects motion.
* @hide
@@ -6309,6 +6356,14 @@ public final class Settings {
public static final String LOCK_SCREEN_SHOW_NOTIFICATIONS =
"lock_screen_show_notifications";
+ /**
+ * This preference stores the last stack active task time for each user, which affects what
+ * tasks will be visible in Overview.
+ * @hide
+ */
+ public static final String OVERVIEW_LAST_STACK_ACTIVE_TIME =
+ "overview_last_stack_active_time";
+
/**
* List of TV inputs that are currently hidden. This is a string
* containing the IDs of all hidden TV inputs. Each ID is encoded by
@@ -6420,12 +6475,6 @@ public final class Settings {
*/
public static final String NIGHT_DISPLAY_CUSTOM_END_TIME = "night_display_custom_end_time";
- /**
- * Whether brightness should automatically adjust based on twilight state.
- * @hide
- */
- public static final String BRIGHTNESS_USE_TWILIGHT = "brightness_use_twilight";
-
/**
* Names of the service components that the current user has explicitly allowed to
* be a VR mode listener, separated by ':'.
@@ -6551,6 +6600,12 @@ public final class Settings {
*/
public static final String WEB_ACTION_ENABLED = "web_action_enabled";
+ /**
+ * Has this pairable device been paired or upgraded from a previously paired system.
+ * @hide
+ */
+ public static final String DEVICE_PAIRED = "device_paired";
+
/**
* Whether to include options in power menu for rebooting into recovery or bootloader
* @hide
@@ -6648,6 +6703,7 @@ public final class Settings {
DOZE_ENABLED,
DOZE_PULSE_ON_PICK_UP,
DOZE_PULSE_ON_DOUBLE_TAP,
+ NFC_PAYMENT_DEFAULT_COMPONENT,
ADVANCED_REBOOT,
CAMERA_GESTURE_DISABLED
};
@@ -7035,6 +7091,12 @@ public final class Settings {
*/
public static final String DOCK_SOUNDS_ENABLED = "dock_sounds_enabled";
+ /**
+ * Whether to play a sound for dock events, only when an accessibility service is on.
+ * @hide
+ */
+ public static final String DOCK_SOUNDS_ENABLED_WHEN_ACCESSIBILITY = "dock_sounds_enabled_when_accessbility";
+
/**
* URI for the "device locked" (keyguard shown) sound.
* @hide
@@ -7337,6 +7399,13 @@ public final class Settings {
*/
public static final String MOBILE_DATA_ALWAYS_ON = "mobile_data_always_on";
+ /**
+ * Size of the event buffer for IP connectivity metrics.
+ * @hide
+ */
+ public static final String CONNECTIVITY_METRICS_BUFFER_SIZE =
+ "connectivity_metrics_buffer_size";
+
/** {@hide} */
public static final String NETSTATS_ENABLED = "netstats_enabled";
/** {@hide} */
@@ -7762,6 +7831,13 @@ public final class Settings {
public static final String WIMAX_NETWORKS_AVAILABLE_NOTIFICATION_ON =
"wimax_networks_available_notification_on";
+ /**
+ * Whether we support connecting to Carrier Networks.
+ * @hide
+ **/
+ public static final String WIFI_CONNECT_CARRIER_NETWORKS =
+ "wifi_connect_carrier_networks";
+
/**
* Delay (in seconds) before repeating the Wi-Fi networks available notification.
* Connecting to a network will reset the timer.
@@ -8189,12 +8265,46 @@ public final class Settings {
*/
public static final String PAC_CHANGE_DELAY = "pac_change_delay";
+ /**
+ * Don't attempt to detect captive portals.
+ *
+ * @hide
+ */
+ public static final int CAPTIVE_PORTAL_MODE_IGNORE = 0;
+
+ /**
+ * When detecting a captive portal, display a notification that
+ * prompts the user to sign in.
+ *
+ * @hide
+ */
+ public static final int CAPTIVE_PORTAL_MODE_PROMPT = 1;
+
+ /**
+ * When detecting a captive portal, immediately disconnect from the
+ * network and do not reconnect to that network in the future.
+ *
+ * @hide
+ */
+ public static final int CAPTIVE_PORTAL_MODE_AVOID = 2;
+
+ /**
+ * What to do when connecting a network that presents a captive portal.
+ * Must be one of the CAPTIVE_PORTAL_MODE_* constants above.
+ *
+ * The default for this setting is CAPTIVE_PORTAL_MODE_PROMPT.
+ * @hide
+ */
+ public static final String CAPTIVE_PORTAL_MODE = "captive_portal_mode";
+
/**
* Setting to turn off captive portal detection. Feature is enabled by
* default and the setting needs to be set to 0 to disable it.
*
+ * @deprecated use CAPTIVE_PORTAL_MODE_IGNORE to disable captive portal detection
* @hide
*/
+ @Deprecated
public static final String
CAPTIVE_PORTAL_DETECTION_ENABLED = "captive_portal_detection_enabled";
@@ -9575,6 +9685,24 @@ public final class Settings {
* @hide
*/
public static final String CELL_ON = "cell_on";
+
+ /**
+ * Whether to show the high temperature warning notification.
+ * @hide
+ */
+ public static final String SHOW_TEMPERATURE_WARNING = "show_temperature_warning";
+
+ /**
+ * Temperature at which the high temperature warning notification should be shown.
+ * @hide
+ */
+ public static final String WARNING_TEMPERATURE = "warning_temperature";
+
+ /**
+ * Whether the diskstats logging task is enabled/disabled.
+ * @hide
+ */
+ public static final String ENABLE_DISKSTATS_LOGGING = "enable_diskstats_logging";
}
/**
diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java
index 5099eebf6eb1600000495e4ee17c6115f6282214..1e5416382f8c5c3593bcf212fe15d3d8a7211ef5 100644
--- a/core/java/android/provider/VoicemailContract.java
+++ b/core/java/android/provider/VoicemailContract.java
@@ -30,6 +30,7 @@ import android.provider.CallLog.Calls;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.Voicemail;
+
import java.util.List;
/**
@@ -317,6 +318,48 @@ public class VoicemailContract {
*/
public static final String LAST_MODIFIED = "last_modified";
+ /**
+ * Flag to indicate the voicemail was backed up. The value will be 1 if backed up, 0 if
+ * not.
+ *
+ *
Type: INTEGER (boolean)
+ *
+ * @hide
+ */
+ public static final String BACKED_UP = "backed_up";
+
+ /**
+ * Flag to indicate the voicemail was restored from a backup. The value will be 1 if
+ * restored, 0 if not.
+ *
+ *
Type: INTEGER (boolean)
+ *
+ * @hide
+ */
+ public static final String RESTORED = "restored";
+
+ /**
+ * Flag to indicate the voicemail was marked as archived. Archived voicemail should not be
+ * deleted even if it no longer exist on the server. The value will be 1 if archived true, 0
+ * if not.
+ *
+ *
Type: INTEGER (boolean)
+ *
+ * @hide
+ */
+ public static final String ARCHIVED = "archived";
+
+ /**
+ * Flag to indicate the voicemail is a OMTP voicemail handled by the {@link
+ * android.telephony.VisualVoicemailService}. The UI should only show OMTP voicemails from
+ * the current visual voicemail package.
+ *
+ *
Type: INTEGER (boolean)
+ *
+ * @hide
+ */
+ public static final String IS_OMTP_VOICEMAIL = "is_omtp_voicemail";
+
/**
* A convenience method to build voicemail URI specific to a source package by appending
* {@link VoicemailContract#PARAM_KEY_SOURCE_PACKAGE} param to the base URI.
diff --git a/core/java/android/security/IKeystoreService.aidl b/core/java/android/security/IKeystoreService.aidl
index 8689dce3fef5505ca439de4ed44c324264730a9d..641e1ada6eaa2382a0866779769c353fe4d764b1 100644
--- a/core/java/android/security/IKeystoreService.aidl
+++ b/core/java/android/security/IKeystoreService.aidl
@@ -76,4 +76,5 @@ interface IKeystoreService {
int onUserAdded(int userId, int parentId);
int onUserRemoved(int userId);
int attestKey(String alias, in KeymasterArguments params, out KeymasterCertificateChain chain);
+ int onDeviceOffBody();
}
diff --git a/core/java/android/service/carrier/CarrierService.java b/core/java/android/service/carrier/CarrierService.java
index 455e1b25df18e258e4c29e4aeb57e3532c6f2dbf..813acc232289eb791a25b8fc3eecac70558e60f5 100644
--- a/core/java/android/service/carrier/CarrierService.java
+++ b/core/java/android/service/carrier/CarrierService.java
@@ -107,12 +107,12 @@ public abstract class CarrierService extends Service {
*
* Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges.
- * @see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}
+ * or the calling app has carrier privileges.
*
* @param active Whether the carrier network change is or shortly will be
* active. Set this value to true to begin showing
* alternative UI and false to stop.
+ * @see android.telephony.TelephonyManager#hasCarrierPrivileges
*/
public final void notifyCarrierNetworkChange(boolean active) {
try {
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index c1da0f107995af9f44c5b3935d833cd149c3b6f1..abb48aefdd4b17456ec7dd542ad47f3ba937b514 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -785,7 +785,7 @@ public abstract class NotificationListenerService extends Service {
}
/**
- * Request that the listener be rebound, after a previous call to (@link requestUnbind).
+ * Request that the listener be rebound, after a previous call to {@link #requestUnbind}.
*
*
This method will fail for listeners that have
* not been granted the permission by the user.
diff --git a/core/java/android/text/Editable.java b/core/java/android/text/Editable.java
index b3f2c2a5c447f5f0f92ed628ebf67403b3780541..519ccd2560f633bd249adaceab8d92e27a13c2e6 100644
--- a/core/java/android/text/Editable.java
+++ b/core/java/android/text/Editable.java
@@ -94,10 +94,10 @@ extends CharSequence, GetChars, Spannable, Appendable
public Editable append(char text);
/**
- * Convenience for replace(0, length(), "", 0, 0)
- * @see #replace(int, int, CharSequence, int, int)
+ * Convenience for replace(0, length(), "", 0, 0).
* Note that this clears the text, not the spans;
* use {@link #clearSpans} if you need that.
+ * @see #replace(int, int, CharSequence, int, int)
*/
public void clear();
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index dc8e4b93e093929916538b7566b81f52f77b9c27..cdf7e8b092210efe399624be2935f1303638c95b 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -21,6 +21,7 @@ import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.GrowingArrayUtils;
@@ -73,8 +74,6 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
mSpanFlags = EmptyArray.INT;
mSpanMax = EmptyArray.INT;
mSpanOrder = EmptyArray.INT;
- mPrioSortBuffer = EmptyArray.INT;
- mOrderSortBuffer = EmptyArray.INT;
if (text instanceof Spanned) {
Spanned sp = (Spanned) text;
@@ -856,14 +855,14 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
* @param queryStart Start index.
* @param queryEnd End index.
* @param kind Class type to search for.
- * @param sort If true the results are sorted by the insertion order.
+ * @param sortByInsertionOrder If true the results are sorted by the insertion order.
* @param
* @return Array of the spans. Empty array if no results are found.
*
* @hide
*/
public T[] getSpans(int queryStart, int queryEnd, @Nullable Class kind,
- boolean sort) {
+ boolean sortByInsertionOrder) {
if (kind == null) return (T[]) ArrayUtils.emptyArray(Object.class);
if (mSpanCount == 0) return ArrayUtils.emptyArray(kind);
int count = countSpans(queryStart, queryEnd, kind, treeRoot());
@@ -873,13 +872,15 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
// Safe conversion, but requires a suppressWarning
T[] ret = (T[]) Array.newInstance(kind, count);
- if (sort) {
- mPrioSortBuffer = checkSortBuffer(mPrioSortBuffer, count);
- mOrderSortBuffer = checkSortBuffer(mOrderSortBuffer, count);
+ final int[] prioSortBuffer = sortByInsertionOrder ? obtain(count) : EmptyArray.INT;
+ final int[] orderSortBuffer = sortByInsertionOrder ? obtain(count) : EmptyArray.INT;
+ getSpansRec(queryStart, queryEnd, kind, treeRoot(), ret, prioSortBuffer,
+ orderSortBuffer, 0, sortByInsertionOrder);
+ if (sortByInsertionOrder) {
+ sort(ret, prioSortBuffer, orderSortBuffer);
+ recycle(prioSortBuffer);
+ recycle(orderSortBuffer);
}
- getSpansRec(queryStart, queryEnd, kind, treeRoot(), ret, mPrioSortBuffer,
- mOrderSortBuffer, 0, sort);
- if (sort) sort(ret, mPrioSortBuffer, mOrderSortBuffer);
return ret;
}
@@ -991,16 +992,64 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
return count;
}
+ /**
+ * Obtain a temporary sort buffer.
+ *
+ * @param elementCount the size of the int[] to be returned
+ * @return an int[] with elementCount length
+ */
+ private static int[] obtain(final int elementCount) {
+ int[] result = null;
+ synchronized (sCachedIntBuffer) {
+ // try finding a tmp buffer with length of at least elementCount
+ // if not get the first available one
+ int candidateIndex = -1;
+ for (int i = sCachedIntBuffer.length - 1; i >= 0; i--) {
+ if (sCachedIntBuffer[i] != null) {
+ if (sCachedIntBuffer[i].length >= elementCount) {
+ candidateIndex = i;
+ break;
+ } else if (candidateIndex == -1) {
+ candidateIndex = i;
+ }
+ }
+ }
+
+ if (candidateIndex != -1) {
+ result = sCachedIntBuffer[candidateIndex];
+ sCachedIntBuffer[candidateIndex] = null;
+ }
+ }
+ result = checkSortBuffer(result, elementCount);
+ return result;
+ }
+
+ /**
+ * Recycle sort buffer.
+ *
+ * @param buffer buffer to be recycled
+ */
+ private static void recycle(int[] buffer) {
+ synchronized (sCachedIntBuffer) {
+ for (int i = 0; i < sCachedIntBuffer.length; i++) {
+ if (sCachedIntBuffer[i] == null || buffer.length > sCachedIntBuffer[i].length) {
+ sCachedIntBuffer[i] = buffer;
+ break;
+ }
+ }
+ }
+ }
+
/**
* Check the size of the buffer and grow if required.
*
- * @param buffer Buffer to be checked.
- * @param size Required size.
+ * @param buffer buffer to be checked.
+ * @param size required size.
* @return Same buffer instance if the current size is greater than required size. Otherwise a
* new instance is created and returned.
*/
- private final int[] checkSortBuffer(int[] buffer, int size) {
- if(size > buffer.length) {
+ private static int[] checkSortBuffer(int[] buffer, int size) {
+ if (buffer == null || size > buffer.length) {
return ArrayUtils.newUnpaddedIntArray(GrowingArrayUtils.growSize(size));
}
return buffer;
@@ -1025,16 +1074,19 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
}
for (int i = size - 1; i > 0; i--) {
- T v = array[0];
- int prio = priority[0];
- int insertOrder = insertionOrder[0];
+ final T tmpSpan = array[0];
array[0] = array[i];
+ array[i] = tmpSpan;
+
+ final int tmpPriority = priority[0];
priority[0] = priority[i];
+ priority[i] = tmpPriority;
+
+ final int tmpOrder = insertionOrder[0];
insertionOrder[0] = insertionOrder[i];
+ insertionOrder[i] = tmpOrder;
+
siftDown(0, array, i, priority, insertionOrder);
- array[i] = v;
- priority[i] = prio;
- insertionOrder[i] = insertOrder;
}
}
@@ -1050,10 +1102,6 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
*/
private final void siftDown(int index, T[] array, int size, int[] priority,
int[] insertionOrder) {
- T v = array[index];
- int prio = priority[index];
- int insertOrder = insertionOrder[index];
-
int left = 2 * index + 1;
while (left < size) {
if (left < size - 1 && compareSpans(left, left + 1, priority, insertionOrder) < 0) {
@@ -1062,15 +1110,22 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
if (compareSpans(index, left, priority, insertionOrder) >= 0) {
break;
}
+
+ final T tmpSpan = array[index];
array[index] = array[left];
+ array[left] = tmpSpan;
+
+ final int tmpPriority = priority[index];
priority[index] = priority[left];
+ priority[left] = tmpPriority;
+
+ final int tmpOrder = insertionOrder[index];
insertionOrder[index] = insertionOrder[left];
+ insertionOrder[left] = tmpOrder;
+
index = left;
left = 2 * index + 1;
}
- array[index] = v;
- priority[index] = prio;
- insertionOrder[index] = insertOrder;
}
/**
@@ -1702,6 +1757,10 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
}
private static final InputFilter[] NO_FILTERS = new InputFilter[0];
+
+ @GuardedBy("sCachedIntBuffer")
+ private static final int[][] sCachedIntBuffer = new int[6][0];
+
private InputFilter[] mFilters = NO_FILTERS;
private char[] mText;
@@ -1715,8 +1774,6 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
private int[] mSpanFlags;
private int[] mSpanOrder; // store the order of span insertion
private int mSpanInsertCount; // counter for the span insertion
- private int[] mPrioSortBuffer; // buffer used to sort getSpans result
- private int[] mOrderSortBuffer; // buffer used to sort getSpans result
private int mSpanCount;
private IdentityHashMap