Merge "Add contentInsetStartWithNavigation/EndWithActions" into nyc-dev
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 66e0ada..10259be 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1581,14 +1581,6 @@
= "android.intent.extra.UNINSTALL_ALL_USERS";
/**
- * Specified when the uninstall confirmation dialog is not required to be shown.
- * Use with {@link #ACTION_UNINSTALL_PACKAGE}
- * @hide
- */
- public static final String EXTRA_SKIP_UNINSTALL_CONFIRMATION =
- "android.intent.extra.SKIP_UNINSTALL_CONFIRMATION";
-
- /**
* A string associated with a {@link #ACTION_UPGRADE_SETUP} activity
* describing the last run version of the platform that was setup.
* @hide
diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java
index 31b2f96..df57639 100644
--- a/core/java/com/android/internal/view/menu/MenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/MenuBuilder.java
@@ -65,7 +65,6 @@
private final Context mContext;
private final Resources mResources;
- private final boolean mShowCascadingMenus;
/**
* Whether the shortcuts should be qwerty-accessible. Use isQwertyMode()
@@ -188,9 +187,6 @@
public MenuBuilder(Context context) {
mContext = context;
mResources = context.getResources();
- mShowCascadingMenus = context.getResources().getBoolean(
- com.android.internal.R.bool.config_enableCascadingSubmenus);
-
mItems = new ArrayList<MenuItemImpl>();
mVisibleItems = new ArrayList<MenuItemImpl>();
@@ -915,10 +911,6 @@
close(true /* closeAllMenus */);
}
} else if (itemImpl.hasSubMenu() || providerHasSubMenu) {
- if (!mShowCascadingMenus) {
- close(false /* closeAllMenus */);
- }
-
if (!itemImpl.hasSubMenu()) {
itemImpl.setSubMenu(new SubMenuBuilder(getContext(), this, itemImpl));
}
diff --git a/core/java/com/android/internal/view/menu/StandardMenuPopup.java b/core/java/com/android/internal/view/menu/StandardMenuPopup.java
index 2cb224e..8ced36f 100644
--- a/core/java/com/android/internal/view/menu/StandardMenuPopup.java
+++ b/core/java/com/android/internal/view/menu/StandardMenuPopup.java
@@ -240,7 +240,10 @@
mTreeObserver = null;
}
mShownAnchorView.removeOnAttachStateChangeListener(mAttachStateChangeListener);
- mOnDismissListener.onDismiss();
+
+ if (mOnDismissListener != null) {
+ mOnDismissListener.onDismiss();
+ }
}
@Override
@@ -265,6 +268,13 @@
subPopup.setPresenterCallback(mPresenterCallback);
subPopup.setForceShowIcon(mAdapter.getForceShowIcon());
+ // Pass responsibility for handling onDismiss to the submenu.
+ subPopup.setOnDismissListener(mOnDismissListener);
+ mOnDismissListener = null;
+
+ // Close this menu popup to make room for the submenu popup.
+ dismiss();
+
// Show the new sub-menu popup at the same location as this popup.
if (subPopup.tryShow(mXOffset, mYOffset)) {
if (mPresenterCallback != null) {
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 6ecaa1f..892b3d5 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2497,4 +2497,8 @@
<!-- True if the device supports at least one form of multi-window.
E.g. freeform, split-screen, picture-in-picture. -->
<bool name="config_supportsMultiWindow">true</bool>
+
+ <!-- True if the device requires AppWidgetService even if it does not have
+ the PackageManager.FEATURE_APP_WIDGETS feature -->
+ <bool name="config_enableAppWidgetService">false</bool>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6526571..694e934 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -307,6 +307,7 @@
<java-symbol type="bool" name="config_supportsMultiWindow" />
<java-symbol type="bool" name="config_guestUserEphemeral" />
<java-symbol type="bool" name="config_localDisplaysMirrorContent" />
+ <java-symbol type="bool" name="config_enableAppWidgetService" />
<java-symbol type="string" name="config_defaultPictureInPictureBounds" />
<java-symbol type="integer" name="config_wifi_framework_5GHz_preference_boost_threshold" />
<java-symbol type="integer" name="config_wifi_framework_5GHz_preference_boost_factor" />
diff --git a/libs/hwui/BakedOpState.cpp b/libs/hwui/BakedOpState.cpp
index 85903654..b70d586 100644
--- a/libs/hwui/BakedOpState.cpp
+++ b/libs/hwui/BakedOpState.cpp
@@ -108,5 +108,63 @@
clippedBounds.doIntersect(clipRect->rect);
}
+BakedOpState* BakedOpState::tryConstruct(LinearAllocator& allocator,
+ Snapshot& snapshot, const RecordedOp& recordedOp) {
+ if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
+ BakedOpState* bakedState = allocator.create_trivial<BakedOpState>(
+ allocator, snapshot, recordedOp, false);
+ if (bakedState->computedState.clippedBounds.isEmpty()) {
+ // bounds are empty, so op is rejected
+ allocator.rewindIfLastAlloc(bakedState);
+ return nullptr;
+ }
+ return bakedState;
+}
+
+BakedOpState* BakedOpState::tryConstructUnbounded(LinearAllocator& allocator,
+ Snapshot& snapshot, const RecordedOp& recordedOp) {
+ if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
+ return allocator.create_trivial<BakedOpState>(allocator, snapshot, recordedOp);
+}
+
+BakedOpState* BakedOpState::tryStrokeableOpConstruct(LinearAllocator& allocator,
+ Snapshot& snapshot, const RecordedOp& recordedOp, StrokeBehavior strokeBehavior) {
+ if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
+ bool expandForStroke = (strokeBehavior == StrokeBehavior::StyleDefined)
+ ? (recordedOp.paint && recordedOp.paint->getStyle() != SkPaint::kFill_Style)
+ : true;
+
+ BakedOpState* bakedState = allocator.create_trivial<BakedOpState>(
+ allocator, snapshot, recordedOp, expandForStroke);
+ if (bakedState->computedState.clippedBounds.isEmpty()) {
+ // bounds are empty, so op is rejected
+ // NOTE: this won't succeed if a clip was allocated
+ allocator.rewindIfLastAlloc(bakedState);
+ return nullptr;
+ }
+ return bakedState;
+}
+
+BakedOpState* BakedOpState::tryShadowOpConstruct(LinearAllocator& allocator,
+ Snapshot& snapshot, const ShadowOp* shadowOpPtr) {
+ if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
+
+ // clip isn't empty, so construct the op
+ return allocator.create_trivial<BakedOpState>(allocator, snapshot, shadowOpPtr);
+}
+
+BakedOpState* BakedOpState::directConstruct(LinearAllocator& allocator,
+ const ClipRect* clip, const Rect& dstRect, const RecordedOp& recordedOp) {
+ return allocator.create_trivial<BakedOpState>(clip, dstRect, recordedOp);
+}
+
+void BakedOpState::setupOpacity(const SkPaint* paint) {
+ computedState.opaqueOverClippedBounds = computedState.transform.isSimple()
+ && computedState.clipState->mode == ClipMode::Rectangle
+ && MathUtils::areEqual(alpha, 1.0f)
+ && !roundRectClipState
+ && PaintUtils::isOpaquePaint(paint);
+}
+
} // namespace uirenderer
} // namespace android
diff --git a/libs/hwui/BakedOpState.h b/libs/hwui/BakedOpState.h
index 4e3cb8a..e1441fc 100644
--- a/libs/hwui/BakedOpState.h
+++ b/libs/hwui/BakedOpState.h
@@ -93,6 +93,7 @@
Rect clippedBounds;
int clipSideFlags = 0;
const SkPath* localProjectionPathMask = nullptr;
+ bool opaqueOverClippedBounds = false;
};
/**
@@ -103,23 +104,10 @@
class BakedOpState {
public:
static BakedOpState* tryConstruct(LinearAllocator& allocator,
- Snapshot& snapshot, const RecordedOp& recordedOp) {
- if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
- BakedOpState* bakedState = allocator.create_trivial<BakedOpState>(
- allocator, snapshot, recordedOp, false);
- if (bakedState->computedState.clippedBounds.isEmpty()) {
- // bounds are empty, so op is rejected
- allocator.rewindIfLastAlloc(bakedState);
- return nullptr;
- }
- return bakedState;
- }
+ Snapshot& snapshot, const RecordedOp& recordedOp);
static BakedOpState* tryConstructUnbounded(LinearAllocator& allocator,
- Snapshot& snapshot, const RecordedOp& recordedOp) {
- if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
- return allocator.create_trivial<BakedOpState>(allocator, snapshot, recordedOp);
- }
+ Snapshot& snapshot, const RecordedOp& recordedOp);
enum class StrokeBehavior {
// stroking is forced, regardless of style on paint (such as for lines)
@@ -129,35 +117,16 @@
};
static BakedOpState* tryStrokeableOpConstruct(LinearAllocator& allocator,
- Snapshot& snapshot, const RecordedOp& recordedOp, StrokeBehavior strokeBehavior) {
- if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
- bool expandForStroke = (strokeBehavior == StrokeBehavior::StyleDefined)
- ? (recordedOp.paint && recordedOp.paint->getStyle() != SkPaint::kFill_Style)
- : true;
-
- BakedOpState* bakedState = allocator.create_trivial<BakedOpState>(
- allocator, snapshot, recordedOp, expandForStroke);
- if (bakedState->computedState.clippedBounds.isEmpty()) {
- // bounds are empty, so op is rejected
- // NOTE: this won't succeed if a clip was allocated
- allocator.rewindIfLastAlloc(bakedState);
- return nullptr;
- }
- return bakedState;
- }
+ Snapshot& snapshot, const RecordedOp& recordedOp, StrokeBehavior strokeBehavior);
static BakedOpState* tryShadowOpConstruct(LinearAllocator& allocator,
- Snapshot& snapshot, const ShadowOp* shadowOpPtr) {
- if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
-
- // clip isn't empty, so construct the op
- return allocator.create_trivial<BakedOpState>(allocator, snapshot, shadowOpPtr);
- }
+ Snapshot& snapshot, const ShadowOp* shadowOpPtr);
static BakedOpState* directConstruct(LinearAllocator& allocator,
- const ClipRect* clip, const Rect& dstRect, const RecordedOp& recordedOp) {
- return allocator.create_trivial<BakedOpState>(clip, dstRect, recordedOp);
- }
+ const ClipRect* clip, const Rect& dstRect, const RecordedOp& recordedOp);
+
+ // Set opaqueOverClippedBounds. If this method isn't called, the op is assumed translucent.
+ void setupOpacity(const SkPaint* paint);
// computed state:
ResolvedRenderState computedState;
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index b1314fe..b18836f 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -481,12 +481,17 @@
* Defers an unmergeable, strokeable op, accounting correctly
* for paint's style on the bounds being computed.
*/
-const BakedOpState* FrameBuilder::deferStrokeableOp(const RecordedOp& op, batchid_t batchId,
+BakedOpState* FrameBuilder::deferStrokeableOp(const RecordedOp& op, batchid_t batchId,
BakedOpState::StrokeBehavior strokeBehavior) {
// Note: here we account for stroke when baking the op
BakedOpState* bakedState = BakedOpState::tryStrokeableOpConstruct(
mAllocator, *mCanvasState.writableSnapshot(), op, strokeBehavior);
if (!bakedState) return nullptr; // quick rejected
+
+ if (op.opId == RecordedOpId::RectOp && op.paint->getStyle() != SkPaint::kStroke_Style) {
+ bakedState->setupOpacity(op.paint);
+ }
+
currentLayer().deferUnmergeableOp(mAllocator, bakedState, batchId);
return bakedState;
}
@@ -516,6 +521,7 @@
void FrameBuilder::deferBitmapOp(const BitmapOp& op) {
BakedOpState* bakedState = tryBakeOpState(op);
if (!bakedState) return; // quick rejected
+ bakedState->setupOpacity(op.paint);
// Don't merge non-simply transformed or neg scale ops, SET_TEXTURE doesn't handle rotation
// Don't merge A8 bitmaps - the paint's color isn't compared by mergeId, or in
diff --git a/libs/hwui/FrameBuilder.h b/libs/hwui/FrameBuilder.h
index 0b7a606..02c05cb 100644
--- a/libs/hwui/FrameBuilder.h
+++ b/libs/hwui/FrameBuilder.h
@@ -201,7 +201,7 @@
return mAllocator.create<SkPath>();
}
- const BakedOpState* deferStrokeableOp(const RecordedOp& op, batchid_t batchId,
+ BakedOpState* deferStrokeableOp(const RecordedOp& op, batchid_t batchId,
BakedOpState::StrokeBehavior strokeBehavior = BakedOpState::StrokeBehavior::StyleDefined);
/**
diff --git a/libs/hwui/LayerBuilder.cpp b/libs/hwui/LayerBuilder.cpp
index e6a95ff..eea11bf 100644
--- a/libs/hwui/LayerBuilder.cpp
+++ b/libs/hwui/LayerBuilder.cpp
@@ -236,6 +236,21 @@
mClearRects.push_back(rect);
}
+void LayerBuilder::onDeferOp(LinearAllocator& allocator, const BakedOpState* bakedState) {
+ if (bakedState->op->opId != RecordedOpId::CopyToLayerOp) {
+ // First non-CopyToLayer, so stop stashing up layer clears for unclipped save layers,
+ // and issue them together in one draw.
+ flushLayerClears(allocator);
+
+ if (CC_UNLIKELY(activeUnclippedSaveLayers.empty()
+ && bakedState->computedState.opaqueOverClippedBounds
+ && bakedState->computedState.clippedBounds.contains(repaintRect))) {
+ // discard all deferred drawing ops, since new one will occlude them
+ clear();
+ }
+ }
+}
+
void LayerBuilder::flushLayerClears(LinearAllocator& allocator) {
if (CC_UNLIKELY(!mClearRects.empty())) {
const int vertCount = mClearRects.size() * 4;
@@ -270,11 +285,7 @@
void LayerBuilder::deferUnmergeableOp(LinearAllocator& allocator,
BakedOpState* op, batchid_t batchId) {
- if (batchId != OpBatchType::CopyToLayer) {
- // if first op after one or more unclipped saveLayers, flush the layer clears
- flushLayerClears(allocator);
- }
-
+ onDeferOp(allocator, op);
OpBatch* targetBatch = mBatchLookup[batchId];
size_t insertBatchIndex = mBatches.size();
@@ -295,10 +306,7 @@
void LayerBuilder::deferMergeableOp(LinearAllocator& allocator,
BakedOpState* op, batchid_t batchId, mergeid_t mergeId) {
- if (batchId != OpBatchType::CopyToLayer) {
- // if first op after one or more unclipped saveLayers, flush the layer clears
- flushLayerClears(allocator);
- }
+ onDeferOp(allocator, op);
MergingOpBatch* targetBatch = nullptr;
// Try to merge with any existing batch with same mergeId
@@ -348,6 +356,14 @@
}
}
+void LayerBuilder::clear() {
+ mBatches.clear();
+ for (int i = 0; i < OpBatchType::Count; i++) {
+ mBatchLookup[i] = nullptr;
+ mMergingBatchLookup[i].clear();
+ }
+}
+
void LayerBuilder::dump() const {
ALOGD("LayerBuilder %p, %ux%u buffer %p, blo %p, rn %p (%s)",
this, width, height, offscreenBuffer, beginLayerOp,
diff --git a/libs/hwui/LayerBuilder.h b/libs/hwui/LayerBuilder.h
index 4a7ca2d..4de432c 100644
--- a/libs/hwui/LayerBuilder.h
+++ b/libs/hwui/LayerBuilder.h
@@ -100,9 +100,7 @@
return mBatches.empty();
}
- void clear() {
- mBatches.clear();
- }
+ void clear();
void dump() const;
@@ -117,6 +115,7 @@
// list of deferred CopyFromLayer ops, to be deferred upon encountering EndUnclippedLayerOps
std::vector<BakedOpState*> activeUnclippedSaveLayers;
private:
+ void onDeferOp(LinearAllocator& allocator, const BakedOpState* bakedState);
void flushLayerClears(LinearAllocator& allocator);
std::vector<BatchBase*> mBatches;
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index e97aaa6..ba22f91 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -216,6 +216,80 @@
<< "Expect number of ops = 2 * loop count";
}
+RENDERTHREAD_TEST(FrameBuilder, avoidOverdraw_rects) {
+ class AvoidOverdrawRectsTestRenderer : public TestRendererBase {
+ public:
+ void onRectOp(const RectOp& op, const BakedOpState& state) override {
+ EXPECT_EQ(mIndex++, 0) << "Should be one rect";
+ EXPECT_EQ(Rect(10, 10, 190, 190), op.unmappedBounds)
+ << "Last rect should occlude others.";
+ }
+ };
+ auto node = TestUtils::createNode(0, 0, 200, 200,
+ [](RenderProperties& props, RecordingCanvas& canvas) {
+ canvas.drawRect(0, 0, 200, 200, SkPaint());
+ canvas.drawRect(0, 0, 200, 200, SkPaint());
+ canvas.drawRect(10, 10, 190, 190, SkPaint());
+ });
+
+ // Damage (and therefore clip) is same as last draw, subset of renderable area.
+ // This means last op occludes other contents, and they'll be rejected to avoid overdraw.
+ SkRect damageRect = SkRect::MakeLTRB(10, 10, 190, 190);
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, damageRect, 200, 200,
+ TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
+
+ EXPECT_EQ(3u, node->getDisplayList()->getOps().size())
+ << "Recording must not have rejected ops, in order for this test to be valid";
+
+ AvoidOverdrawRectsTestRenderer renderer;
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+ EXPECT_EQ(1, renderer.getIndex()) << "Expect exactly one op";
+}
+
+RENDERTHREAD_TEST(FrameBuilder, avoidOverdraw_bitmaps) {
+ static SkBitmap opaqueBitmap = TestUtils::createSkBitmap(50, 50,
+ SkColorType::kRGB_565_SkColorType);
+ static SkBitmap transpBitmap = TestUtils::createSkBitmap(50, 50,
+ SkColorType::kAlpha_8_SkColorType);
+ class AvoidOverdrawBitmapsTestRenderer : public TestRendererBase {
+ public:
+ void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override {
+ EXPECT_LT(mIndex++, 2) << "Should be two bitmaps";
+ switch(mIndex++) {
+ case 0:
+ EXPECT_EQ(opaqueBitmap.pixelRef(), op.bitmap->pixelRef());
+ break;
+ case 1:
+ EXPECT_EQ(transpBitmap.pixelRef(), op.bitmap->pixelRef());
+ break;
+ default:
+ ADD_FAILURE() << "Only two ops expected.";
+ }
+ }
+ };
+
+ auto node = TestUtils::createNode(0, 0, 50, 50,
+ [](RenderProperties& props, RecordingCanvas& canvas) {
+ canvas.drawRect(0, 0, 50, 50, SkPaint());
+ canvas.drawRect(0, 0, 50, 50, SkPaint());
+ canvas.drawBitmap(transpBitmap, 0, 0, nullptr);
+
+ // only the below draws should remain, since they're
+ canvas.drawBitmap(opaqueBitmap, 0, 0, nullptr);
+ canvas.drawBitmap(transpBitmap, 0, 0, nullptr);
+ });
+
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(50, 50), 50, 50,
+ TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
+
+ EXPECT_EQ(5u, node->getDisplayList()->getOps().size())
+ << "Recording must not have rejected ops, in order for this test to be valid";
+
+ AvoidOverdrawBitmapsTestRenderer renderer;
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+ EXPECT_EQ(2, renderer.getIndex()) << "Expect exactly one op";
+}
+
RENDERTHREAD_TEST(FrameBuilder, clippedMerging) {
class ClippedMergingTestRenderer : public TestRendererBase {
public:
diff --git a/libs/hwui/utils/PaintUtils.h b/libs/hwui/utils/PaintUtils.h
index db53713..4faab9a 100644
--- a/libs/hwui/utils/PaintUtils.h
+++ b/libs/hwui/utils/PaintUtils.h
@@ -67,6 +67,21 @@
&& getXfermode(paint.getXfermode()) == SkXfermode::kSrcOver_Mode;
}
+ static bool isOpaquePaint(const SkPaint* paint) {
+ if (!paint) return true; // default (paintless) behavior is SrcOver, black
+
+ if (paint->getAlpha() != 0xFF
+ || PaintUtils::isBlendedShader(paint->getShader())
+ || PaintUtils::isBlendedColorFilter(paint->getColorFilter())) {
+ return false;
+ }
+
+ // Only let simple srcOver / src blending modes declare opaque, since behavior is clear.
+ SkXfermode::Mode mode = getXfermode(paint->getXfermode());
+ return mode == SkXfermode::Mode::kSrcOver_Mode
+ || mode == SkXfermode::Mode::kSrc_Mode;
+ }
+
static bool isBlendedShader(const SkShader* shader) {
if (shader == nullptr) {
return false;
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 45008dc..9e2f1167 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -165,6 +165,7 @@
public void onStart() {
mMountService = new MountService(getContext());
publishBinderService("mount", mMountService);
+ mMountService.start();
}
@Override
@@ -430,9 +431,13 @@
= { "password", "default", "pattern", "pin" };
private final Context mContext;
+
private final NativeDaemonConnector mConnector;
private final NativeDaemonConnector mCryptConnector;
+ private final Thread mConnectorThread;
+ private final Thread mCryptConnectorThread;
+
private volatile boolean mSystemReady = false;
private volatile boolean mBootCompleted = false;
private volatile boolean mDaemonConnected = false;
@@ -1494,17 +1499,13 @@
null);
mConnector.setDebug(true);
mConnector.setWarnIfHeld(mLock);
-
- Thread thread = new Thread(mConnector, VOLD_TAG);
- thread.start();
+ mConnectorThread = new Thread(mConnector, VOLD_TAG);
// Reuse parameters from first connector since they are tested and safe
mCryptConnector = new NativeDaemonConnector(this, "cryptd",
MAX_CONTAINERS * 2, CRYPTD_TAG, 25, null);
mCryptConnector.setDebug(true);
-
- Thread crypt_thread = new Thread(mCryptConnector, CRYPTD_TAG);
- crypt_thread.start();
+ mCryptConnectorThread = new Thread(mCryptConnector, CRYPTD_TAG);
final IntentFilter userFilter = new IntentFilter();
userFilter.addAction(Intent.ACTION_USER_ADDED);
@@ -1521,6 +1522,11 @@
}
}
+ private void start() {
+ mConnectorThread.start();
+ mCryptConnectorThread.start();
+ }
+
private void systemReady() {
mSystemReady = true;
mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 6df36e4..7f0da1e 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -31,7 +31,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
@@ -924,12 +923,12 @@
}
// Don't call them within the mRestrictionsLock.
synchronized (mPackagesLock) {
- if (globalChanged) {
- writeUserListLP();
- }
if (localChanged) {
writeUserLP(getUserDataNoChecks(userId));
}
+ if (globalChanged) {
+ writeUserListLP();
+ }
}
synchronized (mRestrictionsLock) {
@@ -1491,8 +1490,8 @@
updateUserIds();
initDefaultGuestRestrictions();
- writeUserListLP();
writeUserLP(userData);
+ writeUserListLP();
}
private String getOwnerName() {
@@ -1542,8 +1541,10 @@
serializer.attribute(null, ATTR_CREATION_TIME, Long.toString(userInfo.creationTime));
serializer.attribute(null, ATTR_LAST_LOGGED_IN_TIME,
Long.toString(userInfo.lastLoggedInTime));
- serializer.attribute(null, ATTR_LAST_LOGGED_IN_FINGERPRINT,
- userInfo.lastLoggedInFingerprint);
+ if (userInfo.lastLoggedInFingerprint != null) {
+ serializer.attribute(null, ATTR_LAST_LOGGED_IN_FINGERPRINT,
+ userInfo.lastLoggedInFingerprint);
+ }
if (userInfo.iconPath != null) {
serializer.attribute(null, ATTR_ICON_PATH, userInfo.iconPath);
}
@@ -1599,7 +1600,7 @@
serializer.endDocument();
userFile.finishWrite(fos);
} catch (Exception ioe) {
- Slog.e(LOG_TAG, "Error writing user info " + userData.info.id + "\n" + ioe);
+ Slog.e(LOG_TAG, "Error writing user info " + userData.info.id, ioe);
userFile.failWrite(fos);
}
}
@@ -1944,6 +1945,7 @@
userData.info = userInfo;
mUsers.put(userId, userData);
}
+ writeUserLP(userData);
writeUserListLP();
if (parent != null) {
if (isManagedProfile) {
@@ -2217,13 +2219,13 @@
mCachedEffectiveUserRestrictions.remove(userHandle);
mDevicePolicyLocalUserRestrictions.remove(userHandle);
}
- // Remove user file
- AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + XML_SUFFIX));
- userFile.delete();
// Update the user list
synchronized (mPackagesLock) {
writeUserListLP();
}
+ // Remove user file
+ AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + XML_SUFFIX));
+ userFile.delete();
updateUserIds();
File userDir = Environment.getUserSystemDirectory(userHandle);
File renamedUserDir = Environment.getUserSystemDirectory(UserHandle.USER_NULL - userHandle);
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 14efc27..0a4effb 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1025,7 +1025,8 @@
mSystemServiceManager.startService(BACKUP_MANAGER_SERVICE_CLASS);
}
- if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS)) {
+ if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS)
+ || context.getResources().getBoolean(R.bool.config_enableAppWidgetService)) {
mSystemServiceManager.startService(APPWIDGET_SERVICE_CLASS);
}