diff options
65 files changed, 1234 insertions, 850 deletions
diff --git a/cmds/bootanimation/Android.mk b/cmds/bootanimation/Android.mk index 3cf13d908632..3a92b9e74144 100644 --- a/cmds/bootanimation/Android.mk +++ b/cmds/bootanimation/Android.mk @@ -36,8 +36,4 @@ ifdef TARGET_32_BIT_SURFACEFLINGER LOCAL_32_BIT_ONLY := true endif -# get asserts to work -APP_OPTIM := debug -LOCAL_CFLAGS += -UNDEBUG - include $(BUILD_EXECUTABLE) diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 4098772bba12..ebcc9ff0451f 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -588,7 +588,7 @@ bool BootAnimation::preloadZip(Animation& animation) return false; } - bool hasAudio = false; + Animation::Part* partWithAudio = NULL; ZipEntryRO entry; char name[ANIM_ENTRY_NAME_MAX]; while ((entry = zip->nextEntry(cookie)) != NULL) { @@ -612,10 +612,10 @@ bool BootAnimation::preloadZip(Animation& animation) if (map) { Animation::Part& part(animation.parts.editItemAt(j)); if (leaf == "audio.wav") { - hasAudio = true; // a part may have at most one audio file part.audioData = (uint8_t *)map->getDataPtr(); part.audioLength = map->getDataLength(); + partWithAudio = ∂ } else if (leaf == "trim.txt") { part.trimData.setTo((char const*)map->getDataPtr(), map->getDataLength()); @@ -666,9 +666,11 @@ bool BootAnimation::preloadZip(Animation& animation) } // Create and initialize audioplay if there is a wav file in any of the animations. - if (hasAudio) { + if (partWithAudio != NULL) { ALOGD("found audio.wav, creating playback engine"); - audioplay::create(); + if (!audioplay::create(partWithAudio->audioData, partWithAudio->audioLength)) { + return false; + } } zip->endIteration(cookie); @@ -904,7 +906,10 @@ BootAnimation::Animation* BootAnimation::loadAnimation(const String8& fn) mLoadedFiles.add(animation->fileName); parseAnimationDesc(*animation); - preloadZip(*animation); + if (!preloadZip(*animation)) { + return NULL; + } + mLoadedFiles.remove(fn); return animation; diff --git a/cmds/bootanimation/audioplay.cpp b/cmds/bootanimation/audioplay.cpp index e20ef0c7c6cc..8a5c2c6d229c 100644 --- a/cmds/bootanimation/audioplay.cpp +++ b/cmds/bootanimation/audioplay.cpp @@ -21,7 +21,6 @@ #define CHATTY ALOGD -#include <assert.h> #include <string.h> #include <utils/Log.h> @@ -80,8 +79,6 @@ struct ChunkFormat { void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) { (void)bq; (void)context; - assert(bq == bqPlayerBufferQueue); - assert(NULL == context); audioplay::setPlaying(false); } @@ -90,39 +87,56 @@ bool hasPlayer() { } // create the engine and output mix objects -void createEngine() { +bool createEngine() { SLresult result; // create engine result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); - assert(SL_RESULT_SUCCESS == result); + if (result != SL_RESULT_SUCCESS) { + ALOGE("slCreateEngine failed with result %d", result); + return false; + } (void)result; // realize the engine result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); - assert(SL_RESULT_SUCCESS == result); + if (result != SL_RESULT_SUCCESS) { + ALOGE("sl engine Realize failed with result %d", result); + return false; + } (void)result; // get the engine interface, which is needed in order to create other objects result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); - assert(SL_RESULT_SUCCESS == result); + if (result != SL_RESULT_SUCCESS) { + ALOGE("sl engine GetInterface failed with result %d", result); + return false; + } (void)result; // create output mix, with environmental reverb specified as a non-required interface const SLInterfaceID ids[1] = {SL_IID_ENVIRONMENTALREVERB}; const SLboolean req[1] = {SL_BOOLEAN_FALSE}; result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 1, ids, req); - assert(SL_RESULT_SUCCESS == result); + if (result != SL_RESULT_SUCCESS) { + ALOGE("sl engine CreateOutputMix failed with result %d", result); + return false; + } (void)result; // realize the output mix result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE); - assert(SL_RESULT_SUCCESS == result); + if (result != SL_RESULT_SUCCESS) { + ALOGE("sl outputMix Realize failed with result %d", result); + return false; + } (void)result; + + return true; } // create buffer queue audio player -void createBufferQueueAudioPlayer(const ChunkFormat* chunkFormat) { +bool createBufferQueueAudioPlayer(const ChunkFormat* chunkFormat) { SLresult result; // configure audio source @@ -148,83 +162,89 @@ void createBufferQueueAudioPlayer(const ChunkFormat* chunkFormat) { const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req); - assert(SL_RESULT_SUCCESS == result); + if (result != SL_RESULT_SUCCESS) { + ALOGE("sl CreateAudioPlayer failed with result %d", result); + return false; + } (void)result; // realize the player result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE); - assert(SL_RESULT_SUCCESS == result); + if (result != SL_RESULT_SUCCESS) { + ALOGE("sl player Realize failed with result %d", result); + return false; + } (void)result; // get the play interface result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay); - assert(SL_RESULT_SUCCESS == result); + if (result != SL_RESULT_SUCCESS) { + ALOGE("sl player GetInterface failed with result %d", result); + return false; + } (void)result; // get the buffer queue interface result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE, &bqPlayerBufferQueue); - assert(SL_RESULT_SUCCESS == result); + if (result != SL_RESULT_SUCCESS) { + ALOGE("sl playberBufferQueue GetInterface failed with result %d", result); + return false; + } (void)result; // register callback on the buffer queue result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, NULL); - assert(SL_RESULT_SUCCESS == result); - (void)result; - -#if 0 // mute/solo is not supported for sources that are known to be mono, as this is - // get the mute/solo interface - result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_MUTESOLO, &bqPlayerMuteSolo); - assert(SL_RESULT_SUCCESS == result); + if (result != SL_RESULT_SUCCESS) { + ALOGE("sl bqPlayerBufferQueue RegisterCallback failed with result %d", result); + return false; + } (void)result; -#endif // get the volume interface result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume); - assert(SL_RESULT_SUCCESS == result); + if (result != SL_RESULT_SUCCESS) { + ALOGE("sl volume GetInterface failed with result %d", result); + return false; + } (void)result; // set the player's state to playing audioplay::setPlaying(true); CHATTY("Created buffer queue player: %p", bqPlayerBufferQueue); + return true; } -} // namespace - -void create() { - createEngine(); -} - -bool playClip(const uint8_t* buf, int size) { - // Parse the WAV header - nextBuffer = buf; - nextSize = size; - const RiffWaveHeader* wavHeader = (const RiffWaveHeader*)buf; - if (nextSize < sizeof(*wavHeader) || (wavHeader->riff_id != ID_RIFF) || +bool parseClipBuf(const uint8_t* clipBuf, int clipBufSize, const ChunkFormat** oChunkFormat, + const uint8_t** oSoundBuf, unsigned* oSoundBufSize) { + *oSoundBuf = clipBuf; + *oSoundBufSize = clipBufSize; + *oChunkFormat = NULL; + const RiffWaveHeader* wavHeader = (const RiffWaveHeader*)*oSoundBuf; + if (*oSoundBufSize < sizeof(*wavHeader) || (wavHeader->riff_id != ID_RIFF) || (wavHeader->wave_id != ID_WAVE)) { ALOGE("Error: audio file is not a riff/wave file\n"); return false; } - nextBuffer += sizeof(*wavHeader); - nextSize -= sizeof(*wavHeader); + *oSoundBuf += sizeof(*wavHeader); + *oSoundBufSize -= sizeof(*wavHeader); - const ChunkFormat* chunkFormat = nullptr; while (true) { - const ChunkHeader* chunkHeader = (const ChunkHeader*)nextBuffer; - if (nextSize < sizeof(*chunkHeader)) { + const ChunkHeader* chunkHeader = (const ChunkHeader*)*oSoundBuf; + if (*oSoundBufSize < sizeof(*chunkHeader)) { ALOGE("EOF reading chunk headers"); return false; } - nextBuffer += sizeof(*chunkHeader); - nextSize -= sizeof(*chunkHeader); + *oSoundBuf += sizeof(*chunkHeader); + *oSoundBufSize -= sizeof(*chunkHeader); bool endLoop = false; switch (chunkHeader->id) { case ID_FMT: - chunkFormat = (const ChunkFormat*)nextBuffer; - nextBuffer += chunkHeader->sz; - nextSize -= chunkHeader->sz; + *oChunkFormat = (const ChunkFormat*)*oSoundBuf; + *oSoundBuf += chunkHeader->sz; + *oSoundBufSize -= chunkHeader->sz; break; case ID_DATA: /* Stop looking for chunks */ @@ -232,27 +252,49 @@ bool playClip(const uint8_t* buf, int size) { break; default: /* Unknown chunk, skip bytes */ - nextBuffer += chunkHeader->sz; - nextSize -= chunkHeader->sz; + *oSoundBuf += chunkHeader->sz; + *oSoundBufSize -= chunkHeader->sz; } if (endLoop) { break; } } - if (!chunkFormat) { + if (*oChunkFormat == NULL) { ALOGE("format not found in WAV file"); return false; } + return true; +} - // If this is the first clip, create the buffer based on this WAV's header. - // We assume all future clips with be in the same format. - if (bqPlayerBufferQueue == nullptr) { - createBufferQueueAudioPlayer(chunkFormat); +} // namespace + +bool create(const uint8_t* exampleClipBuf, int exampleClipBufSize) { + if (!createEngine()) { + return false; } - assert(bqPlayerBufferQueue != nullptr); - assert(buf != nullptr); + // Parse the example clip. + const ChunkFormat* chunkFormat; + const uint8_t* soundBuf; + unsigned soundBufSize; + if (!parseClipBuf(exampleClipBuf, exampleClipBufSize, &chunkFormat, &soundBuf, &soundBufSize)) { + return false; + } + + // Initialize the BufferQueue based on this clip's format. + if (!createBufferQueueAudioPlayer(chunkFormat)) { + return false; + } + return true; +} + +bool playClip(const uint8_t* buf, int size) { + // Parse the WAV header + const ChunkFormat* chunkFormat; + if (!parseClipBuf(buf, size, &chunkFormat, &nextBuffer, &nextSize)) { + return false; + } if (!hasPlayer()) { ALOGD("cannot play clip %p without a player", buf); @@ -285,8 +327,6 @@ void setPlaying(bool isPlaying) { // set the player's state result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, isPlaying ? SL_PLAYSTATE_PLAYING : SL_PLAYSTATE_STOPPED); - assert(SL_RESULT_SUCCESS == result); - (void)result; } } diff --git a/cmds/bootanimation/audioplay.h b/cmds/bootanimation/audioplay.h index bdc0a1c84b6e..0e5705af0ad0 100644 --- a/cmds/bootanimation/audioplay.h +++ b/cmds/bootanimation/audioplay.h @@ -22,10 +22,12 @@ namespace audioplay { -void create(); +// Initializes the engine with an example of the type of WAV clip to play. +// All buffers passed to playClip are assumed to be in the same format. +bool create(const uint8_t* exampleClipBuf, int exampleClipBufSize); -// Play a WAV pointed to by buf. All clips are assumed to be in the same format. -// playClip should not be called while a clip is still playing. +// Plays a WAV contained in buf. +// Should not be called while a clip is still playing. bool playClip(const uint8_t* buf, int size); void setPlaying(bool isPlaying); void destroy(); diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index fa943f203a6e..2e37db2fef24 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -3519,6 +3519,8 @@ public class Notification implements Parcelable boolean validRemoteInput = false; int N = mActions.size(); + boolean emphazisedMode = mN.fullScreenIntent != null; + big.setBoolean(R.id.actions, "setEmphasizedMode", emphazisedMode); if (N > 0) { big.setViewVisibility(R.id.actions_container, View.VISIBLE); big.setViewVisibility(R.id.actions, View.VISIBLE); @@ -3529,7 +3531,8 @@ public class Notification implements Parcelable Action action = mActions.get(i); validRemoteInput |= hasValidRemoteInput(action); - final RemoteViews button = generateActionButton(action); + final RemoteViews button = generateActionButton(action, emphazisedMode, + i % 2 != 0); big.addView(R.id.actions, button); } } else { @@ -3694,11 +3697,13 @@ public class Notification implements Parcelable - private RemoteViews generateActionButton(Action action) { + private RemoteViews generateActionButton(Action action, boolean emphazisedMode, + boolean oddAction) { final boolean tombstone = (action.actionIntent == null); RemoteViews button = new BuilderRemoteViews(mContext.getApplicationInfo(), - tombstone ? getActionTombstoneLayoutResource() - : getActionLayoutResource()); + emphazisedMode ? getEmphasizedActionLayoutResource() + : tombstone ? getActionTombstoneLayoutResource() + : getActionLayoutResource()); final Icon ai = action.getIcon(); button.setTextViewText(R.id.action0, processLegacyText(action.title)); if (!tombstone) { @@ -3708,8 +3713,18 @@ public class Notification implements Parcelable if (action.mRemoteInputs != null) { button.setRemoteInputs(R.id.action0, action.mRemoteInputs); } - if (mN.color != COLOR_DEFAULT) { - button.setTextColor(R.id.action0, resolveContrastColor()); + if (emphazisedMode) { + // change the background color + int color = resolveContrastColor(); + if (oddAction) { + color = NotificationColorUtil.lightenColor(color, 10); + } + button.setDrawableParameters(R.id.button_holder, true, -1, color, + PorterDuff.Mode.SRC_ATOP, -1); + } else { + if (mN.color != COLOR_DEFAULT) { + button.setTextColor(R.id.action0, resolveContrastColor()); + } } return button; } @@ -3979,6 +3994,10 @@ public class Notification implements Parcelable return R.layout.notification_material_action; } + private int getEmphasizedActionLayoutResource() { + return R.layout.notification_material_action_emphasized; + } + private int getActionTombstoneLayoutResource() { return R.layout.notification_material_action_tombstone; } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index dc33671a4260..2a12ac8f0567 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -1315,7 +1315,7 @@ public class DevicePolicyManager { /** * Retrieve the current minimum password quality for a particular admin or all admins that set - * retrictions on this user and its participating profiles. Restrictions on profiles that have + * restrictions on this user and its participating profiles. Restrictions on profiles that have * a separate challenge are not taken into account. * * <p>This method can be called on the {@link DevicePolicyManager} instance @@ -1379,7 +1379,7 @@ public class DevicePolicyManager { /** * Retrieve the current minimum password length for a particular admin or all admins that set - * retrictions on this user and its participating profiles. Restrictions on profiles that have + * restrictions on this user and its participating profiles. Restrictions on profiles that have * a separate challenge are not taken into account. * * <p>This method can be called on the {@link DevicePolicyManager} instance @@ -1442,7 +1442,7 @@ public class DevicePolicyManager { /** * Retrieve the current number of upper case letters required in the password - * for a particular admin or all admins that set retrictions on this user and + * for a particular admin or all admins that set restrictions on this user and * its participating profiles. Restrictions on profiles that have a separate challenge * are not taken into account. * This is the same value as set by @@ -1511,7 +1511,7 @@ public class DevicePolicyManager { /** * Retrieve the current number of lower case letters required in the password - * for a particular admin or all admins that set retrictions on this user + * for a particular admin or all admins that set restrictions on this user * and its participating profiles. Restrictions on profiles that have * a separate challenge are not taken into account. * This is the same value as set by @@ -1580,7 +1580,7 @@ public class DevicePolicyManager { /** * Retrieve the current number of letters required in the password - * for a particular admin or all admins that set retrictions on this user + * for a particular admin or all admins that set restrictions on this user * and its participating profiles. Restrictions on profiles that have * a separate challenge are not taken into account. * This is the same value as set by @@ -1648,7 +1648,7 @@ public class DevicePolicyManager { /** * Retrieve the current number of numerical digits required in the password - * for a particular admin or all admins that set retrictions on this user + * for a particular admin or all admins that set restrictions on this user * and its participating profiles. Restrictions on profiles that have * a separate challenge are not taken into account. * This is the same value as set by @@ -1716,7 +1716,7 @@ public class DevicePolicyManager { /** * Retrieve the current number of symbols required in the password - * for a particular admin or all admins that set retrictions on this user + * for a particular admin or all admins that set restrictions on this user * and its participating profiles. Restrictions on profiles that have * a separate challenge are not taken into account. This is the same value as * set by {@link #setPasswordMinimumSymbols(ComponentName, int)} @@ -1783,7 +1783,7 @@ public class DevicePolicyManager { /** * Retrieve the current number of non-letter characters required in the password - * for a particular admin or all admins that set retrictions on this user + * for a particular admin or all admins that set restrictions on this user * and its participating profiles. Restrictions on profiles that have * a separate challenge are not taken into account. * This is the same value as set by @@ -1915,7 +1915,7 @@ public class DevicePolicyManager { /** * Get the current password expiration time for a particular admin or all admins that set - * retrictions on this user and its participating profiles. Restrictions on profiles that have + * restrictions on this user and its participating profiles. Restrictions on profiles that have * a separate challenge are not taken into account. If admin is {@code null}, then a composite * of all expiration times is returned - which will be the minimum of all of them. * @@ -1939,7 +1939,7 @@ public class DevicePolicyManager { /** * Retrieve the current password history length for a particular admin or all admins that - * set retrictions on this user and its participating profiles. Restrictions on profiles that + * set restrictions on this user and its participating profiles. Restrictions on profiles that * have a separate challenge are not taken into account. * * <p>This method can be called on the {@link DevicePolicyManager} instance @@ -2121,7 +2121,7 @@ public class DevicePolicyManager { /** * Retrieve the current maximum number of login attempts that are allowed before the device - * or profile is wiped, for a particular admin or all admins that set retrictions on this user + * or profile is wiped, for a particular admin or all admins that set restrictions on this user * and its participating profiles. Restrictions on profiles that have a separate challenge are * not taken into account. * @@ -2262,7 +2262,7 @@ public class DevicePolicyManager { /** * Retrieve the current maximum time to unlock for a particular admin or all admins that set - * retrictions on this user and its participating profiles. Restrictions on profiles that have + * restrictions on this user and its participating profiles. Restrictions on profiles that have * a separate challenge are not taken into account. * * <p>This method can be called on the {@link DevicePolicyManager} instance @@ -3348,7 +3348,7 @@ public class DevicePolicyManager { /** * Determine whether or not features have been disabled in keyguard either by the calling - * admin, if specified, or all admins that set retrictions on this user and its participating + * admin, if specified, or all admins that set restrictions on this user and its participating * profiles. Restrictions on profiles that have a separate challenge are not taken into account. * * <p>This method can be called on the {@link DevicePolicyManager} instance diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java index 5823abf9d78f..734bf6917eca 100644 --- a/core/java/android/app/job/JobInfo.java +++ b/core/java/android/app/job/JobInfo.java @@ -165,6 +165,9 @@ public class JobInfo implements Parcelable { * network restrictions for the requesting app. Note that this flag alone * doesn't actually place your {@link JobService} in the foreground; you * still need to post the notification yourself. + * <p> + * To use this flag, the caller must hold the + * {@link android.Manifest.permission#CONNECTIVITY_INTERNAL} permission. * * @hide */ diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java index 92134ee01de8..1e44a5ccafc9 100644 --- a/core/java/android/content/res/TypedArray.java +++ b/core/java/android/content/res/TypedArray.java @@ -49,6 +49,10 @@ public class TypedArray { attrs.mLength = len; attrs.mRecycled = false; + // Reset the assets, which may have changed due to configuration changes + // or further resource loading. + attrs.mAssets = res.getAssets(); + final int fullLen = len * AssetManager.STYLE_NUM_ENTRIES; if (attrs.mData.length >= fullLen) { return attrs; @@ -66,7 +70,7 @@ public class TypedArray { private final Resources mResources; private final DisplayMetrics mMetrics; - private final AssetManager mAssets; + private AssetManager mAssets; private boolean mRecycled; @@ -1086,6 +1090,7 @@ public class TypedArray { // These may have been set by the client. mXml = null; mTheme = null; + mAssets = null; mResources.mTypedArrayPool.release(this); } diff --git a/core/java/android/net/network-policy-restrictions.md b/core/java/android/net/network-policy-restrictions.md index fe13f7a5aab9..63ce1a244643 100644 --- a/core/java/android/net/network-policy-restrictions.md +++ b/core/java/android/net/network-policy-restrictions.md @@ -29,8 +29,8 @@ More specifically: | **DS** | *WL* | ok | blk | ok | ok | | **ON** | *!WL* | blk | blk | blk | blk | | | *BL* | blk | blk | blk | blk | -| **DS** | *WL* | blk | ok | ok | ok | -| **OFF** | *!WL* | blk | ok | ok | ok | +| **DS** | *WL* | blk | blk | ok | ok | +| **OFF** | *!WL* | blk | blk | ok | ok | | | *BL* | blk | blk | blk | blk | diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index 80927f368e0c..8d6d9ed567b6 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -286,6 +286,11 @@ public class Environment { } /** {@hide} */ + public static File getReferenceProfile(String packageName) { + return buildPath(getDataDirectory(), "misc", "profiles", "ref", packageName); + } + + /** {@hide} */ public static File getDataProfilesDePackageDirectory(int userId, String packageName) { return buildPath(getDataProfilesDeDirectory(userId), packageName); } diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java index 1158776f5fd1..d587ba80a18c 100644 --- a/core/java/android/provider/DocumentsContract.java +++ b/core/java/android/provider/DocumentsContract.java @@ -235,7 +235,6 @@ public final class DocumentsContract { * @see #FLAG_DIR_PREFERS_GRID * @see #FLAG_DIR_PREFERS_LAST_MODIFIED * @see #FLAG_VIRTUAL_DOCUMENT - * @see #FLAG_ARCHIVE * @see #FLAG_SUPPORTS_COPY * @see #FLAG_SUPPORTS_MOVE * @see #FLAG_SUPPORTS_REMOVE @@ -326,7 +325,7 @@ public final class DocumentsContract { * Flag indicating that a document can be renamed. * * @see #COLUMN_FLAGS - * @see DocumentsContract#renameDocument(ContentProviderClient, Uri, + * @see DocumentsContract#renameDocument(ContentResolver, Uri, * String) * @see DocumentsProvider#renameDocument(String, String) */ @@ -337,7 +336,7 @@ public final class DocumentsContract { * within the same document provider. * * @see #COLUMN_FLAGS - * @see DocumentsContract#copyDocument(ContentProviderClient, Uri, Uri) + * @see DocumentsContract#copyDocument(ContentResolver, Uri, Uri) * @see DocumentsProvider#copyDocument(String, String) */ public static final int FLAG_SUPPORTS_COPY = 1 << 7; @@ -347,7 +346,7 @@ public final class DocumentsContract { * within the same document provider. * * @see #COLUMN_FLAGS - * @see DocumentsContract#moveDocument(ContentProviderClient, Uri, Uri, Uri) + * @see DocumentsContract#moveDocument(ContentResolver, Uri, Uri, Uri) * @see DocumentsProvider#moveDocument(String, String, String) */ public static final int FLAG_SUPPORTS_MOVE = 1 << 8; @@ -368,7 +367,7 @@ public final class DocumentsContract { * Flag indicating that a document can be removed from a parent. * * @see #COLUMN_FLAGS - * @see DocumentsContract#removeDocument(ContentProviderClient, Uri, Uri) + * @see DocumentsContract#removeDocument(ContentResolver, Uri, Uri) * @see DocumentsProvider#removeDocument(String, String) */ public static final int FLAG_SUPPORTS_REMOVE = 1 << 10; @@ -870,7 +869,7 @@ public final class DocumentsContract { * Test if the given URI represents a {@link Document} tree. * * @see #buildTreeDocumentUri(String, String) - * @see #getTreeDocumentId(Uri, String) + * @see #getTreeDocumentId(Uri) */ public static boolean isTreeUri(Uri uri) { final List<String> paths = uri.getPathSegments(); diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 5c2778d483ac..765a3a8cd9d4 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -5295,15 +5295,6 @@ public final class Settings { "accessibility_display_daltonizer"; /** - * Float list that specifies the color matrix to apply to - * the display. Valid values are defined in AccessibilityManager. - * - * @hide - */ - public static final String ACCESSIBILITY_DISPLAY_COLOR_MATRIX = - "accessibility_display_color_matrix"; - - /** * Setting that specifies whether automatic click when the mouse pointer stops moving is * enabled. * @@ -6334,7 +6325,6 @@ public final class Settings { USB_MASS_STORAGE_ENABLED, // moved to global ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, ACCESSIBILITY_DISPLAY_DALTONIZER, - ACCESSIBILITY_DISPLAY_COLOR_MATRIX, ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index a64827af32c2..e6481147c295 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -4215,25 +4215,25 @@ public class View implements Drawable.Callback, KeyEvent.Callback, setAlpha(a.getFloat(attr, 1f)); break; case com.android.internal.R.styleable.View_transformPivotX: - setPivotX(a.getDimensionPixelOffset(attr, 0)); + setPivotX(a.getDimension(attr, 0)); break; case com.android.internal.R.styleable.View_transformPivotY: - setPivotY(a.getDimensionPixelOffset(attr, 0)); + setPivotY(a.getDimension(attr, 0)); break; case com.android.internal.R.styleable.View_translationX: - tx = a.getDimensionPixelOffset(attr, 0); + tx = a.getDimension(attr, 0); transformSet = true; break; case com.android.internal.R.styleable.View_translationY: - ty = a.getDimensionPixelOffset(attr, 0); + ty = a.getDimension(attr, 0); transformSet = true; break; case com.android.internal.R.styleable.View_translationZ: - tz = a.getDimensionPixelOffset(attr, 0); + tz = a.getDimension(attr, 0); transformSet = true; break; case com.android.internal.R.styleable.View_elevation: - elevation = a.getDimensionPixelOffset(attr, 0); + elevation = a.getDimension(attr, 0); transformSet = true; break; case com.android.internal.R.styleable.View_rotation: diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 92801a4d4575..209886b27c18 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -3173,7 +3173,7 @@ public final class ViewRootImpl implements ViewParent, } focusNode.recycle(); } - if (mAccessibilityFocusedHost != null) { + if ((mAccessibilityFocusedHost != null) && (mAccessibilityFocusedHost != view)) { // Clear accessibility focus in the view. mAccessibilityFocusedHost.clearAccessibilityFocusNoCallbacks( AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS); diff --git a/core/java/com/android/internal/util/NotificationColorUtil.java b/core/java/com/android/internal/util/NotificationColorUtil.java index 48bcc0930164..77452ca3a4dc 100644 --- a/core/java/com/android/internal/util/NotificationColorUtil.java +++ b/core/java/com/android/internal/util/NotificationColorUtil.java @@ -341,6 +341,20 @@ public class NotificationColorUtil { } /** + * Lighten a color by a specified value + * @param baseColor the base color to lighten + * @param amount the amount to lighten the color from 0 to 100. This corresponds to the L + * increase in the LAB color space. + * @return the lightened color + */ + public static int lightenColor(int baseColor, int amount) { + final double[] result = ColorUtilsFromCompat.getTempDouble3Array(); + ColorUtilsFromCompat.colorToLAB(baseColor, result); + result[0] = Math.min(100, result[0] + amount); + return ColorUtilsFromCompat.LABToColor(result[0], result[1], result[2]); + } + + /** * Framework copy of functions needed from android.support.v4.graphics.ColorUtils. */ private static class ColorUtilsFromCompat { @@ -434,7 +448,7 @@ public class NotificationColorUtil { * Convert RGB components to its CIE Lab representative components. * * <ul> - * <li>outLab[0] is L [0 ...1)</li> + * <li>outLab[0] is L [0 ...100)</li> * <li>outLab[1] is a [-128...127)</li> * <li>outLab[2] is b [-128...127)</li> * </ul> @@ -516,7 +530,7 @@ public class NotificationColorUtil { * 2° Standard Observer (1931).</p> * * <ul> - * <li>outLab[0] is L [0 ...1)</li> + * <li>outLab[0] is L [0 ...100)</li> * <li>outLab[1] is a [-128...127)</li> * <li>outLab[2] is b [-128...127)</li> * </ul> @@ -634,7 +648,7 @@ public class NotificationColorUtil { : (XYZ_KAPPA * component + 16) / 116; } - private static double[] getTempDouble3Array() { + public static double[] getTempDouble3Array() { double[] result = TEMP_ARRAY.get(); if (result == null) { result = new double[3]; diff --git a/core/java/com/android/internal/widget/NotificationActionListLayout.java b/core/java/com/android/internal/widget/NotificationActionListLayout.java index 9dd118c5a942..073aac542e31 100644 --- a/core/java/com/android/internal/widget/NotificationActionListLayout.java +++ b/core/java/com/android/internal/widget/NotificationActionListLayout.java @@ -17,11 +17,13 @@ package com.android.internal.widget; import android.content.Context; +import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.util.Pair; import android.view.Gravity; +import android.view.RemotableViewMethod; import android.view.View; -import android.view.ViewGroup; +import android.widget.LinearLayout; import android.widget.RemoteViews; import android.widget.TextView; @@ -33,11 +35,14 @@ import java.util.Comparator; * the remaining available width, and the last action consumes the remaining space. */ @RemoteViews.RemoteView -public class NotificationActionListLayout extends ViewGroup { +public class NotificationActionListLayout extends LinearLayout { private int mTotalWidth = 0; private ArrayList<Pair<Integer, TextView>> mMeasureOrderTextViews = new ArrayList<>(); private ArrayList<View> mMeasureOrderOther = new ArrayList<>(); + private boolean mMeasureLinearly; + private int mDefaultPaddingEnd; + private Drawable mDefaultBackground; public NotificationActionListLayout(Context context, AttributeSet attrs) { super(context, attrs); @@ -45,6 +50,10 @@ public class NotificationActionListLayout extends ViewGroup { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (mMeasureLinearly) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + return; + } final int N = getChildCount(); int textViews = 0; int otherViews = 0; @@ -186,6 +195,10 @@ public class NotificationActionListLayout extends ViewGroup { @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + if (mMeasureLinearly) { + super.onLayout(changed, left, top, right, bottom); + return; + } final boolean isLayoutRtl = isLayoutRtl(); final int paddingTop = mPaddingTop; @@ -241,26 +254,24 @@ public class NotificationActionListLayout extends ViewGroup { } @Override - public LayoutParams generateLayoutParams(AttributeSet attrs) { - return new MarginLayoutParams(getContext(), attrs); - } - - @Override - protected LayoutParams generateDefaultLayoutParams() { - return new MarginLayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); + protected void onFinishInflate() { + super.onFinishInflate(); + mDefaultPaddingEnd = getPaddingEnd(); + mDefaultBackground = getBackground(); } - @Override - protected LayoutParams generateLayoutParams(LayoutParams p) { - if (p instanceof MarginLayoutParams) { - return new MarginLayoutParams((MarginLayoutParams)p); - } - return new MarginLayoutParams(p); - } - - @Override - protected boolean checkLayoutParams(LayoutParams p) { - return p instanceof MarginLayoutParams; + /** + * Set whether the list is in a mode where some actions are emphasized. This will trigger an + * equal measuring where all actions are full height and change a few parameters like + * the padding. + */ + @RemotableViewMethod + public void setEmphasizedMode(boolean emphasizedMode) { + mMeasureLinearly = emphasizedMode; + setPaddingRelative(getPaddingStart(), getPaddingTop(), + emphasizedMode ? 0 : mDefaultPaddingEnd, getPaddingBottom()); + setBackground(emphasizedMode ? null : mDefaultBackground); + requestLayout(); } public static final Comparator<Pair<Integer, TextView>> MEASURE_ORDER_COMPARATOR diff --git a/core/res/res/drawable/notification_material_action_background_emphasized.xml b/core/res/res/drawable/notification_material_action_background_emphasized.xml new file mode 100644 index 000000000000..b7153ba620e3 --- /dev/null +++ b/core/res/res/drawable/notification_material_action_background_emphasized.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> + +<ripple xmlns:android="http://schemas.android.com/apk/res/android" + android:color="@color/ripple_material_dark"> + <item android:id="@id/mask"> + <color android:color="@color/white" /> + </item> +</ripple> + diff --git a/core/res/res/layout/notification_material_action_emphasized.xml b/core/res/res/layout/notification_material_action_emphasized.xml new file mode 100644 index 000000000000..992e43ede404 --- /dev/null +++ b/core/res/res/layout/notification_material_action_emphasized.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/button_holder" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_weight="1" + android:background="#ff000000"> + <Button + style="@android:style/Widget.Material.Light.Button.Borderless.Small" + android:id="@+id/action0" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="center" + android:textColor="#ffffffff" + android:singleLine="true" + android:ellipsize="end" + android:background="@drawable/notification_material_action_background_emphasized" + /> +</FrameLayout> diff --git a/core/res/res/values-watch/colors_material.xml b/core/res/res/values-watch/colors_material.xml index 91eee7d0039f..45eb9812f137 100644 --- a/core/res/res/values-watch/colors_material.xml +++ b/core/res/res/values-watch/colors_material.xml @@ -20,5 +20,7 @@ <color name="accent_material_dark">#ff5e97f6</color> <color name="accent_material_light">#ff4285f4</color> + <color name="primary_material_dark">#4D4D4D</color> + <color name="button_material_dark">#ff999999</color> </resources> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index c7b605d2504a..674a0d7f61eb 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -764,7 +764,7 @@ 1 - AUTO_MODE_CUSTOM 2 - AUTO_MODE_TWILIGHT --> - <integer name="config_defaultNightDisplayAutoMode">1</integer> + <integer name="config_defaultNightDisplayAutoMode">0</integer> <!-- Default time when Night display is automatically activated. Represented as milliseconds from midnight (e.g. 79200000 == 10pm). --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 91cfd91d0357..3590ac86afd0 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2628,6 +2628,8 @@ <!-- Used internally for assistant to launch activity transitions --> <java-symbol type="id" name="cross_task_transition" /> + <java-symbol type="id" name="button_holder" /> + <java-symbol type="bool" name="config_useRoundIcon" /> <!-- For System navigation keys --> @@ -2636,6 +2638,8 @@ <java-symbol type="layout" name="unsupported_display_size_dialog_content" /> <java-symbol type="string" name="unsupported_display_size_message" /> + <java-symbol type="layout" name="notification_material_action_emphasized" /> + <!-- Package name for the device provisioning package --> <java-symbol type="string" name="config_deviceProvisioningPackage" /> diff --git a/docs/html/_redirects.yaml b/docs/html/_redirects.yaml index 48aca2860edd..4a9cab6d239f 100644 --- a/docs/html/_redirects.yaml +++ b/docs/html/_redirects.yaml @@ -361,6 +361,8 @@ redirects: to: /about/dashboards/index.html - from: /resources/community-groups.html to: /support.html +- from: /community/index.html + to: /support.html - from: /guide/tutorials/ to: /resources/tutorials/ - from: /resources/tutorials/views/hello-linearlayout.html diff --git a/docs/html/community/index.html b/docs/html/community/index.html deleted file mode 100644 index e3834ba15cd0..000000000000 --- a/docs/html/community/index.html +++ /dev/null @@ -1,320 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> -<meta name="viewport" content="width=device-width" /> - -<meta name="google-site-verification" content="sa-bIAI6GKvct3f61-WpRguHq-aNjtF7xJjMTSi79as" /> -<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" /> -<title>Android Developers Community</title> - -<!-- STYLESHEETS --> -<link rel="stylesheet" -href="//fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic,bold" title="roboto"> -<link href="/assets/css/default.css" rel="stylesheet" type="text/css"> - -<!-- JAVASCRIPT --> -<script src="//www.google.com/jsapi" type="text/javascript"></script> -<script src="/assets/js/android_3p-bundle.js" type="text/javascript"></script> -<script type="text/javascript"> - var toRoot = "/"; - var devsite = false; -</script> - -<script type="text/javascript"> - var _gaq = _gaq || []; - _gaq.push(['_setAccount', 'UA-5831155-1']); - _gaq.push(['_trackPageview']); - - (function() { - var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; - ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; - var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); - })(); -</script> - -<style> -#header { - padding: 2.2em 0 0.2em 0; -} -#header-wrap h1 { - margin:0; - padding:0; - line-height:16px; -} -#body-content { - margin-top:20px; -} -#nav-x.wrap { - overflow:auto; -} -h2 { - border-bottom:1px solid #CCC; -} -</style> -</head> - - - - - - -<body> - - -<!-- Header --> -<div id="header"> - <div class="wrap" id="header-wrap"> - <div class="col-3 logo"> - <a href="/index.html"> - <img src="http://developer.android.com/assets/images/dac_logo.png" width="123" height="25" alt="Android Developers" /> - </a> - </div> - <div class="col-8"> - <h1>Community Outreach</h1> - </div> - - <div class="menu-container"> - <div class="moremenu"> - <div id="more-btn"></div> - </div> - <div class="morehover" id="moremenu"> - <div class="top"></div> - <div class="mid"> - <div class="header">Links</div> - <ul style="margin-bottom:0"> - <li><a href="https://www.youtube.com/user/androiddevelopers">Android Developers Live</a></li> - <li><a href="http://android-developers.blogspot.com/">Android Developers Blog</a></li> - <li><a href="http://developer.android.com/training/">Android Developer Training</a></li> - <li><a href="http://developer.android.com/samples/">Samples</a></li> - </ul> - <br class="clear-fix"> - </div> - <div class="bottom"></div> - </div><!-- end morehover --> - </div><!-- end menu-container --> - </div><!-- end header-wrap --> -</div> -<!-- /Header --> - -<div id="nav-x" class="wrap"> - <ul class="nav-x col-9 develop"> - <li><a href="#News">News</a></li> - <li><a href="#Community">Community</a></li> - <li><a href="#Content">Content</a></li> - <li><a href="#Social">Social</a></li> - </ul> -</div> - - -<!-- MAIN CONTENT --> - - -<div class="wrap" id="body-content"> - -<img src="/images/community/aco1small.png" alt="" style="float:right;margin:20px 0 0 40px"> - -<p style="clear:left"> - Android is working with communities to -<ul> -<li>Create a cooperative relationship between highly impactful communities and high performing developers</li> -<li>Strengthen relationships between Android and coding communities so that developers have a motivation to interact with those communities</li> -<li>Reward communities for attracting developers by providing them with resources and direct access to the Android team</li></ul> -<p>Our IMPACT is measured by <strong>good apps</strong> and a <strong>thriving community</strong></p> - -<h2 id="News" style="clear:left">News</h2> -<p>Our current theme is on the <b><em>Android 4.4 KitKat and Updated Developer Tools</em></b> release, with new ways to create beautiful apps, printing and storage frameworks, low-power sensors, new media capabilities and RenderScript in the NDK.</p> - -<div class="col-8" style="margin-left:0"> -<img src="/images/community/kk-hero2.jpg" alt="" height="277"> -</div> - -<div class="col-8" style="margin-right:0"> -<h3 style="margin-top:0"><a href="http://developer.android.com/about/versions/kitkat.html">Android 4.4 Platform Highlights</a></h3> -<p>Android KitKat brings all of Android's most innovative, most beautiful, and most useful features to more devices everywhere.</p> - -<h3><a href="http://developer.android.com/about/versions/android-4.4.html">Android 4.4 APIs</a></h3> -<p>Android 4.4 (KITKAT) is a new release for the Android platform that offers new features for users and app developers. This document provides an introduction to the most notable new APIs.</p> - -<h3><a href="https://play.google.com/store/devices/details?id=nexus_5_white_32gb">New Nexus 5</a></h3> -<p>Nexus 5 helps you capture the everyday and the epic in fresh new ways. It's the slimmest and fastest Nexus phone ever made, powered by Android 4.4, KitKat.</p> -</div> -<p></p> - -<h2 id="Community" style="clear:left">Community Spotlight</h2> - -<div class="col-8" style="margin-left:0"> -<h3>Android Community Groups</h3> -<h4>July 2013</h4> -<p><a href="mailto:gtugam@gmail.com">GDG Armenia</a> held <a href="http://eca.hackathon.am/">ecaHack Yerevan</a>, an Android hackathon featuring "Angry Designers vs Android Developers", where the designers had a look into developers apps and gave them some advices regarding to design. The hackathon was sponsored by Alcatel One Touch and each member of the winner team got one Alcatel One Touch Idol. Check out the <a href="https://plus.google.com/u/0/events/gallery/cgj9d39gphiephlq0e2899dv6j4?cfem=1">photos.</a></p> -<h4>September 2013</h4> -<p><a href="mailto:soham.mondal@gmail.com">GDG Blrdroid</a> held a <a href="http://www.meetup.com/blrdroid/events/140665852/">meetup</a> on performance optimisation.</p> -<p><a href="mailto:baileye@gmail.com">GDG Dublin</a> held their meetup with a talk on AdMob for Android and iOS, entitled “Admob for Android and iOS developers”. </p> -<p>GDG Mbale’s <a href="mailto:nsubugahassan@gmail.com">Hassan Nsubuga</a> has been managing a university <a href="https://plus.google.com/103735976334615631393/posts/gQMWCGUhMBn">course session</a> since September. They are now through with the basics and have a firm foundation, so this month they will be doing a lot of advanced stuff including exploring the latest API enhancements with KitKat. </p> -<p><a href="mailto:wojtek.kalicinski@gmail.com">GDG Warsaw</a> held an Android Barcamp focused on App Quality. The discussion was moderated by GDG organisers, but the talks were given by the community members, including some top Android companies and developers in Poland.</p> -<h4>October 2013</h4> -<p><a href="mailto:benjamin.r.m.weiss@gmail.com">GDG Berlin Android</a> held their <a href="https://berlin.ticketbud.com/devfest-berlin-2013">DevFest</a>.</p> -<p><a href="mailto:soham.mondal@gmail.com">GDG Blrdroid</a> held their <a href="http://www.meetup.com/blrdroid/events/144457162/">meetup</a> in collaboration with GDG Bangalore, where they talked about a wider range of things from incorporating user feedback to effectively using the cell radio. David McLaughlin from the Developer Relations team also visited during the meetup and delivered the keynote. They also hit a milestone with its 4th anniversary on the 9th of October and crossed 4300 members in the past few days so its been a memorable couple of months for them.</p> -<p><a href="mailto:hir3npatel@gmail.com">GDG Cape Town</a> held an <a href="https://plus.google.com/108309780217630451504/posts/9BTCEqnBHoQ">Android Workshop</a> where they gave away lots of branded KitKats.</p> -<p><a href="mailto:baileye@gmail.com">GDG Dublin</a> held its DevFest, which featured a codeLab on Android titled “Codelab: Intro to Android Development.”</p> -<p><a href="mailto:hugo@dutchaug.org">GDG Dutch Android User Group</a> held their <a href="http://www.devfest.nl/program">DevFest</a>. They had a bunch of Android sessions, mostly by local speakers. In addition to the Android sessions, they also ran a workshop on writing custom views.</p> -<p><a href="mailto:hugo@dutchaug.org">Hugo Visser</a> from the Dutch Android User Group spoke at <a href="https://bitbucket.org/qbusict/cupboard">DroidCon UK barcamp</a>, where he delivered a talk on Cupboard, a simple and lightweight persistence framework, specifically for Android.</p> -<p><a href="mailto:prajyotmainkar@gmail.com">GDG GAUG</a> held the <a href="https://plus.google.com/110448195989468248957/posts/8doJuCpySWS">Google Devfest 2013</a>, where they had two tracks and more than 200 delegates attending. They also had a <a href="https://plus.google.com/110448195989468248957/posts/6rxLzj2Rpde">Hackathon</a> and they hit the <a href="https://plus.google.com/110448195989468248957">1000 member</a> mark this month, which makes them the second largest android community in India after GDG Blrdroid. </p> -<p><a href="mailto:cyrilleguipie@gmail.com">GDG Miage</a> held their DevFest where they gave a talk about Intents and Services. The also held a startup Weekend Bootcamp where they talked about Activites and Layouts. They will also hold an Android Workshop in December.</p> -<p><a href="mailto:gabriel.kb@gmail.com">GDG Uruguay</a> had their <a href="http://gdg.uy/devfest2013">DevFest</a>, where they held an Android workshop for beginners as an Android vs iOS comparison, a session on best practices using YouTube APIs in Android, and What's new in Google for developers (with a special section about Android). You can see pictures on <a href="https://plus.google.com/114520966453242230657/posts/dqZAuMqc12Z">the G+ page</a>. </p> - -<h4>November 2013</h4> -<p><a href="mailto:yorogoule@gmail.com">Abidjandroid/GDG Côte d'Ivoire</a> held an Android Launch Party featuring the KitKat release.</p> -<p>The <a href="mailto:hugo@dutchaug.org">Dutch Android User Group</a> had a very interactive presentation on Android Code Puzzlers and Tips & tricks, where they rewarded participation by giving out books, tshirts, jelly beans and kitkats. The presentation was at the <a href="http://www.nljug.org/jfall">Dutch JFall conference</a>, organized by the NLJUG. It's a large yearly Java conference and the DAUG had the only Android session there.</p> -<p>The <a href="mailto:benjamin.r.m.weiss@gmail.com">GDG Berlin Android</a> meetup this month featured the KitKat release.</p> -<p><a href="mailto:soham.mondal@gmail.com">The GDG Blrdroid</a> <a href="http://www.meetup.com/blrdroid/events/148210762/%20">meetup</a> was another focused on KitKat.</p> -<p>At the <a href="mailto:amahdy7@gmail.com">GDG Cairo</a> <a href="https://plus.google.com/events/co59j0870in5a4kh8n5navifnm8">DevFest</a> there was a "What's new in Android SDK" session on day 1, and an Android workshop on day 2. Kitkat also provided interest in the sessions and the snacks bar. The KitKat <a href="http://buff.ly/HNE7yq">presentation</a>, the track organization, and everything related to it were all organized by women.</p> -<p><a href="mailto:hir3npatel@gmail.com">GDG Cape Town</a> held an Android Workshop.</p> -<p><a href="mailto:alessandro.gbridge@gmail.com">GDG Udine</a> organized a talk after the release of KitKat for a school in Pordenone.</p> -<p><a href="mailto:hugo@dutchaug.org">Hugo Visser</a> from Droidcon Netherlands organized an Android hackathon themed "Location, Location, Location". </p> -<p><a href="mailto:eyal.lezmy@gmail.com">Paris Android User Group</a> welcomed <a href="https://plus.google.com/+RomainGuy">Romain Guy</a> and <a href="https://plus.google.com/+ChetHaase">Chet Haase</a> to their meetup this month. They’ll be meeting up with other GDG leads and UG managers meet at <a href="https://plus.google.com/events/cupo201fjreo9g9t2e596gv8nd4">Devoxx</a> next Thursday.</p> -<p><a href="mailto:wojtek.kalicinski@gmail.com">GDG Warsaw</a> had over 250 attendees at their DevFest, which featured session tracks on Android and Web and a whole day of Code Labs in Android, AngularJS and Arduino.</p> -<h4>December 2013</h4> -<p><a href="mailto:prajyotmainkar@gmail.com">GDG GAUG</a> are planning a codelab and hackathon.</p> -<p><a href="mailto:psvensson@gmail.com">Peter Svensson</a> spoke at <a href="http://swdc.se/droidcon/events/stockholm-2013/">DroidCon Stockholm</a></p> -The unstoppable <a href="mailto:bonbhel@gmail.com">Max Bonbhel</a> from the African GDG Android is hosting AAC 2014 and Android GDG Barcamp events in December. Also, in order to encourage African Java developers to move to the Android platform, he created the <a href="https://docs.google.com/spreadsheet/ccc?key=0AtFPan-z2ps-dHBtX1luY2pRQjdtRjliUGcxMVBNeVE&usp=sharing#gid=0">Africa Android Training (AAT) program</a>. The training material targets developers with different levels of experience in Java development. More than 60 developers have been taking part in the weekly sessions. The next 10 sessions will start Saturday, November 9, 2013. 260 GDG and Java User Group members have already registered from 12 Countries. -<p> </p> -</div> - -<div class="col-8" style="margin-right:0"> -<h3>Android Community Experts</h3> - -<h4>October 2013</h4> -<p><a href="mailto:eyal.lezmy@gmail.com">Eyal Lezmy</a> presented two sessions. “<a href="http://bit.ly/andbigfail">Play Store bashing, learn from the biggest fails</a>” looked at several applications, mainly developed by huge companies, and analyzed why they failed to satisfy the users or the Android guidelines. “<a href="http://bit.ly/lifeofapp">Android, the life of your app</a>” tells a story, living the life of a user, identify the frustrations he can encounter and present ways to avoid it, as a developer.</p> -<p><a href="mailto:mariux01@gmail.com">Mario Viviani</a> presented and recorded the next <a href="http://www.youtube.com/watch?v=jaT0bYhhaGY">Android App Clinic - Italia</a>. This episode was regarding the Cards UI and SMS app support in Android 4.4. They experimented with a short form of the video (10 minutes instead of 20) and in less than day it got almost 400+ views -- which is great considering it's in Italian! The previous episode reached 1300 views all-time and was the most successful video of GDL Italia in Q2.</p> -<p><a href="mailto:m.kaeppler@gmail.com">Matthias Käppler</a> contributed the <a href="https://github.com/Netflix/RxJava/tree/master/rxjava-contrib/rxjava-android">first Android specific component</a> to the RxJava project, and spoke about <a href="http://uk.droidcon.com/2013/sessions/conquering-concurrency-bringing-the-reactive-extensions-to-the-android-platform/">RxJava and reactive programming on Android</a> at DroidCon UK. He has also open sourced <a href="https://github.com/mttkay/memento">Memento</a>, an Android annotation processor to replace the deprecated onRetainNonConfigurationInstance.</p> -<p><a href="mailto:wojtek.kalicinski@gmail.com">Wojtek KaliciÅ„ski</a>’s talk, "Android - is it time for a break yet?" highlights not only what's new in Android 4.4 KitKat, but also how to take your app to the next level by making sure you provide the best app experience possible to all 4.0+ users.</p> -<a href="https://plus.sandbox.google.com/110448195989468248957/posts"><img src="/images/community/hackathon-gdgaug.jpg" alt="" align="right"></a> - -</div> - -<h2 id="Content" style="clear:left">New Content</h2> -<div class="col-8" style="margin-left:0"> -<p><h4>Android 4.4 What's New</h4> -KitKat has been optimized to run on a much broader range of devices, with special focus on the millions of entry-level devices that have as little as 512MB RAM. To help, we've created new APIs, better tools, and better documentation to let you create apps that perform well on all devices.<br> -Check out this video summary of some of the most significant developer features in the latest Android release, including new ways to make your apps beautiful, NFC Host Card Emulation, a printing framework, the storage access framework, low-power step detector and step counter sensors, and more!<br> -<h5><a href="http://www.youtube.com/watch?v=sONcojECWXs&list=PLWz5rJ2EKKc-2quE-o0enpILZF3nBZg_K">Video</a></h5> -<h5><a href="https://drive.google.com/a/google.com/folderview?id=0BwhAiXVwzMoFc28wWEpyeE9qYTQ&usp=sharing">Presentation</a></h5> -<i>Be sure to get the <a href="http://developer.android.com/about/versions/android-4.4.html">full Android 4.4 API Overview</a>, and take a look at our <a href="https://www.youtube.com/playlist?list=PLWz5rJ2EKKc-2quE-o0enpILZF3nBZg_K">related DevBytes videos</a></i></p> - -<p><h4>WebView in Android 4.4</h4> -Android 4.4 (API level 19) introduces a new version of WebView that is based on Chromium. This change upgrades WebView performance and standards support for HTML5, CSS3, and JavaScript to match the latest web browsers. Any apps using WebView will inherit these upgrades when running on Android 4.4 and higher. -<h5><a href="http://developer.android.com/guide/webapps/migrating.html">API Guide</a></h5> -</p> - -<p><h4>Android 4.4 Immersive Mode</h4> -With Android 4.4 KitKat, your apps can now truly go full-screen with a new Immersive Mode. Immersive Mode lets your apps hide the system's status and navigation bars while capturing all touch events—ideal for rich interactive content such as books and games. This video demonstrates how to use the new API, in addition to recapping earlier full-screen APIs on Android. -<h5><a href="http://www.youtube.com/watch?v=cBi8fjv90E4&list=PLWz5rJ2EKKc-2quE-o0enpILZF3nBZg_K">Video</a></h5> -<h5><a href="https://drive.google.com/a/google.com/folderview?id=0BwhAiXVwzMoFc28wWEpyeE9qYTQ&usp=sharing">Presentation</a></h5> -<h5><a href="http://developer.android.com/samples/ImmersiveMode/index.html">Sample</a></h5> -</p> - -<p> -<h4>Android 4.4 Storage Access Framework - Provider</h4> -Get up to speed on the new document storage API in Android 4.4 KitKat. This video gets you up and running with your own DocumentProvider by stepping you through the making of a simple cloud storage app. -<h5><a href="http://www.youtube.com/watch?v=zxHVeXbK1P4&list=PLWz5rJ2EKKc-2quE-o0enpILZF3nBZg_K">Video</a></h5> -<h5><a href="https://drive.google.com/a/google.com/folderview?id=0BwhAiXVwzMoFc28wWEpyeE9qYTQ&usp=sharing">Presentation</a></h5> -<h5><a href="http://developer.android.com/guide/topics/providers/document-provider.html">Training</a></h5> -<h5><a href="http://developer.android.com/samples/StorageProvider/index.html">Sample</a>, <a href="https://play.google.com/store/apps/details?id=com.box.android">Box Application</a></h5> -</blockquote> - -</p> - - -<p><h4>Android 4.4 Storage Access Framework - Client</h4> -Get up to speed on the new storage access framework in Android 4.4 KitKat. This video teaches you how to quickly create, edit, save and delete documents provided by other apps as a client of the storage access framework. -<h5><a href="http://www.youtube.com/watch?v=UFj9AEz0DHQ&list=PLWz5rJ2EKKc-2quE-o0enpILZF3nBZg_K">Video</a></h5> -<h5><a href="https://drive.google.com/a/google.com/folderview?id=0BwhAiXVwzMoFc28wWEpyeE9qYTQ&usp=sharing">Presentation</a></h5> -<h5><a href="http://developer.android.com/samples/StorageClient/index.html">Sample</a></h5> -</p> - -<p><h4>Android 4.4 Closed Captioning</h4> -Displaying closed captions in your app's videos can be quick and simple in Android 4.4 KitKat,. Learn how to attach timed text tracks to VideoView and allow users to customize how captions are displayed. -<h5><a href="http://www.youtube.com/watch?v=hCRGc2PcmB8&list=PLWz5rJ2EKKc-2quE-o0enpILZF3nBZg_K">Video</a></h5> -<h5><a href="https://drive.google.com/a/google.com/folderview?id=0BwhAiXVwzMoFc28wWEpyeE9qYTQ&usp=sharing">Presentation</a> -</p> -</h5> -</div> - -<div class="col-8" style="margin-right:0"> - -<p> -<h4>Android 4.4 Transitions</h4> -In this episode, we introduce the new Transitions API in Android 4.4 Kitkat. This API provides a simple way for developers to provide animated segues to different scenes of their application, helping users to understand the application flow with very little code. The general approach is to tell the system that you'd like to run a transition animation, then make the necessary changes to your UI. The system figures out the differences and animates the changes. -<h5><a href="http://www.youtube.com/watch?v=S3H7nJ4QaD8&list=PLWz5rJ2EKKc-2quE-o0enpILZF3nBZg_K&index=3">Video</a></h5> -<h5><a href="https://drive.google.com/a/google.com/folderview?id=0BwhAiXVwzMoFc28wWEpyeE9qYTQ&usp=sharing">Presentation</a></p> -</h5> -<p><h4>Android 4.4: SMS APIs</h4> -Android 4.4 KitKat introduces the new SMS APIs as well as the new concept of a default SMS app. This video discusses these new APIs and how your app should use them to send and receive SMS and MMS messages.<br> -<h5><a href="http://www.youtube.com/watch?v=mdq0R2WQssQ&list=PLWz5rJ2EKKc-2quE-o0enpILZF3nBZg_K">Video</a></h5> -<h5><a href="https://drive.google.com/a/google.com/folderview?id=0BwhAiXVwzMoFc28wWEpyeE9qYTQ&usp=sharing">Presentation</a></h5> -<i>See also -<br> -<a href="http://goo.gl/sw5NdH">Android Developer Blog post on Android 4.4 KitKat SMS APIs</a><br> -<a href="http://goo.gl/7vTx3s">Android Protip on using booleans in your AndroidManifest.xml</a></i></p> - - -<p><h4>Android 4.4 Printing API</h4> -In this video, we introduce the new Printing API in Android 4.4 KitKat. This API provides a simple way for developers to print to cloud-connected printers using Google Cloud Print. It's really easy to print bitmaps, and HTML (that you generate on the device, or just web content).<br> -<h5><a href="http://www.youtube.com/watch?v=Iub67ic87KI&list=PLWz5rJ2EKKc-2quE-o0enpILZF3nBZg_K">Video</a></h5> -<h5><a href="https://drive.google.com/a/google.com/folderview?id=0BwhAiXVwzMoFc28wWEpyeE9qYTQ&usp=sharing">Presentation</a></h5> -<h5><a href="http://developer.android.com/training/printing/index.html">Training</a></h5> -<i>Some pro-tips:</i> -<ul> - <li>For Webview/HTML printing, printing from javascript is not supported yet (window.print() for example). Also we are planning to address the limitations around WebView/HTML printing in future releases (eg: headers/footers, and specifying print ranges).</li> -<li>We encourage developers to open Android Open Source bugs for features that they feel important as a feedback.</li> -</ul> - -<p><h4>App Indexing</h4> -In this episode we discuss the new App Indexing feature that we recently announced for Google Search for Android.<br> -Currently, when you do a google search on the web, you get results that are links to websites. With App Indexing, you will be able to point Google Search users on Android directly to content within your app! -If you’re an Android app developer who has a web presence and you want more control over how your content is accessed from search, via your website or Android app, App Indexing is a great feature for you to explore. -Also, enabling your website and app for indexing is a way to increase engagement with your app by making the content more discoverable, and more accessible to users directly from the search results page. -For information on App Indexing, please visit <a href="http://g.co/appindexing">http://g.co/appindexing</a> -<h5><a href="http://www.youtube.com/watch?v=Xh_W82JgOms&list=PLWz5rJ2EKKc-2quE-o0enpILZF3nBZg_K">Video</a></h5> -<h5><a href="https://drive.google.com/a/google.com/folderview?id=0BwhAiXVwzMoFc28wWEpyeE9qYTQ&usp=sharing">Presentation</a> -</p> -</h5> -</div> - -<h2 id="Social" style="clear:left">Social</h2> -<div class="col-8" style="margin-left:0"> - -<h3 >G+</h3> - -<ul> -<li><a href="https://plus.google.com/u/1/108967384991768947849/posts/1iVvwyfTM8y">What's New in Android 4.4</a> - <ul> - <li><a href="http://www.youtube.com/watch?v=HrFRY32i_sE">What's New in Android 4.4 [JAPANESE!]</a></li> - <li><a href="https://www.youtube.com/watch?v=U9jAcwaETD4">What's New in Android 4.4 [KOREAN!]</a></li> - <li><a href="https://plus.google.com/u/1/108967384991768947849/posts/WfqdvDG2Cyr">Quer saber das novidades do Android 4.4? [PORTUGUESE!]</a></li> - </ul> -</li> -<li><a href="https://plus.google.com/u/1/+AndroidDevelopers/posts/femjRbay18f">Android 4.4 and Updated Developer Tools -</a></li> -<li><a href="https://plus.google.com/u/1/108967384991768947849/posts/P2q82aYN7do">Google Play Services 4.0 -</a></li> -</ul> -</div> - -<div class="col-8" style="margin-right:0"> -<h3>Blog</h3> - -<ul> - <li><a href="http://android-developers.blogspot.hk/2013/10/android-44-kitkat-and-updated-developer.html">Android 4.4 KitKat and Updated Developer Tools</a></li> - <li><a href="http://android-developers.blogspot.hk/2013/10/google-play-services-40.html">Google Play Services 4.0</a></li> - <li><a href="http://android-developers.blogspot.hk/2013/10/making-your-app-content-more-accessible.html">Making your App Content more Accessible from Googl...</a></li> - <li><a href="http://android-developers.blogspot.hk/2013/10/getting-your-sms-apps-ready-for-kitkat.html">Getting Your SMS Apps Ready for KitKat</a></li> -</ul> -</div> - -</div><!-- /MAIN CONTENT 'wrap' --> -</body> -</html> - - - diff --git a/docs/html/preview/setup-sdk.jd b/docs/html/preview/setup-sdk.jd index 3e95f3e864c0..ff11e8e93c3f 100644 --- a/docs/html/preview/setup-sdk.jd +++ b/docs/html/preview/setup-sdk.jd @@ -77,32 +77,10 @@ Android N Preview SDK in Android Studio as follows:</p> <h3 id="docs-dl">Get the N Preview reference documentation</h3> <p>Beginning with the Preview 4 release, the API reference for the -N platform (API level 24) is now available online at <a href= - "{@docRoot}reference/">developer.android.com/reference/</a>. -</p> - -<p>If you'd like an offline copy of the API reference, you can download it -from the following table. The download also includes an incremental diff report -for API changes between the Preview 3 and Preview 4 release, which is not -available online.</p> - -<table> - <tr> - <th scope="col">Documentation</th> - <th scope="col">Checksums</th> - </tr> - <tr> - <td style="white-space: nowrap"> - <a href="{@docRoot}shareables/preview/n-preview-4-docs.zip" - >n-preview-4-docs.zip</a></td> - <td width="100%"> - MD5: f853e3ba0707083336dfa780b8fed9a7<br> - SHA-1: 36fcbc497cc2e63b1bc1d629c304b0ba43a88946 - </td> - </tr> -</table> - - + N platform (API level 24) is now available online at <a href= + "{@docRoot}reference/">developer.android.com/reference/</a>. There is also + an incremental diff report for <a href="{@docRoot}sdk/api_diff/24/changes.html" + >API changes between API levels 23 and 24</a>.</p> <h2 id="java8">Get the Java 8 JDK</h2> diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java index 99145b7bda0a..eea92b5ca62e 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java +++ b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java @@ -94,6 +94,7 @@ public final class RemotePrintDocument { // but the content has changed. if (mNextCommand == null) { if (mUpdateSpec.pages != null && (mDocumentInfo.changed + || mDocumentInfo.writtenPages == null || (mDocumentInfo.info.getPageCount() != PrintDocumentInfo.PAGE_COUNT_UNKNOWN && !PageRangeUtils.contains(mDocumentInfo.writtenPages, diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java index b79ce8027231..bf48e5de1da3 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java @@ -247,7 +247,6 @@ public class SettingsHelper { return Settings.Secure.getInt(mContext.getContentResolver(), name, 0) != 0; case Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES: case Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES: - case Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX: case Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER: case Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE: return !TextUtils.isEmpty(Settings.Secure.getString( diff --git a/packages/SystemUI/res/drawable/ic_qs_night_display_off.xml b/packages/SystemUI/res/drawable/ic_qs_night_display_off.xml new file mode 100644 index 000000000000..778ccbc5f4a4 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_night_display_off.xml @@ -0,0 +1,27 @@ +<!-- + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="64dp" + android:height="64dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:alpha="0.3"> + + <path + android:fillColor="#FFF" + android:pathData="M6,12c0,5.5,4.5,10,10,10c1,0,2-0.2,3-0.5c-4.1-1.3-7-5.1-7-9.5s2.9-8.3,7-9.5C18.1,2.2,17.1,2,16,2C10.5,2,6,6.5,6,12z" /> + +</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_night_display_on.xml b/packages/SystemUI/res/drawable/ic_qs_night_display_on.xml new file mode 100644 index 000000000000..aaca663e59e9 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_night_display_on.xml @@ -0,0 +1,26 @@ +<!-- + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="64dp" + android:height="64dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:fillColor="#FFF" + android:pathData="M6,12c0,5.5,4.5,10,10,10c1,0,2-0.2,3-0.5c-4.1-1.3-7-5.1-7-9.5s2.9-8.3,7-9.5C18.1,2.2,17.1,2,16,2C10.5,2,6,6.5,6,12z" /> + +</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml b/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml index 258bd0f7902e..4d7f325073dc 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml @@ -1,37 +1,30 @@ <!-- - Copyright (C) 2016 The Android Open Source Project + 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 + 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 - 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. + 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. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="18.0dp" - android:height="24dp" - android:viewportWidth="36.0" - android:viewportHeight="36.0"> - + android:width="24.0dp" + android:height="24.0dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> <path - android:fillColor="#FFFFFF" - android:pathData="M6.797,13.334h1.231v1.522H6.797v2.509h-1.62v-2.509H1.101l-0.039-1.157l4.069-7.643h1.666V13.334z -M2.648,13.334h2.53V8.721L5.137,8.713L4.984,9.148L2.648,13.334z" /> + android:fillColor="#FFFFFFFF" + android:pathData="M4.6,7.8l0.7,0.0l0.0,1.3L4.6,9.1L4.6,11.0L3.0,11.0L3.0,9.2L0.1,9.2L0.0,8.2l3.0,-5.7l1.7,0.0L4.6,7.8L4.6,7.8zM1.7,7.8L3.0,7.8l0.0,-3.0L2.9,5.0L1.7,7.8z"/> <path - android:fillColor="#FFFFFF" - android:pathData="M16.155,15.836c-0.269,0.439-0.695,0.832-1.282,1.177c-0.587,0.344-1.344,0.517-2.271,0.517 -c-1.151,0-2.098-0.432-2.841-1.294c-0.744-0.862-1.115-1.978-1.115-3.345v-2.36c0-1.367,0.359-2.481,1.077-3.343 -c0.719-0.863,1.643-1.293,2.772-1.293c1.132,0,2.017,0.331,2.649,0.994c0.633,0.663,0.941,1.528,0.924,2.594l-0.021,0.047h-1.545 -c0-0.638-0.171-1.15-0.513-1.538c-0.341-0.389-0.831-0.583-1.469-0.583c-0.674,0-1.217,0.292-1.63,0.877 -c-0.413,0.585-0.619,1.328-0.619,2.229v2.375c0,0.912,0.215,1.662,0.645,2.25c0.431,0.587,0.992,0.881,1.684,0.881 -c0.522,0,0.935-0.068,1.238-0.205c0.304-0.138,0.533-0.305,0.688-0.502v-2.338h-2.041v-1.413h3.668V15.836z" /> + android:fillColor="#FFFFFFFF" + android:pathData="M11.9,9.9c-0.2,0.4 -0.6,0.7 -1.0,0.9s-1.0,0.4 -1.8,0.4c-0.9,0.0 -1.7,-0.3 -2.2,-0.8S6.1,9.0 6.1,7.9L6.1,5.6c0.0,-1.1 0.3,-1.9 0.8,-2.4S8.2,2.4 9.0,2.4c1.0,0.0 1.7,0.2 2.1,0.7s0.7,1.2 0.7,2.1l-1.6,0.0c0.0,-0.5 -0.1,-0.9 -0.2,-1.1S9.5,3.7 9.0,3.7c-0.4,0.0 -0.7,0.2 -0.9,0.5S7.8,5.0 7.8,5.6l0.0,2.3c0.0,0.7 0.1,1.1 0.3,1.4c0.2,0.3 0.6,0.5 1.0,0.5c0.3,0.0 0.6,0.0 0.7,-0.1s0.3,-0.2 0.4,-0.3L10.2,7.8L9.0,7.8L9.0,6.6l2.9,0.0L11.9,9.9z"/> <path - android:fillColor="#FFFFFF" - android:pathData="M19.366,14.701v-2.232h-2.25v-1.541h2.25V8.695h1.5v2.232h2.256v1.541h-2.256v2.232H19.366z" /> + android:fillColor="#FFFFFFFF" + android:pathData="M17.7,4.4l-1.900001,0.0 0.0,-1.9 -1.2,0.0 0.0,1.9 -1.900001,0.0 0.0,1.2 1.900001,0.0 0.0,1.9 1.2,0.0 0.0,-1.9 1.900001,0.0z"/> </vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml b/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml new file mode 100644 index 000000000000..3af062999728 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml @@ -0,0 +1,33 @@ +<!-- + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24.0dp" + android:height="24.0dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M2.0,9.7l2.0,0.0L4.0,11.0L0.4,11.0L0.4,2.5L2.0,2.5L2.0,9.7z"/> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M8.3,3.8L7.0,3.8L7.0,11.0L5.4,11.0L5.4,3.8L4.0,3.8L4.0,2.5l4.3,0.0L8.3,3.8z"/> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M12.4,7.3l-1.7,0.0l0.0,2.4l2.1,0.0L12.799999,11.0L9.0,11.0L9.0,2.5l3.7,0.0l0.0,1.3l-2.1,0.0l0.0,2.1l1.7,0.0L12.4,7.3L12.4,7.3z"/> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M18.4,4.4l-1.9,0.0 0.0,-1.9 -1.2,0.0 0.0,1.9 -1.900001,0.0 0.0,1.2 1.900001,0.0 0.0,1.9 1.2,0.0 0.0,-1.9 1.9,0.0z"/> +</vector> diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml index 17a4394ce6df..3cdd3e104bfb 100644 --- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml +++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml @@ -1,37 +1,30 @@ <!-- - Copyright (C) 2016 The Android Open Source Project + 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 + 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 + 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. + 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. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="15dp" - android:height="20dp" - android:viewportWidth="36" - android:viewportHeight="36"> - + android:width="17.0dp" + android:height="17.0dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> <path - android:fillColor="#FFFFFF" - android:pathData="M6.797,13.334h1.231v1.522H6.797v2.509h-1.62v-2.509H1.101l-0.039-1.157l4.069-7.643h1.666V13.334z -M2.648,13.334h2.53V8.721L5.137,8.713L4.984,9.148L2.648,13.334z" /> + android:fillColor="#FFFFFFFF" + android:pathData="M4.6,7.8l0.7,0.0l0.0,1.3L4.6,9.1L4.6,11.0L3.0,11.0L3.0,9.2L0.1,9.2L0.0,8.2l3.0,-5.7l1.7,0.0L4.6,7.8L4.6,7.8zM1.7,7.8L3.0,7.8l0.0,-3.0L2.9,5.0L1.7,7.8z"/> <path - android:fillColor="#FFFFFF" - android:pathData="M16.155,15.836c-0.269,0.439-0.695,0.832-1.282,1.177c-0.587,0.344-1.344,0.517-2.271,0.517 -c-1.151,0-2.098-0.432-2.841-1.294c-0.744-0.862-1.115-1.978-1.115-3.345v-2.36c0-1.367,0.359-2.481,1.077-3.343 -c0.719-0.863,1.643-1.293,2.772-1.293c1.132,0,2.017,0.331,2.649,0.994c0.633,0.663,0.941,1.528,0.924,2.594l-0.021,0.047h-1.545 -c0-0.638-0.171-1.15-0.513-1.538c-0.341-0.389-0.831-0.583-1.469-0.583c-0.674,0-1.217,0.292-1.63,0.877 -c-0.413,0.585-0.619,1.328-0.619,2.229v2.375c0,0.912,0.215,1.662,0.645,2.25c0.431,0.587,0.992,0.881,1.684,0.881 -c0.522,0,0.935-0.068,1.238-0.205c0.304-0.138,0.533-0.305,0.688-0.502v-2.338h-2.041v-1.413h3.668V15.836z" /> + android:fillColor="#FFFFFFFF" + android:pathData="M11.9,9.9c-0.2,0.4 -0.6,0.7 -1.0,0.9s-1.0,0.4 -1.8,0.4c-0.9,0.0 -1.7,-0.3 -2.2,-0.8S6.1,9.0 6.1,7.9L6.1,5.6c0.0,-1.1 0.3,-1.9 0.8,-2.4S8.2,2.4 9.0,2.4c1.0,0.0 1.7,0.2 2.1,0.7s0.7,1.2 0.7,2.1l-1.6,0.0c0.0,-0.5 -0.1,-0.9 -0.2,-1.1S9.5,3.7 9.0,3.7c-0.4,0.0 -0.7,0.2 -0.9,0.5S7.8,5.0 7.8,5.6l0.0,2.3c0.0,0.7 0.1,1.1 0.3,1.4c0.2,0.3 0.6,0.5 1.0,0.5c0.3,0.0 0.6,0.0 0.7,-0.1s0.3,-0.2 0.4,-0.3L10.2,7.8L9.0,7.8L9.0,6.6l2.9,0.0L11.9,9.9z"/> <path - android:fillColor="#FFFFFF" - android:pathData="M19.366,14.701v-2.232h-2.25v-1.541h2.25V8.695h1.5v2.232h2.256v1.541h-2.256v2.232H19.366z" /> + android:fillColor="#FFFFFFFF" + android:pathData="M17.7,4.4l-1.900001,0.0 0.0,-1.9 -1.2,0.0 0.0,1.9 -1.900001,0.0 0.0,1.2 1.900001,0.0 0.0,1.9 1.2,0.0 0.0,-1.9 1.900001,0.0z"/> </vector> diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte_plus.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte_plus.xml new file mode 100644 index 000000000000..db18fad637e7 --- /dev/null +++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte_plus.xml @@ -0,0 +1,33 @@ +<!-- + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="17.0dp" + android:height="17.0dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M2.0,9.7l2.0,0.0L4.0,11.0L0.4,11.0L0.4,2.5L2.0,2.5L2.0,9.7z"/> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M8.3,3.8L7.0,3.8L7.0,11.0L5.4,11.0L5.4,3.8L4.0,3.8L4.0,2.5l4.3,0.0L8.3,3.8z"/> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M12.4,7.3l-1.7,0.0l0.0,2.4l2.1,0.0L12.799999,11.0L9.0,11.0L9.0,2.5l3.7,0.0l0.0,1.3l-2.1,0.0l0.0,2.1l1.7,0.0L12.4,7.3L12.4,7.3z"/> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M18.4,4.4l-1.9,0.0 0.0,-1.9 -1.2,0.0 0.0,1.9 -1.900001,0.0 0.0,1.2 1.900001,0.0 0.0,1.9 1.2,0.0 0.0,-1.9 1.9,0.0z"/> +</vector> diff --git a/packages/SystemUI/res/layout/battery_detail.xml b/packages/SystemUI/res/layout/battery_detail.xml index 1f24ab0fad21..8abfcf6057aa 100644 --- a/packages/SystemUI/res/layout/battery_detail.xml +++ b/packages/SystemUI/res/layout/battery_detail.xml @@ -25,7 +25,7 @@ android:id="@+id/charge_and_estimation" android:layout_width="match_parent" android:layout_height="wrap_content" - android:paddingStart="72dp" + android:paddingStart="16dp" android:textAppearance="?android:attr/textAppearanceSmall" android:textColor="?android:attr/colorAccent" /> diff --git a/packages/SystemUI/res/layout/qs_detail_header.xml b/packages/SystemUI/res/layout/qs_detail_header.xml index c062b6d671a5..f6ca862370ac 100644 --- a/packages/SystemUI/res/layout/qs_detail_header.xml +++ b/packages/SystemUI/res/layout/qs_detail_header.xml @@ -22,19 +22,9 @@ android:background="@drawable/btn_borderless_rect" android:gravity="center"> - <ImageView - android:id="@*android:id/up" - android:layout_width="56dp" - android:layout_height="56dp" - android:layout_marginEnd="16dp" - android:padding="16dp" - android:clickable="true" - android:background="?android:attr/selectableItemBackground" - android:contentDescription="@*android:string/action_bar_up_description" - android:src="?android:attr/homeAsUpIndicator" /> - <TextView android:id="@android:id/title" + android:paddingStart="16dp" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 3ed071177de8..a0cb61ab301e 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -354,6 +354,9 @@ <!-- Content description of the data connection type LTE for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_data_connection_lte">LTE</string> + <!-- Content description of the data connection type LTE+ for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_data_connection_lte_plus">LTE+</string> + <!-- Content description of the data connection type CDMA for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_data_connection_cdma">CDMA</string> @@ -752,6 +755,12 @@ <string name="quick_settings_cellular_detail_data_warning"><xliff:g id="data_limit" example="2.0 GB">%s</xliff:g> warning</string> <!-- QuickSettings: Work mode [CHAR LIMIT=NONE] --> <string name="quick_settings_work_mode_label">Work mode</string> + <!-- QuickSettings: Label for the toggle to activate Night display (renamed "Night Light" with title caps). [CHAR LIMIT=20] --> + <string name="quick_settings_night_display_label">Night Light</string> + <!-- QuickSettings: Summary for the toggle to deactivate Night display when it's on (renamed "Night Light" with title caps). [CHAR LIMIT=NONE] --> + <string name="quick_settings_night_display_summary_on">Night Light on, tap to turn off</string> + <!-- QuickSettings: Label for the toggle to activate Night display when it's off (renamed "Night Light" with title caps). [CHAR LIMIT=NONE] --> + <string name="quick_settings_night_display_summary_off">Night Light off, tap to turn on</string> <!-- Recents: The empty recents string. [CHAR LIMIT=NONE] --> <string name="recents_empty_message">No recent items</string> diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java index a40e5b7789c6..c63be9ce9760 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java @@ -63,7 +63,6 @@ public class QSDetail extends LinearLayout { private boolean mScanState; private boolean mClosingDetail; private boolean mFullyExpanded; - private View mQsDetailHeaderBack; private BaseStatusBarHeader mHeader; private boolean mTriggeredExpand; private int mOpenX; @@ -92,7 +91,6 @@ public class QSDetail extends LinearLayout { mDetailDoneButton = (TextView) findViewById(android.R.id.button1); mQsDetailHeader = findViewById(R.id.qs_detail_header); - mQsDetailHeaderBack = mQsDetailHeader.findViewById(com.android.internal.R.id.up); mQsDetailHeaderTitle = (TextView) mQsDetailHeader.findViewById(android.R.id.title); mQsDetailHeaderSwitch = (Switch) mQsDetailHeader.findViewById(android.R.id.toggle); mQsDetailHeaderProgress = (ImageView) findViewById(R.id.qs_detail_header_progress); @@ -109,7 +107,6 @@ public class QSDetail extends LinearLayout { mQsPanel.closeDetail(); } }; - mQsDetailHeaderBack.setOnClickListener(doneListener); mDetailDoneButton.setOnClickListener(doneListener); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java new file mode 100644 index 000000000000..9a3549eb6a75 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2016, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.tiles; + +import android.content.Intent; +import android.provider.Settings; +import android.widget.Switch; + +import com.android.internal.app.NightDisplayController; +import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.MetricsProto.MetricsEvent; +import com.android.systemui.R; +import com.android.systemui.qs.QSTile; + +public class NightDisplayTile extends QSTile<QSTile.BooleanState> + implements NightDisplayController.Callback { + + private final NightDisplayController mController; + + public NightDisplayTile(Host host) { + super(host); + mController = new NightDisplayController(mContext); + } + + @Override + public boolean isAvailable() { + return NightDisplayController.isAvailable(mContext); + } + + @Override + public BooleanState newTileState() { + return new BooleanState(); + } + + @Override + protected void handleClick() { + final boolean activated = !mState.value; + MetricsLogger.action(mContext, getMetricsCategory(), activated); + mController.setActivated(activated); + } + + @Override + protected void handleUpdateState(BooleanState state, Object arg) { + final boolean isActivated = mController.isActivated(); + state.value = isActivated; + state.label = mContext.getString(R.string.quick_settings_night_display_label); + state.icon = ResourceIcon.get(isActivated ? R.drawable.ic_qs_night_display_on + : R.drawable.ic_qs_night_display_off); + state.contentDescription = mContext.getString(isActivated + ? R.string.quick_settings_night_display_summary_on + : R.string.quick_settings_night_display_summary_off); + state.minimalAccessibilityClassName = state.expandedAccessibilityClassName + = Switch.class.getName(); + } + + @Override + public int getMetricsCategory() { + return MetricsEvent.QS_NIGHT_DISPLAY; + } + + @Override + public Intent getLongClickIntent() { + return new Intent(Settings.ACTION_DISPLAY_SETTINGS); + } + + @Override + protected void setListening(boolean listening) { + if (listening) { + mController.setListener(this); + refreshState(); + } else { + mController.setListener(null); + } + } + + @Override + public CharSequence getTileLabel() { + return mContext.getString(R.string.quick_settings_night_display_label); + } + + @Override + public void onActivated(boolean activated) { + refreshState(); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java index ca7f9051f56d..15e235dd4d5f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java @@ -52,6 +52,7 @@ import com.android.systemui.qs.tiles.FlashlightTile; import com.android.systemui.qs.tiles.HotspotTile; import com.android.systemui.qs.tiles.IntentTile; import com.android.systemui.qs.tiles.LocationTile; +import com.android.systemui.qs.tiles.NightDisplayTile; import com.android.systemui.qs.tiles.RotationLockTile; import com.android.systemui.qs.tiles.UserTile; import com.android.systemui.qs.tiles.WifiTile; @@ -440,6 +441,7 @@ public class QSTileHost implements QSTile.Host, Tunable { else if (tileSpec.equals("user")) return new UserTile(this); else if (tileSpec.equals("battery")) return new BatteryTile(this); else if (tileSpec.equals("saver")) return new DataSaverTile(this); + else if (tileSpec.equals("night")) return new NightDisplayTile(this); // Intent tiles. else if (tileSpec.startsWith(IntentTile.PREFIX)) return IntentTile.create(this,tileSpec); else if (tileSpec.startsWith(CustomTile.PREFIX)) return CustomTile.create(this,tileSpec); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java index f415ae588c4e..0c9bfab794d1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java @@ -338,11 +338,12 @@ public class StatusBarIconController extends StatusBarIconList implements Tunabl public void dump(PrintWriter pw) { int N = mStatusIcons.getChildCount(); - pw.println(" system icons: " + N); + pw.println(" icon views: " + N); for (int i=0; i<N; i++) { StatusBarIconView ic = (StatusBarIconView) mStatusIcons.getChildAt(i); pw.println(" [" + i + "] icon=" + ic); } + super.dump(pw); } public void dispatchDemoCommand(String command, Bundle args) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java index 97b31f248fa1..682187926762 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java @@ -81,9 +81,9 @@ public class StatusBarIconList { public void dump(PrintWriter pw) { final int N = mSlots.size(); - pw.println("Icon list:"); + pw.println(" icon slots: " + N); for (int i=0; i<N; i++) { - pw.printf(" %2d: (%s) %s\n", i, mSlots.get(i), mIcons.get(i)); + pw.printf(" %2d: (%s) %s\n", i, mSlots.get(i), mIcons.get(i)); } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java index ac3246d5ff6b..8178bdaded04 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java @@ -201,7 +201,7 @@ public class MobileSignalController extends SignalController< TelephonyIcons.FOUR_G_PLUS); } else { mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.LTE); - mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA, TelephonyIcons.LTE); + mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA, TelephonyIcons.LTE_PLUS); } mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_IWLAN, TelephonyIcons.WFC); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java index 7a042af7f42e..a31bc04d8318 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -786,6 +786,7 @@ public class NetworkControllerImpl extends BroadcastReceiver datatype.equals("g") ? TelephonyIcons.G : datatype.equals("h") ? TelephonyIcons.H : datatype.equals("lte") ? TelephonyIcons.LTE : + datatype.equals("lte+") ? TelephonyIcons.LTE_PLUS : datatype.equals("roam") ? TelephonyIcons.ROAMING : TelephonyIcons.UNKNOWN; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java index d91b3329d1ac..ed8c7ff96aac 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java @@ -208,10 +208,12 @@ class TelephonyIcons { }; static final int QS_DATA_LTE = R.drawable.ic_qs_signal_lte; + static final int QS_DATA_LTE_PLUS = R.drawable.ic_qs_signal_lte_plus; static final int FLIGHT_MODE_ICON = R.drawable.stat_sys_airplane_mode; static final int ROAMING_ICON = R.drawable.stat_sys_data_fully_connected_roam; static final int ICON_LTE = R.drawable.stat_sys_data_fully_connected_lte; + static final int ICON_LTE_PLUS = R.drawable.stat_sys_data_fully_connected_lte_plus; static final int ICON_G = R.drawable.stat_sys_data_fully_connected_g; static final int ICON_E = R.drawable.stat_sys_data_fully_connected_e; static final int ICON_H = R.drawable.stat_sys_data_fully_connected_h; @@ -393,6 +395,21 @@ class TelephonyIcons { TelephonyIcons.QS_DATA_LTE ); + static final MobileIconGroup LTE_PLUS = new MobileIconGroup( + "LTE+", + TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH, + TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, + 0, 0, + TelephonyIcons.TELEPHONY_NO_NETWORK, + TelephonyIcons.QS_TELEPHONY_NO_NETWORK, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], + R.string.accessibility_data_connection_lte_plus, + TelephonyIcons.ICON_LTE_PLUS, + true, + TelephonyIcons.QS_DATA_LTE_PLUS + ); + static final MobileIconGroup ROAMING = new MobileIconGroup( "Roaming", TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java index 7de38797adcc..e00674a55b1e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java @@ -2347,6 +2347,7 @@ public class NotificationStackScrollLayout extends ViewGroup if (hasAddEvent) { // This child was just added lets remove all events. mHeadsUpChangeAnimations.removeAll(mTmpList); + ((ExpandableNotificationRow ) child).setHeadsupDisappearRunning(false); } mTmpList.clear(); return hasAddEvent; @@ -3093,6 +3094,16 @@ public class NotificationStackScrollLayout extends ViewGroup requestChildrenUpdate(); runAnimationFinishedRunnables(); clearViewOverlays(); + clearHeadsUpDisappearRunning(); + } + + private void clearHeadsUpDisappearRunning() { + for (int i = 0; i < getChildCount(); i++) { + View view = getChildAt(i); + if (view instanceof ExpandableNotificationRow) { + ((ExpandableNotificationRow) view).setHeadsupDisappearRunning(false); + } + } } private void clearViewOverlays() { diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerZenModePanel.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerZenModePanel.java index cc0ffb0e2653..1ea23bb65107 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/TunerZenModePanel.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerZenModePanel.java @@ -54,7 +54,6 @@ public class TunerZenModePanel extends LinearLayout implements OnClickListener { mHeaderSwitch = findViewById(R.id.tuner_zen_switch); mHeaderSwitch.setVisibility(View.VISIBLE); mHeaderSwitch.setOnClickListener(this); - mHeaderSwitch.findViewById(com.android.internal.R.id.up).setVisibility(View.GONE); ((TextView) mHeaderSwitch.findViewById(android.R.id.title)).setText( R.string.quick_settings_dnd_label); mZenModePanel = (ZenModePanel) findViewById(R.id.zen_mode_panel); diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto index 966d0ec44835..ba59c2f0192a 100644 --- a/proto/src/metrics_constants.proto +++ b/proto/src/metrics_constants.proto @@ -2188,6 +2188,12 @@ message MetricsEvent { // Settings launched from collapsed quick settings. ACTION_QS_COLLAPSED_SETTINGS_LAUNCH = 490; + // OPEN: QS Night mode tile shown + // ACTION: QS Night mode tile tapped + // SUBTYPE: 0 is off, 1 is on + // CATEGORY: QUICK_SETTINGS + QS_NIGHT_DISPLAY = 491; + // ---- End N-MR1 Constants, all N-MR1 constants go above this line ---- // Add new aosp constants above this line. // END OF AOSP CONSTANTS diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 60d33397368d..7ebc150bb30b 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -1422,7 +1422,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { updateTouchExplorationLocked(userState); updatePerformGesturesLocked(userState); updateEnhancedWebAccessibilityLocked(userState); - updateDisplayColorAdjustmentSettingsLocked(userState); + updateDisplayDaltonizerLocked(userState); + updateDisplayInversionLocked(userState); updateMagnificationLocked(userState); updateSoftKeyboardShowModeLocked(userState); scheduleUpdateInputFilter(userState); @@ -1539,7 +1540,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { somethingChanged |= readEnhancedWebAccessibilityEnabledChangedLocked(userState); somethingChanged |= readDisplayMagnificationEnabledSettingLocked(userState); somethingChanged |= readAutoclickEnabledSettingLocked(userState); - somethingChanged |= readDisplayColorAdjustmentSettingsLocked(userState); return somethingChanged; } @@ -1602,18 +1602,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { return false; } - private boolean readDisplayColorAdjustmentSettingsLocked(UserState userState) { - final boolean displayAdjustmentsEnabled = DisplayAdjustmentUtils.hasAdjustments(mContext, - userState.mUserId); - if (displayAdjustmentsEnabled != userState.mHasDisplayColorAdjustment) { - userState.mHasDisplayColorAdjustment = displayAdjustmentsEnabled; - return true; - } - // If display adjustment is enabled, always assume there was a change in - // the adjustment settings. - return displayAdjustmentsEnabled; - } - private boolean readHighTextContrastEnabledSettingLocked(UserState userState) { final boolean highTextContrastEnabled = Settings.Secure.getIntForUser( mContext.getContentResolver(), @@ -1730,8 +1718,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { return false; } - private void updateDisplayColorAdjustmentSettingsLocked(UserState userState) { - DisplayAdjustmentUtils.applyAdjustments(mContext, userState.mUserId); + private void updateDisplayDaltonizerLocked(UserState userState) { + DisplayAdjustmentUtils.applyDaltonizerSetting(mContext, userState.mUserId); + } + + private void updateDisplayInversionLocked(UserState userState) { + DisplayAdjustmentUtils.applyInversionSetting(mContext, userState.mUserId); } private void updateMagnificationLocked(UserState userState) { @@ -4184,7 +4176,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { public boolean mIsAutoclickEnabled; public boolean mIsPerformGesturesEnabled; public boolean mIsFilterKeyEventsEnabled; - public boolean mHasDisplayColorAdjustment; public boolean mAccessibilityFocusOnlyInActiveWindow; private Service mUiAutomationService; @@ -4300,9 +4291,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private final Uri mDisplayDaltonizerUri = Settings.Secure.getUriFor( Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER); - private final Uri mDisplayColorMatrixUri = Settings.Secure.getUriFor( - Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX); - private final Uri mHighTextContrastUri = Settings.Secure.getUriFor( Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED); @@ -4334,8 +4322,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { contentResolver.registerContentObserver( mDisplayDaltonizerUri, false, this, UserHandle.USER_ALL); contentResolver.registerContentObserver( - mDisplayColorMatrixUri, false, this, UserHandle.USER_ALL); - contentResolver.registerContentObserver( mHighTextContrastUri, false, this, UserHandle.USER_ALL); contentResolver.registerContentObserver( mAccessibilitySoftKeyboardModeUri, false, this, UserHandle.USER_ALL); @@ -4377,14 +4363,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { if (readEnhancedWebAccessibilityEnabledChangedLocked(userState)) { onUserStateChangedLocked(userState); } - } else if (mDisplayInversionEnabledUri.equals(uri) - || mDisplayDaltonizerEnabledUri.equals(uri) + } else if (mDisplayDaltonizerEnabledUri.equals(uri) || mDisplayDaltonizerUri.equals(uri)) { - if (readDisplayColorAdjustmentSettingsLocked(userState)) { - updateDisplayColorAdjustmentSettingsLocked(userState); - } - } else if (mDisplayColorMatrixUri.equals(uri)) { - updateDisplayColorAdjustmentSettingsLocked(userState); + updateDisplayDaltonizerLocked(userState); + } else if (mDisplayInversionEnabledUri.equals(uri)) { + updateDisplayInversionLocked(userState); } else if (mHighTextContrastUri.equals(uri)) { if (readHighTextContrastEnabledSettingLocked(userState)) { onUserStateChangedLocked(userState); diff --git a/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java b/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java index e1f3cd8dc40c..15329461a811 100644 --- a/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java +++ b/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java @@ -18,23 +18,23 @@ package com.android.server.accessibility; import android.content.ContentResolver; import android.content.Context; -import android.opengl.Matrix; -import android.os.IBinder; -import android.os.Parcel; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.provider.Settings; -import android.util.Slog; +import android.provider.Settings.Secure; import android.view.accessibility.AccessibilityManager; +import com.android.server.LocalServices; +import com.android.server.display.DisplayTransformManager; + /** * Utility methods for performing accessibility display adjustments. */ class DisplayAdjustmentUtils { - private static final String LOG_TAG = DisplayAdjustmentUtils.class.getSimpleName(); + + /** Default inversion mode for display color correction. */ + private static final int DEFAULT_DISPLAY_DALTONIZER = + AccessibilityManager.DALTONIZER_CORRECT_DEUTERANOMALY; /** Matrix and offset used for converting color to gray-scale. */ - private static final float[] GRAYSCALE_MATRIX = new float[] { + private static final float[] MATRIX_GRAYSCALE = new float[] { .2126f, .2126f, .2126f, 0, .7152f, .7152f, .7152f, 0, .0722f, .0722f, .0722f, 0, @@ -48,150 +48,44 @@ class DisplayAdjustmentUtils { * represents a non-multiplied addition, see surfaceflinger's ProgramCache * for full implementation details. */ - private static final float[] INVERSION_MATRIX_VALUE_ONLY = new float[] { + private static final float[] MATRIX_INVERT_COLOR = new float[] { 0.402f, -0.598f, -0.599f, 0, -1.174f, -0.174f, -1.175f, 0, -0.228f, -0.228f, 0.772f, 0, 1, 1, 1, 1 }; - /** Default inversion mode for display color correction. */ - private static final int DEFAULT_DISPLAY_DALTONIZER = - AccessibilityManager.DALTONIZER_CORRECT_DEUTERANOMALY; - - /** - * Returns whether the specified user with has any display color - * adjustments. - */ - public static boolean hasAdjustments(Context context, int userId) { + public static void applyDaltonizerSetting(Context context, int userId) { final ContentResolver cr = context.getContentResolver(); + final DisplayTransformManager dtm = LocalServices.getService(DisplayTransformManager.class); - if (Settings.Secure.getIntForUser(cr, - Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, userId) != 0) { - return true; + int daltonizerMode = AccessibilityManager.DALTONIZER_DISABLED; + if (Secure.getIntForUser(cr, + Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0, userId) != 0) { + daltonizerMode = Secure.getIntForUser(cr, + Secure.ACCESSIBILITY_DISPLAY_DALTONIZER, DEFAULT_DISPLAY_DALTONIZER, userId); } - if (Settings.Secure.getIntForUser(cr, - Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0, userId) != 0) { - return true; + float[] grayscaleMatrix = null; + if (daltonizerMode == AccessibilityManager.DALTONIZER_SIMULATE_MONOCHROMACY) { + // Monochromacy isn't supported by the native Daltonizer. + grayscaleMatrix = MATRIX_GRAYSCALE; + daltonizerMode = AccessibilityManager.DALTONIZER_DISABLED; } - - return false; + dtm.setColorMatrix(DisplayTransformManager.LEVEL_COLOR_MATRIX_GRAYSCALE, grayscaleMatrix); + dtm.setDaltonizerMode(daltonizerMode); } /** * Applies the specified user's display color adjustments. */ - public static void applyAdjustments(Context context, int userId) { + public static void applyInversionSetting(Context context, int userId) { final ContentResolver cr = context.getContentResolver(); - float[] colorMatrix = null; - - if (Settings.Secure.getIntForUser(cr, - Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, userId) != 0) { - colorMatrix = multiply(colorMatrix, INVERSION_MATRIX_VALUE_ONLY); - } - - if (Settings.Secure.getIntForUser(cr, - Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0, userId) != 0) { - final int daltonizerMode = Settings.Secure.getIntForUser(cr, - Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER, DEFAULT_DISPLAY_DALTONIZER, - userId); - // Monochromacy isn't supported by the native Daltonizer. - if (daltonizerMode == AccessibilityManager.DALTONIZER_SIMULATE_MONOCHROMACY) { - colorMatrix = multiply(colorMatrix, GRAYSCALE_MATRIX); - setDaltonizerMode(AccessibilityManager.DALTONIZER_DISABLED); - } else { - setDaltonizerMode(daltonizerMode); - } - } else { - setDaltonizerMode(AccessibilityManager.DALTONIZER_DISABLED); - } - - String matrix = Settings.Secure.getStringForUser(cr, - Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, userId); - if (matrix != null) { - final float[] userMatrix = get4x4Matrix(matrix); - if (userMatrix != null) { - colorMatrix = multiply(colorMatrix, userMatrix); - } - } - - setColorTransform(colorMatrix); - } - - private static float[] get4x4Matrix(String matrix) { - String[] strValues = matrix.split(","); - if (strValues.length != 16) { - return null; - } - float[] values = new float[strValues.length]; - try { - for (int i = 0; i < values.length; i++) { - values[i] = Float.parseFloat(strValues[i]); - } - } catch (java.lang.NumberFormatException ex) { - return null; - } - return values; - } + final DisplayTransformManager dtm = LocalServices.getService(DisplayTransformManager.class); - private static float[] multiply(float[] matrix, float[] other) { - if (matrix == null) { - return other; - } - float[] result = new float[16]; - Matrix.multiplyMM(result, 0, matrix, 0, other, 0); - return result; + final boolean invertColors = Secure.getIntForUser(cr, + Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, userId) != 0; + dtm.setColorMatrix(DisplayTransformManager.LEVEL_COLOR_MATRIX_INVERT_COLOR, + invertColors ? MATRIX_INVERT_COLOR : null); } - - /** - * Sets the surface flinger's Daltonization mode. This adjusts the color - * space to correct for or simulate various types of color blindness. - * - * @param mode new Daltonization mode - */ - private static void setDaltonizerMode(int mode) { - try { - final IBinder flinger = ServiceManager.getService("SurfaceFlinger"); - if (flinger != null) { - final Parcel data = Parcel.obtain(); - data.writeInterfaceToken("android.ui.ISurfaceComposer"); - data.writeInt(mode); - flinger.transact(1014, data, null, 0); - data.recycle(); - } - } catch (RemoteException ex) { - Slog.e(LOG_TAG, "Failed to set Daltonizer mode", ex); - } - } - - /** - * Sets the surface flinger's color transformation as a 4x4 matrix. If the - * matrix is null, color transformations are disabled. - * - * @param m the float array that holds the transformation matrix, or null to - * disable transformation - */ - private static void setColorTransform(float[] m) { - try { - final IBinder flinger = ServiceManager.getService("SurfaceFlinger"); - if (flinger != null) { - final Parcel data = Parcel.obtain(); - data.writeInterfaceToken("android.ui.ISurfaceComposer"); - if (m != null) { - data.writeInt(1); - for (int i = 0; i < 16; i++) { - data.writeFloat(m[i]); - } - } else { - data.writeInt(0); - } - flinger.transact(1015, data, null, 0); - data.recycle(); - } - } catch (RemoteException ex) { - Slog.e(LOG_TAG, "Failed to set color transform", ex); - } - } - } diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index f7bd04b08ede..577cada36c3e 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -1225,11 +1225,13 @@ public class AccountManagerService } finally { db.endTransaction(); } - sendAccountsChangedBroadcast(accounts.userId); } if (getUserManager().getUserInfo(accounts.userId).canHaveProfile()) { addAccountToLinkedRestrictedUsers(account, accounts.userId); } + + // Only send LOGIN_ACCOUNTS_CHANGED when the database changed. + sendAccountsChangedBroadcast(accounts.userId); return true; } @@ -1412,7 +1414,6 @@ public class AccountManagerService synchronized (accounts.cacheLock) { final SQLiteDatabase db = accounts.openHelper.getWritableDatabaseUserIsUnlocked(); db.beginTransaction(); - boolean isSuccessful = false; Account renamedAccount = new Account(newName, accountToRename.type); try { final long accountId = getAccountIdLocked(db, accountToRename); @@ -1425,54 +1426,51 @@ public class AccountManagerService values.put(ACCOUNTS_PREVIOUS_NAME, accountToRename.name); db.update(TABLE_ACCOUNTS, values, ACCOUNTS_ID + "=?", argsAccountId); db.setTransactionSuccessful(); - isSuccessful = true; logRecord(db, DebugDbHelper.ACTION_ACCOUNT_RENAME, TABLE_ACCOUNTS, accountId, accounts); } } finally { db.endTransaction(); - if (isSuccessful) { - /* - * Database transaction was successful. Clean up cached - * data associated with the account in the user profile. - */ - insertAccountIntoCacheLocked(accounts, renamedAccount); - /* - * Extract the data and token caches before removing the - * old account to preserve the user data associated with - * the account. - */ - HashMap<String, String> tmpData = accounts.userDataCache.get(accountToRename); - HashMap<String, String> tmpTokens = accounts.authTokenCache.get(accountToRename); - removeAccountFromCacheLocked(accounts, accountToRename); - /* - * Update the cached data associated with the renamed - * account. - */ - accounts.userDataCache.put(renamedAccount, tmpData); - accounts.authTokenCache.put(renamedAccount, tmpTokens); - accounts.previousNameCache.put( - renamedAccount, - new AtomicReference<String>(accountToRename.name)); - resultAccount = renamedAccount; - - int parentUserId = accounts.userId; - if (canHaveProfile(parentUserId)) { - /* - * Owner or system user account was renamed, rename the account for - * those users with which the account was shared. - */ - List<UserInfo> users = getUserManager().getUsers(true); - for (UserInfo user : users) { - if (user.isRestricted() - && (user.restrictedProfileParentId == parentUserId)) { - renameSharedAccountAsUser(accountToRename, newName, user.id); - } - } + } + /* + * Database transaction was successful. Clean up cached + * data associated with the account in the user profile. + */ + insertAccountIntoCacheLocked(accounts, renamedAccount); + /* + * Extract the data and token caches before removing the + * old account to preserve the user data associated with + * the account. + */ + HashMap<String, String> tmpData = accounts.userDataCache.get(accountToRename); + HashMap<String, String> tmpTokens = accounts.authTokenCache.get(accountToRename); + removeAccountFromCacheLocked(accounts, accountToRename); + /* + * Update the cached data associated with the renamed + * account. + */ + accounts.userDataCache.put(renamedAccount, tmpData); + accounts.authTokenCache.put(renamedAccount, tmpTokens); + accounts.previousNameCache.put( + renamedAccount, + new AtomicReference<String>(accountToRename.name)); + resultAccount = renamedAccount; + + int parentUserId = accounts.userId; + if (canHaveProfile(parentUserId)) { + /* + * Owner or system user account was renamed, rename the account for + * those users with which the account was shared. + */ + List<UserInfo> users = getUserManager().getUsers(true); + for (UserInfo user : users) { + if (user.isRestricted() + && (user.restrictedProfileParentId == parentUserId)) { + renameSharedAccountAsUser(accountToRename, newName, user.id); } - sendAccountsChangedBroadcast(accounts.userId); } } + sendAccountsChangedBroadcast(accounts.userId); } return resultAccount; } @@ -1653,7 +1651,7 @@ public class AccountManagerService } private boolean removeAccountInternal(UserAccounts accounts, Account account, int callingUid) { - int deleted; + boolean isChanged = false; boolean userUnlocked = isLocalUnlockedUser(accounts.userId); if (!userUnlocked) { Slog.i(TAG, "Removing account " + account + " while user "+ accounts.userId @@ -1663,25 +1661,38 @@ public class AccountManagerService final SQLiteDatabase db = userUnlocked ? accounts.openHelper.getWritableDatabaseUserIsUnlocked() : accounts.openHelper.getWritableDatabase(); - final long accountId = getAccountIdLocked(db, account); db.beginTransaction(); + // Set to a dummy value, this will only be used if the database + // transaction succeeds. + long accountId = -1; try { - deleted = db.delete(TABLE_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE - + "=?", new String[]{account.name, account.type}); - if (userUnlocked) { - // Delete from CE table - deleted = db.delete(CE_TABLE_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE - + "=?", new String[]{account.name, account.type}); + accountId = getAccountIdLocked(db, account); + if (accountId >= 0) { + db.delete( + TABLE_ACCOUNTS, + ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE + "=?", + new String[]{ account.name, account.type }); + if (userUnlocked) { + // Delete from CE table + db.delete( + CE_TABLE_ACCOUNTS, + ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE + "=?", + new String[]{ account.name, account.type }); + } + db.setTransactionSuccessful(); + isChanged = true; } - db.setTransactionSuccessful(); } finally { db.endTransaction(); } - removeAccountFromCacheLocked(accounts, account); - sendAccountsChangedBroadcast(accounts.userId); - String action = userUnlocked ? DebugDbHelper.ACTION_ACCOUNT_REMOVE - : DebugDbHelper.ACTION_ACCOUNT_REMOVE_DE; - logRecord(db, action, TABLE_ACCOUNTS, accountId, accounts); + if (isChanged) { + removeAccountFromCacheLocked(accounts, account); + // Only broadcast LOGIN_ACCOUNTS_CHANGED if a change occured. + sendAccountsChangedBroadcast(accounts.userId); + String action = userUnlocked ? DebugDbHelper.ACTION_ACCOUNT_REMOVE + : DebugDbHelper.ACTION_ACCOUNT_REMOVE_DE; + logRecord(db, action, TABLE_ACCOUNTS, accountId, accounts); + } } long id = Binder.clearCallingIdentity(); try { @@ -1698,7 +1709,7 @@ public class AccountManagerService } finally { Binder.restoreCallingIdentity(id); } - return (deleted > 0); + return isChanged; } @Override @@ -1922,6 +1933,7 @@ public class AccountManagerService if (account == null) { return; } + boolean isChanged = false; synchronized (accounts.cacheLock) { final SQLiteDatabase db = accounts.openHelper.getWritableDatabaseUserIsUnlocked(); db.beginTransaction(); @@ -1931,12 +1943,17 @@ public class AccountManagerService final long accountId = getAccountIdLocked(db, account); if (accountId >= 0) { final String[] argsAccountId = {String.valueOf(accountId)}; - db.update(CE_TABLE_ACCOUNTS, values, ACCOUNTS_ID + "=?", argsAccountId); - db.delete(CE_TABLE_AUTHTOKENS, AUTHTOKENS_ACCOUNTS_ID + "=?", argsAccountId); + db.update( + CE_TABLE_ACCOUNTS, values, ACCOUNTS_ID + "=?", argsAccountId); + db.delete( + CE_TABLE_AUTHTOKENS, AUTHTOKENS_ACCOUNTS_ID + "=?", argsAccountId); accounts.authTokenCache.remove(account); accounts.accountTokenCaches.remove(account); db.setTransactionSuccessful(); - + // If there is an account whose password will be updated and the database + // transactions succeed, then we say that a change has occured. Even if the + // new password is the same as the old and there were no authtokens to delete. + isChanged = true; String action = (password == null || password.length() == 0) ? DebugDbHelper.ACTION_CLEAR_PASSWORD : DebugDbHelper.ACTION_SET_PASSWORD; @@ -1944,8 +1961,11 @@ public class AccountManagerService } } finally { db.endTransaction(); + if (isChanged) { + // Send LOGIN_ACCOUNTS_CHANGED only if the something changed. + sendAccountsChangedBroadcast(accounts.userId); + } } - sendAccountsChangedBroadcast(accounts.userId); } } diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index a4fc251b70d8..c16fc62d1177 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -3074,7 +3074,7 @@ public final class ActivityStackSupervisor implements DisplayListener { final boolean nowVisible = allResumedActivitiesVisible(); for (int activityNdx = mStoppingActivities.size() - 1; activityNdx >= 0; --activityNdx) { ActivityRecord s = mStoppingActivities.get(activityNdx); - final boolean waitingVisible = mWaitingVisibleActivities.contains(s); + boolean waitingVisible = mWaitingVisibleActivities.contains(s); if (DEBUG_STATES) Slog.v(TAG, "Stopping " + s + ": nowVisible=" + nowVisible + " waitingVisible=" + waitingVisible + " finishing=" + s.finishing); if (waitingVisible && nowVisible) { @@ -3087,6 +3087,7 @@ public final class ActivityStackSupervisor implements DisplayListener { // hidden by the activities in front of it. if (DEBUG_STATES) Slog.v(TAG, "Before stopping, can hide: " + s); mWindowManager.setAppVisibility(s.appToken, false); + waitingVisible = false; } } if ((!waitingVisible || mService.isSleepingOrShuttingDownLocked()) && remove) { diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java index 92b55db40cd8..12310e390061 100644 --- a/services/core/java/com/android/server/connectivity/Tethering.java +++ b/services/core/java/com/android/server/connectivity/Tethering.java @@ -591,13 +591,13 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering synchronized (mPublicSync) { TetherState tetherState = mTetherStates.get(iface); if (tetherState == null) { - Log.e(TAG, "Tried to Tether an unknown iface :" + iface + ", ignoring"); + Log.e(TAG, "Tried to Tether an unknown iface: " + iface + ", ignoring"); return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE; } // Ignore the error status of the interface. If the interface is available, // the errors are referring to past tethering attempts anyway. if (tetherState.mLastState != IControlsTethering.STATE_AVAILABLE) { - Log.e(TAG, "Tried to Tether an unavailable iface :" + iface + ", ignoring"); + Log.e(TAG, "Tried to Tether an unavailable iface: " + iface + ", ignoring"); return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE; } tetherState.mStateMachine.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED); @@ -1018,15 +1018,29 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering */ class UpstreamNetworkCallback extends NetworkCallback { @Override + public void onAvailable(Network network) { + mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_CALLBACK, + UpstreamNetworkMonitor.EVENT_ON_AVAILABLE, 0, network); + } + + @Override + public void onCapabilitiesChanged(Network network, NetworkCapabilities newNc) { + mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_CALLBACK, + UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES, 0, + new NetworkState(null, null, newNc, network, null, null)); + } + + @Override public void onLinkPropertiesChanged(Network network, LinkProperties newLp) { - mTetherMasterSM.sendMessage( - TetherMasterSM.EVENT_UPSTREAM_LINKPROPERTIES_CHANGED, + mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_CALLBACK, + UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES, 0, new NetworkState(null, newLp, null, network, null, null)); } @Override public void onLost(Network network) { - mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_LOST, network); + mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_CALLBACK, + UpstreamNetworkMonitor.EVENT_ON_LOST, 0, network); } } @@ -1045,6 +1059,11 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering * could/should be moved here. */ class UpstreamNetworkMonitor { + static final int EVENT_ON_AVAILABLE = 1; + static final int EVENT_ON_CAPABILITIES = 2; + static final int EVENT_ON_LINKPROPERTIES = 3; + static final int EVENT_ON_LOST = 4; + final HashMap<Network, NetworkState> mNetworkMap = new HashMap<>(); NetworkCallback mDefaultNetworkCallback; NetworkCallback mDunTetheringCallback; @@ -1079,33 +1098,107 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering mNetworkMap.clear(); } - // Returns true if these updated LinkProperties pertain to the current - // upstream network interface, false otherwise (or if there is not - // currently any upstream tethering interface). - boolean processLinkPropertiesChanged(NetworkState networkState) { - if (networkState == null || - networkState.network == null || - networkState.linkProperties == null) { - return false; - } + NetworkState lookup(Network network) { + return (network != null) ? mNetworkMap.get(network) : null; + } - mNetworkMap.put(networkState.network, networkState); + NetworkState processCallback(int arg1, Object obj) { + switch (arg1) { + case EVENT_ON_AVAILABLE: { + final Network network = (Network) obj; + if (VDBG) { + Log.d(TAG, "EVENT_ON_AVAILABLE for " + network); + } + if (!mNetworkMap.containsKey(network)) { + mNetworkMap.put(network, + new NetworkState(null, null, null, network, null, null)); + } + + final ConnectivityManager cm = getConnectivityManager(); + + if (mDefaultNetworkCallback != null) { + cm.requestNetworkCapabilities(mDefaultNetworkCallback); + cm.requestLinkProperties(mDefaultNetworkCallback); + } - if (mCurrentUpstreamIface != null) { - for (String ifname : networkState.linkProperties.getAllInterfaceNames()) { - if (mCurrentUpstreamIface.equals(ifname)) { - return true; + // Requesting updates for mDunTetheringCallback is not + // necessary. Because it's a listen, it will already have + // heard all NetworkCapabilities and LinkProperties updates + // since UpstreamNetworkMonitor was started. Because we + // start UpstreamNetworkMonitor before chooseUpstreamType() + // is ever invoked (it can register a DUN request) this is + // mostly safe. However, if a DUN network is already up for + // some reason (unlikely, because DUN is restricted and, + // unless the DUN network is shared with another APN, only + // the system can request it and this is the only part of + // the system that requests it) we won't know its + // LinkProperties or NetworkCapabilities. + + return mNetworkMap.get(network); + } + case EVENT_ON_CAPABILITIES: { + final NetworkState ns = (NetworkState) obj; + if (!mNetworkMap.containsKey(ns.network)) { + // Ignore updates for networks for which we have not yet + // received onAvailable() - which should never happen - + // or for which we have already received onLost(). + return null; + } + if (VDBG) { + Log.d(TAG, String.format("EVENT_ON_CAPABILITIES for %s: %s", + ns.network, ns.networkCapabilities)); } + + final NetworkState prev = mNetworkMap.get(ns.network); + mNetworkMap.put(ns.network, + new NetworkState(null, prev.linkProperties, ns.networkCapabilities, + ns.network, null, null)); + return mNetworkMap.get(ns.network); } + case EVENT_ON_LINKPROPERTIES: { + final NetworkState ns = (NetworkState) obj; + if (!mNetworkMap.containsKey(ns.network)) { + // Ignore updates for networks for which we have not yet + // received onAvailable() - which should never happen - + // or for which we have already received onLost(). + return null; + } + if (VDBG) { + Log.d(TAG, String.format("EVENT_ON_LINKPROPERTIES for %s: %s", + ns.network, ns.linkProperties)); + } + + final NetworkState prev = mNetworkMap.get(ns.network); + mNetworkMap.put(ns.network, + new NetworkState(null, ns.linkProperties, prev.networkCapabilities, + ns.network, null, null)); + return mNetworkMap.get(ns.network); + } + case EVENT_ON_LOST: { + final Network network = (Network) obj; + if (VDBG) { + Log.d(TAG, "EVENT_ON_LOST for " + network); + } + return mNetworkMap.remove(network); + } + default: + return null; } - return false; } + } - void processNetworkLost(Network network) { - if (network != null) { - mNetworkMap.remove(network); + // Needed because the canonical source of upstream truth is just the + // upstream interface name, |mCurrentUpstreamIface|. This is ripe for + // future simplification, once the upstream Network is canonical. + boolean pertainsToCurrentUpstream(NetworkState ns) { + if (ns != null && ns.linkProperties != null && mCurrentUpstreamIface != null) { + for (String ifname : ns.linkProperties.getAllInterfaceNames()) { + if (mCurrentUpstreamIface.equals(ifname)) { + return true; + } } } + return false; } class TetherMasterSM extends StateMachine { @@ -1120,8 +1213,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering static final int CMD_RETRY_UPSTREAM = BASE_MASTER + 4; // Events from NetworkCallbacks that we process on the master state // machine thread on behalf of the UpstreamNetworkMonitor. - static final int EVENT_UPSTREAM_LINKPROPERTIES_CHANGED = BASE_MASTER + 5; - static final int EVENT_UPSTREAM_LOST = BASE_MASTER + 6; + static final int EVENT_UPSTREAM_CALLBACK = BASE_MASTER + 5; private State mInitialState; private State mTetherModeAliveState; @@ -1278,6 +1370,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering } protected void chooseUpstreamType(boolean tryCell) { + final ConnectivityManager cm = getConnectivityManager(); int upType = ConnectivityManager.TYPE_NONE; String iface = null; @@ -1292,8 +1385,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering } for (Integer netType : mUpstreamIfaceTypes) { - NetworkInfo info = - getConnectivityManager().getNetworkInfo(netType.intValue()); + NetworkInfo info = cm.getNetworkInfo(netType.intValue()); if ((info != null) && info.isConnected()) { upType = netType.intValue(); break; @@ -1334,9 +1426,9 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering break; } + Network network = null; if (upType != ConnectivityManager.TYPE_NONE) { - LinkProperties linkProperties = - getConnectivityManager().getLinkProperties(upType); + LinkProperties linkProperties = cm.getLinkProperties(upType); if (linkProperties != null) { // Find the interface with the default IPv4 route. It may be the // interface described by linkProperties, or one of the interfaces @@ -1353,7 +1445,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering } if (iface != null) { - Network network = getConnectivityManager().getNetworkForType(upType); + network = cm.getNetworkForType(upType); if (network == null) { Log.e(TAG, "No Network for upstream type " + upType + "!"); } @@ -1361,6 +1453,13 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering } } notifyTetheredOfNewUpstreamIface(iface); + NetworkState ns = mUpstreamNetworkMonitor.lookup(network); + if (ns != null && pertainsToCurrentUpstream(ns)) { + // If we already have NetworkState for this network examine + // it immediately, because there likely will be no second + // EVENT_ON_AVAILABLE (it was already received). + handleNewUpstreamNetworkState(ns); + } } protected void setDnsForwarders(final Network network, final LinkProperties lp) { @@ -1393,6 +1492,10 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering ifaceName); } } + + protected void handleNewUpstreamNetworkState(NetworkState ns) { + mIPv6TetheringCoordinator.updateUpstreamNetworkState(ns); + } } private final AtomicInteger mSimBcastGenerationNumber = new AtomicInteger(0); @@ -1582,24 +1685,55 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering chooseUpstreamType(mTryCell); mTryCell = !mTryCell; break; - case EVENT_UPSTREAM_LINKPROPERTIES_CHANGED: - NetworkState state = (NetworkState) message.obj; - if (mUpstreamNetworkMonitor.processLinkPropertiesChanged(state)) { - setDnsForwarders(state.network, state.linkProperties); - } else if (mCurrentUpstreamIface == null) { - // If we have no upstream interface, try to run through upstream - // selection again. If, for example, IPv4 connectivity has shown up - // after IPv6 (e.g., 464xlat became available) we want the chance to - // notice and act accordingly. - chooseUpstreamType(false); + case EVENT_UPSTREAM_CALLBACK: { + // First: always update local state about every network. + final NetworkState ns = mUpstreamNetworkMonitor.processCallback( + message.arg1, message.obj); + + if (ns == null || !pertainsToCurrentUpstream(ns)) { + // TODO: In future, this is where upstream evaluation and selection + // could be handled for notifications which include sufficient data. + // For example, after CONNECTIVITY_ACTION listening is removed, here + // is where we could observe a Wi-Fi network becoming available and + // passing validation. + if (mCurrentUpstreamIface == null) { + // If we have no upstream interface, try to run through upstream + // selection again. If, for example, IPv4 connectivity has shown up + // after IPv6 (e.g., 464xlat became available) we want the chance to + // notice and act accordingly. + chooseUpstreamType(false); + } + break; + } + + switch (message.arg1) { + case UpstreamNetworkMonitor.EVENT_ON_AVAILABLE: + // The default network changed, or DUN connected + // before this callback was processed. Updates + // for the current NetworkCapabilities and + // LinkProperties have been requested (default + // request) or are being sent shortly (DUN). Do + // nothing until they arrive; if no updates + // arrive there's nothing to do. + break; + case UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES: + handleNewUpstreamNetworkState(ns); + break; + case UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES: + setDnsForwarders(ns.network, ns.linkProperties); + handleNewUpstreamNetworkState(ns); + break; + case UpstreamNetworkMonitor.EVENT_ON_LOST: + // TODO: Re-evaluate possible upstreams. Currently upstream + // reevaluation is triggered via received CONNECTIVITY_ACTION + // broadcasts that result in being passed a + // TetherMasterSM.CMD_UPSTREAM_CHANGED. + break; + default: + break; } break; - case EVENT_UPSTREAM_LOST: - // TODO: Re-evaluate possible upstreams. Currently upstream reevaluation - // is triggered via received CONNECTIVITY_ACTION broadcasts that result - // in being passed a TetherMasterSM.CMD_UPSTREAM_CHANGED. - mUpstreamNetworkMonitor.processNetworkLost((Network) message.obj); - break; + } default: retValue = false; break; diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index 6a6570b97205..fec7ed1ff998 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -244,6 +244,7 @@ public final class DisplayManagerService extends SystemService { publishBinderService(Context.DISPLAY_SERVICE, new BinderService(), true /*allowIsolated*/); publishLocalService(DisplayManagerInternal.class, new LocalService()); + publishLocalService(DisplayTransformManager.class, new DisplayTransformManager()); } @Override diff --git a/services/core/java/com/android/server/display/DisplayTransformManager.java b/services/core/java/com/android/server/display/DisplayTransformManager.java new file mode 100644 index 000000000000..cfeae7bd6bd7 --- /dev/null +++ b/services/core/java/com/android/server/display/DisplayTransformManager.java @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.display; + +import android.opengl.Matrix; +import android.os.IBinder; +import android.os.Parcel; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.Slog; +import android.util.SparseArray; + +/** + * Manager for applying color transformations to the display. + */ +public class DisplayTransformManager { + + private static final String TAG = "DisplayTransformManager"; + + /** + * Color transform level used by Night display to tint the display red. + */ + public static final int LEVEL_COLOR_MATRIX_NIGHT_DISPLAY = 100; + /** + * Color transform level used by A11y services to make the display monochromatic. + */ + public static final int LEVEL_COLOR_MATRIX_GRAYSCALE = 200; + /** + * Color transform level used by A11y services to invert the display colors. + */ + public static final int LEVEL_COLOR_MATRIX_INVERT_COLOR = 300; + + private final SparseArray<float[]> mColorMatrix = new SparseArray<>(3); + + private int mDaltonizerMode = -1; + + /* package */ DisplayTransformManager() { + } + + /** + * Returns the color transform matrix set for a given level. + */ + public float[] getColorMatrix(int key) { + synchronized (mColorMatrix) { + return mColorMatrix.get(key); + } + } + + /** + * Sets and applies a current color transform matrix for a given level. + * <p> + * Note: all color transforms are first composed to a single matrix in ascending order based + * on level before being applied to the display. + * + * @param key the level used to identify and compose the color transform (low -> high) + * @param value the 4x4 color transform matrix (in column-major order), or {@code null} to + * remove the color transform matrix associated with the provided level + */ + public void setColorMatrix(int key, float[] value) { + if (value != null && value.length != 16) { + throw new IllegalArgumentException("Expected length: 16 (4x4 matrix)" + + ", actual length: " + value.length); + } + + synchronized (mColorMatrix) { + if (value != null) { + mColorMatrix.put(key, value); + } else { + mColorMatrix.remove(key); + } + + // Update the current color transform. + applyColorMatrix(computeColorMatrix()); + } + } + + /** + * Returns the composition of all current color matrices, or {@code null} if there are none. + */ + private float[] computeColorMatrix() { + synchronized (mColorMatrix) { + final int count = mColorMatrix.size(); + if (count == 0) { + return null; + } + + final float[][] result = new float[2][16]; + Matrix.setIdentityM(result[0], 0); + for (int i = 0; i < count; i++) { + float[] rhs = mColorMatrix.valueAt(i); + Matrix.multiplyMM(result[(i + 1) % 2], 0, result[i % 2], 0, rhs, 0); + } + return result[count % 2]; + } + } + + /** + * Returns the current Daltonization mode. + */ + public int getDaltonizerMode() { + return mDaltonizerMode; + } + + /** + * Sets the current Daltonization mode. This adjusts the color space to correct for or simulate + * various types of color blindness. + * + * @param mode the new Daltonization mode, or -1 to disable + */ + public void setDaltonizerMode(int mode) { + if (mDaltonizerMode != mode) { + mDaltonizerMode = mode; + applyDaltonizerMode(mode); + } + } + + /** + * Propagates the provided color transformation matrix to the SurfaceFlinger. + */ + private static void applyColorMatrix(float[] m) { + final IBinder flinger = ServiceManager.getService("SurfaceFlinger"); + if (flinger != null) { + final Parcel data = Parcel.obtain(); + data.writeInterfaceToken("android.ui.ISurfaceComposer"); + if (m != null) { + data.writeInt(1); + for (int i = 0; i < 16; i++) { + data.writeFloat(m[i]); + } + } else { + data.writeInt(0); + } + try { + flinger.transact(1015, data, null, 0); + } catch (RemoteException ex) { + Slog.e(TAG, "Failed to set color transform", ex); + } finally { + data.recycle(); + } + } + } + + /** + * Propagates the provided Daltonization mode to the SurfaceFlinger. + */ + private static void applyDaltonizerMode(int mode) { + final IBinder flinger = ServiceManager.getService("SurfaceFlinger"); + if (flinger != null) { + final Parcel data = Parcel.obtain(); + data.writeInterfaceToken("android.ui.ISurfaceComposer"); + data.writeInt(mode); + try { + flinger.transact(1014, data, null, 0); + } catch (RemoteException ex) { + Slog.e(TAG, "Failed to set Daltonizer mode", ex); + } finally { + data.recycle(); + } + } + } +} diff --git a/services/core/java/com/android/server/display/NightDisplayService.java b/services/core/java/com/android/server/display/NightDisplayService.java index 27abd1e8216d..006747bdfca2 100644 --- a/services/core/java/com/android/server/display/NightDisplayService.java +++ b/services/core/java/com/android/server/display/NightDisplayService.java @@ -47,9 +47,14 @@ public final class NightDisplayService extends SystemService private static final boolean DEBUG = false; /** - * Night mode ~= 3400 K. + * Night display ~= 3400 K. */ - private static final String MATRIX_NIGHT = "1,0,0,0,0,.754,0,0,0,0,.516,0,0,0,0,1"; + private static final float[] MATRIX_NIGHT = new float[] { + 1, 0, 0, 0, + 0, 0.754f, 0, 0, + 0, 0, 0.516f, 0, + 0, 0, 0, 1 + }; private int mCurrentUser = UserHandle.USER_NULL; private boolean mBootCompleted; @@ -159,9 +164,9 @@ public final class NightDisplayService extends SystemService } // Update the current color matrix. - final ContentResolver cr = getContext().getContentResolver(); - Secure.putStringForUser(cr, Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, - activated ? MATRIX_NIGHT : null, mCurrentUser); + final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class); + dtm.setColorMatrix(DisplayTransformManager.LEVEL_COLOR_MATRIX_NIGHT_DISPLAY, + activated ? MATRIX_NIGHT : null); } } diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java index 8589de1a1884..8f212db7d90a 100644 --- a/services/core/java/com/android/server/job/JobSchedulerService.java +++ b/services/core/java/com/android/server/job/JobSchedulerService.java @@ -1556,6 +1556,11 @@ public final class JobSchedulerService extends com.android.server.SystemService } } + if ((job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0) { + getContext().enforceCallingOrSelfPermission( + android.Manifest.permission.CONNECTIVITY_INTERNAL, TAG); + } + long ident = Binder.clearCallingIdentity(); try { return JobSchedulerService.this.schedule(job, uid); diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index f15fdd5304a1..b22a08484b8a 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -1241,6 +1241,24 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private void setNetworkTemplateEnabled(NetworkTemplate template, boolean enabled) { // TODO: reach into ConnectivityManager to proactively disable bringing // up this network, since we know that traffic will be blocked. + + if (template.getMatchRule() == MATCH_MOBILE_ALL) { + // If mobile data usage hits the limit or if the user resumes the data, we need to + // notify telephony. + final SubscriptionManager sm = SubscriptionManager.from(mContext); + final TelephonyManager tm = TelephonyManager.from(mContext); + + final int[] subIds = sm.getActiveSubscriptionIdList(); + for (int subId : subIds) { + final String subscriberId = tm.getSubscriberId(subId); + final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE, + TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true); + // Template is matched when subscriber id matches. + if (template.matches(probeIdent)) { + tm.setPolicyDataEnabled(enabled, subId); + } + } + } } /** diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java index 01b3dc28b50e..02c6472b2f88 100644 --- a/services/core/java/com/android/server/pm/OtaDexoptService.java +++ b/services/core/java/com/android/server/pm/OtaDexoptService.java @@ -213,9 +213,19 @@ public class OtaDexoptService extends IOtaDexopt.Stub { // Use the package manager install and install lock here for the OTA dex optimizer. PackageDexOptimizer optimizer = new OTADexoptPackageDexOptimizer( collectingInstaller, mPackageManagerService.mInstallLock, mContext); + // Make sure that core apps are optimized according to their own "reason". + // If the core apps are not preopted in the B OTA, and REASON_AB_OTA is not speed + // (by default is speed-profile) they will be interepreted/JITed. This in itself is not a + // problem as we will end up doing profile guided compilation. However, some core apps may + // be loaded by system server which doesn't JIT and we need to make sure we don't + // interpret-only + int compilationReason = nextPackage.coreApp + ? PackageManagerService.REASON_CORE_APP + : PackageManagerService.REASON_AB_OTA; + optimizer.performDexOpt(nextPackage, nextPackage.usesLibraryFiles, null /* ISAs */, false /* checkProfiles */, - getCompilerFilterForReason(PackageManagerService.REASON_AB_OTA)); + getCompilerFilterForReason(compilationReason)); mCommandsForCurrentPackage = collectingConnection.commands; if (mCommandsForCurrentPackage.isEmpty()) { diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 5980715c5358..78fa3a37dcf5 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -95,6 +95,7 @@ import static com.android.server.pm.InstructionSets.getPreferredInstructionSet; import static com.android.server.pm.InstructionSets.getPrimaryInstructionSet; import static com.android.server.pm.PackageManagerServiceCompilerMapping.getCompilerFilterForReason; import static com.android.server.pm.PackageManagerServiceCompilerMapping.getFullCompilerFilter; +import static com.android.server.pm.PackageManagerServiceCompilerMapping.getNonProfileGuidedCompilerFilter; import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_FAILURE; import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_SUCCESS; import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED; @@ -2800,7 +2801,7 @@ public class PackageManagerService extends IPackageManager.Stub { } } - int[] stats = performDexOpt(coreApps, false, + int[] stats = performDexOptUpgrade(coreApps, false, getCompilerFilterForReason(REASON_CORE_APP)); final int elapsedTimeSeconds = @@ -7324,7 +7325,7 @@ public class PackageManagerService extends IPackageManager.Stub { } final long startTime = System.nanoTime(); - final int[] stats = performDexOpt(pkgs, mIsPreNUpgrade /* showDialog */, + final int[] stats = performDexOptUpgrade(pkgs, mIsPreNUpgrade /* showDialog */, getCompilerFilterForReason(causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT)); final int elapsedTimeSeconds = @@ -7343,7 +7344,7 @@ public class PackageManagerService extends IPackageManager.Stub { * which are (in order) {@code numberOfPackagesOptimized}, {@code numberOfPackagesSkipped} * and {@code numberOfPackagesFailed}. */ - private int[] performDexOpt(List<PackageParser.Package> pkgs, boolean showDialog, + private int[] performDexOptUpgrade(List<PackageParser.Package> pkgs, boolean showDialog, String compilerFilter) { int numberOfPackagesVisited = 0; @@ -7377,6 +7378,19 @@ public class PackageManagerService extends IPackageManager.Stub { } } + // If the OTA updates a system app which was previously preopted to a non-preopted state + // the app might end up being verified at runtime. That's because by default the apps + // are verify-profile but for preopted apps there's no profile. + // Do a hacky check to ensure that if we have no profiles (a reasonable indication + // that before the OTA the app was preopted) the app gets compiled with a non-profile + // filter (by default interpret-only). + // Note that at this stage unused apps are already filtered. + if (isSystemApp(pkg) && + DexFile.isProfileGuidedCompilerFilter(compilerFilter) && + !Environment.getReferenceProfile(pkg.packageName).exists()) { + compilerFilter = getNonProfileGuidedCompilerFilter(compilerFilter); + } + // checkProfiles is false to avoid merging profiles during boot which // might interfere with background compilation (b/28612421). // Unfortunately this will also means that "pm.dexopt.boot=speed-profile" will diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java index 5f8cbbf0544b..730217db9501 100644 --- a/services/core/java/com/android/server/pm/ShortcutService.java +++ b/services/core/java/com/android/server/pm/ShortcutService.java @@ -1444,6 +1444,10 @@ public class ShortcutService extends IShortcutService.Stub { shortcut.getPackage().equals(shortcut.getActivity().getPackageName()), "Cannot publish shortcut: activity " + shortcut.getActivity() + " does not" + " belong to package " + shortcut.getPackage()); + Preconditions.checkState( + injectIsMainActivity(shortcut.getActivity(), shortcut.getUserId()), + "Cannot publish shortcut: activity " + shortcut.getActivity() + " is not" + + " main activity"); } if (!forUpdate) { diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index ca92b907686c..552803f47652 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -29,6 +29,7 @@ import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.UserHandle; +import android.text.TextUtils; import android.util.ArrayMap; import android.util.Slog; import android.view.KeyEvent; @@ -942,6 +943,20 @@ public class StatusBarManagerService extends IStatusBarService.Stub { + " token=" + tok.token); } pw.println(" mCurrentUserId=" + mCurrentUserId); + pw.println(" mIcons="); + for (String slot : mIcons.keySet()) { + pw.println(" "); + pw.print(slot); + pw.print(" -> "); + final StatusBarIcon icon = mIcons.get(slot); + pw.print(icon); + if (!TextUtils.isEmpty(icon.contentDescription)) { + pw.print(" \""); + pw.print(icon.contentDescription); + pw.print("\""); + } + pw.println(); + } } } } diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java index f570ff24ce36..d5460929960b 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java +++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java @@ -130,7 +130,6 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { assertExpectException(NullPointerException.class, "action must be set", () -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(new Intent())); - // same for add. assertExpectException( IllegalArgumentException.class, "Short label must be provided", () -> { ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id") @@ -139,6 +138,7 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { assertTrue(getManager().setDynamicShortcuts(list(si))); }); + // same for add. assertExpectException( IllegalArgumentException.class, "Short label must be provided", () -> { ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id") @@ -147,7 +147,6 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { assertTrue(getManager().addDynamicShortcuts(list(si))); }); - // same for add. assertExpectException(NullPointerException.class, "Intent must be provided", () -> { ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id") .setActivity(new ComponentName(getTestContext().getPackageName(), "s")) @@ -181,6 +180,33 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { .build(); assertTrue(getManager().addDynamicShortcuts(list(si))); }); + + // Now all activities are not main. + mMainActivityChecker = (component, userId) -> false; + + assertExpectException( + IllegalStateException.class, "is not main", () -> { + ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id") + .setActivity(new ComponentName(getTestContext(), "s")) + .build(); + assertTrue(getManager().setDynamicShortcuts(list(si))); + }); + // For add + assertExpectException( + IllegalStateException.class, "is not main", () -> { + ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id") + .setActivity(new ComponentName(getTestContext(), "s")) + .build(); + assertTrue(getManager().addDynamicShortcuts(list(si))); + }); + // For update + assertExpectException( + IllegalStateException.class, "is not main", () -> { + ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id") + .setActivity(new ComponentName(getTestContext(), "s")) + .build(); + assertTrue(getManager().updateShortcuts(list(si))); + }); } public void testShortcutInfoParcel() { diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 26ef0cbb87a5..df81d7f90008 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -5538,5 +5538,22 @@ public class TelephonyManager { } return 0; } + + /** + * Policy control of data connection. Usually used when data limit is passed. + * @param enabled True if enabling the data, otherwise disabling. + * @param subId sub id + * @hide + */ + public void setPolicyDataEnabled(boolean enabled, int subId) { + try { + ITelephony service = getITelephony(); + if (service != null) { + service.setPolicyDataEnabled(enabled, subId); + } + } catch (RemoteException e) { + Log.e(TAG, "Error calling ITelephony#setPolicyDataEnabled", e); + } + } } diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java index 8166e00f31cf..f01e4c0a8c69 100644 --- a/telephony/java/com/android/internal/telephony/DctConstants.java +++ b/telephony/java/com/android/internal/telephony/DctConstants.java @@ -105,6 +105,7 @@ public class DctConstants { public static final int EVENT_DEVICE_PROVISIONED_CHANGE = BASE + 43; public static final int EVENT_REDIRECTION_DETECTED = BASE + 44; public static final int EVENT_PCO_DATA_RECEIVED = BASE + 45; + public static final int EVENT_SET_CARRIER_DATA_ENABLED = BASE + 46; /***** Constants *****/ diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index 2168b0ea80db..167e1a739ca5 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -1158,4 +1158,12 @@ interface ITelephony { * @hide */ long getVtDataUsage(); + + /** + * Policy control of data connection. Usually used when data limit is passed. + * @param enabled True if enabling the data, otherwise disabling. + * @param subId Subscription index + * @hide + */ + void setPolicyDataEnabled(boolean enabled, int subId); } diff --git a/tests/UiBench/src/com/android/test/uibench/ShadowGridActivity.java b/tests/UiBench/src/com/android/test/uibench/ShadowGridActivity.java index d32f0716fe98..88847eed17fa 100644 --- a/tests/UiBench/src/com/android/test/uibench/ShadowGridActivity.java +++ b/tests/UiBench/src/com/android/test/uibench/ShadowGridActivity.java @@ -23,19 +23,22 @@ import android.view.View; import android.widget.ArrayAdapter; public class ShadowGridActivity extends AppCompatActivity { + public static class NoDividerListFragment extends ListFragment { + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + getListView().setDivider(null); + } + }; + + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); FragmentManager fm = getSupportFragmentManager(); if (fm.findFragmentById(android.R.id.content) == null) { - ListFragment listFragment = new ListFragment() { - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - getListView().setDivider(null); - } - }; + ListFragment listFragment = new NoDividerListFragment(); listFragment.setListAdapter(new ArrayAdapter<>(this, R.layout.card_row, R.id.card_text, TextUtils.buildSimpleStringList())); |