diff options
43 files changed, 334 insertions, 156 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index bc6e9cd0ab7e..0ff3215e1271 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -6416,17 +6416,7 @@ public class Activity extends ContextThemeWrapper */ @Deprecated public boolean requestVisibleBehind(boolean visible) { - if (!mResumed) { - // Do not permit paused or stopped activities to do this. - visible = false; - } - try { - mVisibleBehind = ActivityManager.getService() - .requestVisibleBehind(mToken, visible) && visible; - } catch (RemoteException e) { - mVisibleBehind = false; - } - return mVisibleBehind; + return false; } /** diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index f398c8dc9d6a..aca2d9177835 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -360,6 +360,13 @@ public class ActivityManager { FIRST_START_NON_FATAL_ERROR_CODE + 1; /** + * Result for IActivityManaqer.startActivity: a new activity start was aborted. Never returned + * externally. + * @hide + */ + public static final int START_ABORTED = FIRST_START_NON_FATAL_ERROR_CODE + 2; + + /** * Flag for IActivityManaqer.startActivity: do special start mode where * a new activity is launched only if it is needed. * @hide diff --git a/core/java/android/app/ProgressDialog.java b/core/java/android/app/ProgressDialog.java index 8ec9622ebe34..8a083ebcd7e9 100644 --- a/core/java/android/app/ProgressDialog.java +++ b/core/java/android/app/ProgressDialog.java @@ -42,8 +42,12 @@ import java.text.NumberFormat; * * <p>The progress range is 0 to {@link #getMax() max}.</p> * - * @deprecated Use a progress indicator such as ProgressBar inline inside of - * an activity rather than using this modal dialog. + * @deprecated <code>ProgressDialog</code> is a modal dialog, which prevents the + * user from interacting with the app. Instead of using this class, you should + * use a progress indicator like {@link android.widget.ProgressBar}, which can + * be embedded in your app's UI. Alternatively, you can use a + * <a href="/guide/topics/ui/notifiers/notifications.html">notification</a> + * to inform the user of the task's progress. */ @Deprecated public class ProgressDialog extends AlertDialog { diff --git a/core/java/android/content/pm/LauncherActivityInfo.java b/core/java/android/content/pm/LauncherActivityInfo.java index 358787e66428..e9c958857d5c 100644 --- a/core/java/android/content/pm/LauncherActivityInfo.java +++ b/core/java/android/content/pm/LauncherActivityInfo.java @@ -20,12 +20,10 @@ import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources; -import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.UserHandle; import android.os.UserManager; import android.util.DisplayMetrics; -import android.util.Log; /** * A representation of an activity that can belong to this user or a managed @@ -173,12 +171,6 @@ public class LauncherActivityInfo { public Drawable getBadgedIcon(int density) { Drawable originalIcon = getIcon(density); - if (originalIcon instanceof BitmapDrawable) { - // TODO: Go through LauncherAppsService - return mPm.getUserBadgedIcon(originalIcon, mUser); - } else { - Log.e(TAG, "Unable to create badged icon for " + mActivityInfo); - } - return originalIcon; + return mPm.getUserBadgedIcon(originalIcon, mUser); } } diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java index ed41e79e2c6c..aa9562ff040f 100644 --- a/core/java/android/content/pm/LauncherApps.java +++ b/core/java/android/content/pm/LauncherApps.java @@ -608,15 +608,15 @@ public class LauncherApps { } /** - * Get {@link ApplicationInfo} for a profile + * Returns {@link ApplicationInfo} about an application installed for a specific user profile. * * @param packageName The package name of the application * @param flags Additional option flags {@link PackageManager#getApplicationInfo} * @param user The UserHandle of the profile. * - * @return An {@link ApplicationInfo} containing information about the package or - * null if the package isn't installed for the given user, or the target user - * is not enabled. + * @return {@link ApplicationInfo} containing information about the package. Returns + * {@code null} if the package isn't installed for the given profile, or the profile + * isn't enabled. */ public ApplicationInfo getApplicationInfo(@NonNull String packageName, @ApplicationInfoFlags int flags, @NonNull UserHandle user) diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java index 4bc62b1d04d3..e1cd451ba2a8 100644 --- a/core/java/android/hardware/SensorManager.java +++ b/core/java/android/hardware/SensorManager.java @@ -894,8 +894,9 @@ public abstract class SensorManager { * to free up resource in sensor system associated with the direct channel. * * @param mem A {@link android.os.MemoryFile} shared memory object. - * @return A {@link android.hardware.SensorDirectChannel} object if successful, null otherwise. + * @return A {@link android.hardware.SensorDirectChannel} object. * @throws NullPointerException when mem is null. + * @throws UncheckedIOException if not able to create channel. * @see SensorDirectChannel#close() * @see #configureDirectChannel(SensorDirectChannel, Sensor, int) */ @@ -916,9 +917,9 @@ public abstract class SensorManager { * to free up resource in sensor system associated with the direct channel. * * @param mem A {@link android.hardware.HardwareBuffer} shared memory object. - * @return A {@link android.hardware.SensorDirectChannel} object if successful, - * null otherwise. + * @return A {@link android.hardware.SensorDirectChannel} object. * @throws NullPointerException when mem is null. + * @throws UncheckedIOException if not able to create channel. * @see SensorDirectChannel#close() * @see #configureDirectChannel(SensorDirectChannel, Sensor, int) */ diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java index 2d9860cf0e40..4b79cbb98d8c 100644 --- a/core/java/android/net/VpnService.java +++ b/core/java/android/net/VpnService.java @@ -99,7 +99,7 @@ import java.util.List; * shut down the tunnel gracefully.</li> * </ol> * - * <p>Services extended this class need to be declared with appropriate + * <p>Services extending this class need to be declared with an appropriate * permission and intent filter. Their access must be secured by * {@link android.Manifest.permission#BIND_VPN_SERVICE} permission, and * their intent filter must match {@link #SERVICE_INTERFACE} action. Here @@ -112,6 +112,13 @@ import java.util.List; * </intent-filter> * </service></pre> * + * <p> The Android system starts a VPN in the background by calling + * {@link android.content.Context#startService startService()}. In Android 8.0 + * (API level 26) and higher, the system places VPN apps on the temporary + * whitelist for a short period so the app can start in the background. The VPN + * app must promote itself to the foreground after it's launched or the system + * will shut down the app. + * * @see Builder */ public class VpnService extends Service { diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index a82127cb8ec5..ca7f17994105 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -1422,10 +1422,10 @@ public final class Settings { * to the caller package. * * <p> - * <b>NOTE: </b> applications should call + * <b>NOTE: </b> Applications should call * {@link android.view.autofill.AutofillManager#hasEnabledAutofillServices()} and - * {@link android.view.autofill.AutofillManager#isAutofillSupported()} first, and only - * broadcast this intent if they return {@code false} and {@code true} respectively. + * {@link android.view.autofill.AutofillManager#isAutofillSupported()}, and only use this action + * to start an activity if they return {@code false} and {@code true} respectively. */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_REQUEST_SET_AUTOFILL_SERVICE = diff --git a/core/java/android/util/Log.java b/core/java/android/util/Log.java index 951aa8df9ea3..8691136dfedc 100644 --- a/core/java/android/util/Log.java +++ b/core/java/android/util/Log.java @@ -30,8 +30,9 @@ import java.net.UnknownHostException; /** * API for sending log output. * - * <p>Generally, use the Log.v() Log.d() Log.i() Log.w() and Log.e() - * methods. + * <p>Generally, you should use the {@link #v Log.v()}, {@link #d Log.d()}, + * {@link #i Log.i()}, {@link #w Log.w()}, and {@link #e Log.e()} methods to write logs. + * You can then <a href="{@docRoot}studio/debug/am-logcat.html">view the logs in logcat</a>. * * <p>The order in terms of verbosity, from least to most is * ERROR, WARN, INFO, DEBUG, VERBOSE. Verbose should never be compiled diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index b035b7fd53ed..a19f05c6ae38 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -491,10 +491,10 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb if (myHeight <= 0) myHeight = getHeight(); final boolean formatChanged = mFormat != mRequestedFormat; - final boolean creating = (mSurfaceControl == null || formatChanged) + final boolean visibleChanged = mVisible != mRequestedVisible; + final boolean creating = (mSurfaceControl == null || formatChanged || visibleChanged) && mRequestedVisible; final boolean sizeChanged = mSurfaceWidth != myWidth || mSurfaceHeight != myHeight; - final boolean visibleChanged = mVisible != mRequestedVisible; final boolean windowVisibleChanged = mWindowVisibility != mLastWindowVisibility; boolean redrawNeeded = false; diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 488216595a3e..25c02d17f046 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -724,6 +724,8 @@ import java.util.function.Predicate; * @attr ref android.R.styleable#View_nextFocusUp * @attr ref android.R.styleable#View_onClick * @attr ref android.R.styleable#View_padding + * @attr ref android.R.styleable#View_paddingHorizontal + * @attr ref android.R.styleable#View_paddingVertical * @attr ref android.R.styleable#View_paddingBottom * @attr ref android.R.styleable#View_paddingLeft * @attr ref android.R.styleable#View_paddingRight diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 66df335f07da..1dbc1aca88c5 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -7608,6 +7608,16 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * See * {@link android.R.styleable#ViewGroup_MarginLayout ViewGroup Margin Layout Attributes} * for a list of all child view attributes that this class supports. + * + * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_margin + * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginHorizontal + * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginVertical + * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginLeft + * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginTop + * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginRight + * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginBottom + * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginStart + * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginEnd */ public static class MarginLayoutParams extends ViewGroup.LayoutParams { /** diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index 5b04f41c7ee2..e1e8317d8ccb 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -741,7 +741,8 @@ public final class AutofillManager { } /** - * Returns {@code true} if Autofill is supported for this user. + * Returns {@code true} if autofill is supported by the current device and + * is supported for this user. * * <p>Autofill is typically supported, but it could be unsupported in cases like: * <ol> diff --git a/core/java/com/android/internal/backup/package.html b/core/java/com/android/internal/backup/package.html new file mode 100644 index 000000000000..db6f78bbf628 --- /dev/null +++ b/core/java/com/android/internal/backup/package.html @@ -0,0 +1,3 @@ +<body> +{@hide} +</body>
\ No newline at end of file diff --git a/core/java/com/android/internal/inputmethod/package.html b/core/java/com/android/internal/inputmethod/package.html new file mode 100644 index 000000000000..db6f78bbf628 --- /dev/null +++ b/core/java/com/android/internal/inputmethod/package.html @@ -0,0 +1,3 @@ +<body> +{@hide} +</body>
\ No newline at end of file diff --git a/core/java/com/android/internal/logging/package.html b/core/java/com/android/internal/logging/package.html new file mode 100644 index 000000000000..db6f78bbf628 --- /dev/null +++ b/core/java/com/android/internal/logging/package.html @@ -0,0 +1,3 @@ +<body> +{@hide} +</body>
\ No newline at end of file diff --git a/core/java/com/android/internal/os/package.html b/core/java/com/android/internal/os/package.html new file mode 100644 index 000000000000..db6f78bbf628 --- /dev/null +++ b/core/java/com/android/internal/os/package.html @@ -0,0 +1,3 @@ +<body> +{@hide} +</body>
\ No newline at end of file diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index 8fe9100d2011..544afd993b37 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -3103,12 +3103,29 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } /** + * Check if Setup or Post-Setup update is completed on TV + * @return true if completed + */ + private boolean isTvUserSetupComplete() { + boolean isTvSetupComplete = Settings.Secure.getInt(getContext().getContentResolver(), + Settings.Secure.USER_SETUP_COMPLETE, 0) != 0; + isTvSetupComplete &= Settings.Secure.getInt(getContext().getContentResolver(), + Settings.Secure.TV_USER_SETUP_COMPLETE, 0) != 0; + return isTvSetupComplete; + } + + /** * Helper method for adding launch-search to most applications. Opens the * search window using default settings. * * @return true if search window opened */ private boolean launchDefaultSearch(KeyEvent event) { + if (getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK) + && !isTvUserSetupComplete()) { + // If we are in Setup or Post-Setup update mode on TV, consume the search key + return false; + } boolean result; final Callback cb = getCallback(); if (cb == null || isDestroyed()) { diff --git a/core/java/com/android/internal/statusbar/package.html b/core/java/com/android/internal/statusbar/package.html new file mode 100644 index 000000000000..db6f78bbf628 --- /dev/null +++ b/core/java/com/android/internal/statusbar/package.html @@ -0,0 +1,3 @@ +<body> +{@hide} +</body>
\ No newline at end of file diff --git a/core/java/com/android/internal/widget/package.html b/core/java/com/android/internal/widget/package.html new file mode 100644 index 000000000000..db6f78bbf628 --- /dev/null +++ b/core/java/com/android/internal/widget/package.html @@ -0,0 +1,3 @@ +<body> +{@hide} +</body>
\ No newline at end of file diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp index 2e9a6e895d8a..c19c1a11e3e2 100644 --- a/libs/hwui/GlopBuilder.cpp +++ b/libs/hwui/GlopBuilder.cpp @@ -457,11 +457,13 @@ GlopBuilder& GlopBuilder::setFillTextureLayer(GlLayer& layer, float alpha) { return *this; } -GlopBuilder& GlopBuilder::setFillExternalTexture(Texture& texture, Matrix4& textureTransform) { +GlopBuilder& GlopBuilder::setFillExternalTexture(Texture& texture, Matrix4& textureTransform, + bool requiresFilter) { TRIGGER_STAGE(kFillStage); REQUIRE_STAGES(kMeshStage | kRoundRectClipStage); - mOutGlop->fill.texture = { &texture, GL_LINEAR, GL_CLAMP_TO_EDGE, &textureTransform }; + GLenum filter = requiresFilter ? GL_LINEAR : GL_NEAREST; + mOutGlop->fill.texture = { &texture, filter, GL_CLAMP_TO_EDGE, &textureTransform }; setFill(SK_ColorWHITE, 1.0f, SkBlendMode::kSrc, Blend::ModeOrderSwap::NoSwap, nullptr, nullptr); diff --git a/libs/hwui/GlopBuilder.h b/libs/hwui/GlopBuilder.h index 87b1568ed72b..6d11da19e138 100644 --- a/libs/hwui/GlopBuilder.h +++ b/libs/hwui/GlopBuilder.h @@ -75,7 +75,8 @@ public: GlopBuilder& setFillTextureLayer(GlLayer& layer, float alpha); // TODO: setFillLayer normally forces its own wrap & filter mode, // which isn't always correct. - GlopBuilder& setFillExternalTexture(Texture& texture, Matrix4& textureTransform); + GlopBuilder& setFillExternalTexture(Texture& texture, Matrix4& textureTransform, + bool requiresFilter); GlopBuilder& setTransform(const Matrix4& canvas, const int transformFlags); diff --git a/libs/hwui/OpenGLReadback.cpp b/libs/hwui/OpenGLReadback.cpp index c460c0d2dfd4..51927d5a2c61 100644 --- a/libs/hwui/OpenGLReadback.cpp +++ b/libs/hwui/OpenGLReadback.cpp @@ -191,6 +191,7 @@ inline CopyResult copyTextureInto(Caches& caches, RenderState& renderState, GL_TEXTURE_2D, texture, 0); { + bool requiresFilter; // Draw & readback renderState.setViewport(destWidth, destHeight); renderState.scissor().setEnabled(false); @@ -208,12 +209,17 @@ inline CopyResult copyTextureInto(Caches& caches, RenderState& renderState, croppedTexTransform.scale(srcRect.getWidth() / sourceTexture.width(), srcRect.getHeight() / sourceTexture.height(), 1); croppedTexTransform.multiply(sFlipV); + requiresFilter = srcRect.getWidth() != (float) destWidth + || srcRect.getHeight() != (float) destHeight; + } else { + requiresFilter = sourceTexture.width() != (uint32_t) destWidth + || sourceTexture.height() != (uint32_t) destHeight; } Glop glop; GlopBuilder(renderState, caches, &glop) .setRoundRectClipState(nullptr) .setMeshTexturedUnitQuad(nullptr) - .setFillExternalTexture(sourceTexture, croppedTexTransform) + .setFillExternalTexture(sourceTexture, croppedTexTransform, requiresFilter) .setTransform(Matrix4::identity(), TransformFlags::None) .setModelViewMapUnitToRect(Rect(destWidth, destHeight)) .build(); diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java index 3b29a6cd7b6c..1e262314284d 100644 --- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java +++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java @@ -77,7 +77,7 @@ public class DeviceDiscoveryService extends Service { private BluetoothAdapter mBluetoothAdapter; private WifiManager mWifiManager; - private BluetoothLeScanner mBLEScanner; + @Nullable private BluetoothLeScanner mBLEScanner; private ScanSettings mDefaultScanSettings = new ScanSettings.Builder().build(); private List<DeviceFilter<?>> mFilters; @@ -185,7 +185,7 @@ public class DeviceDiscoveryService extends Service { mBluetoothAdapter.startDiscovery(); } - if (shouldScan(mBLEFilters)) { + if (shouldScan(mBLEFilters) && mBLEScanner != null) { mBLEScanCallback = new BLEScanCallback(); mBLEScanner.startScan(mBLEScanFilters, mDefaultScanSettings, mBLEScanCallback); } @@ -224,7 +224,7 @@ public class DeviceDiscoveryService extends Service { unregisterReceiver(mBluetoothBroadcastReceiver); mBluetoothBroadcastReceiver = null; } - mBLEScanner.stopScan(mBLEScanCallback); + if (mBLEScanner != null) mBLEScanner.stopScan(mBLEScanCallback); if (mWifiBroadcastReceiver != null) { unregisterReceiver(mWifiBroadcastReceiver); mWifiBroadcastReceiver = null; diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index f66a09e04192..4245b1183e08 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -776,7 +776,4 @@ <dimen name="qs_gutter_height">6dp</dimen> - <!-- Width of the hollow triangle for empty signal state --> - <dimen name="mobile_signal_empty_strokewidth">2dp</dimen> - </resources> diff --git a/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java b/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java index c43820d5a8fc..f5c82a778eb6 100644 --- a/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java +++ b/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java @@ -28,10 +28,8 @@ import android.graphics.Rect; import android.graphics.Typeface; import android.os.PowerManager; import android.os.SystemClock; -import android.os.UserHandle; import android.provider.Settings; import android.text.InputType; -import android.text.TextUtils; import android.util.AttributeSet; import android.view.Gravity; import android.view.View; @@ -248,9 +246,9 @@ public class PasswordTextView extends View { mText = mText.substring(0, length - 1); CharState charState = mTextChars.get(length - 1); charState.startRemoveAnimation(0, 0); + sendAccessibilityEventTypeViewTextChanged(textbefore, textbefore.length() - 1, 1, 0); } userActivity(); - sendAccessibilityEventTypeViewTextChanged(textbefore, textbefore.length() - 1, 1, 0); } public String getText() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java index c09da2183076..bd4a1df246f3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java @@ -417,7 +417,7 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl @Override public void onHeightUpdate() { - if (mParent == null || mMenuItems.size() == 0) { + if (mParent == null || mMenuItems.size() == 0 || mMenuContainer == null) { return; } int parentHeight = mParent.getCollapsedHeight(); @@ -477,7 +477,7 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl private void setMenuLocation() { boolean showOnLeft = mTranslation > 0; - if ((mIconsPlaced && showOnLeft == mOnLeft) || mSnapping + if ((mIconsPlaced && showOnLeft == mOnLeft) || mSnapping || mMenuContainer == null || !mMenuContainer.isAttachedToWindow()) { // Do nothing return; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java index 983a79615304..1c34b7de2d4d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java @@ -85,12 +85,8 @@ public class SignalDrawable extends Drawable { {-1.9f / VIEWPORT, -1.9f / VIEWPORT}, }; - // The easiest way to understand this is as if we set Style.STROKE and draw the triangle, - // but that is only theoretically right. Instead, draw the triangle and clip out a smaller - // one inset by this amount. - private final float mEmptyStrokeWidth; private static final float INV_TAN = 1f / (float) Math.tan(Math.PI / 8f); - private final float mEmptyDiagInset; // == mEmptyStrokeWidth * INV_TAN + private static final float CUT_WIDTH_DP = 1f / 12f; private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private final Paint mForegroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); @@ -126,11 +122,6 @@ public class SignalDrawable extends Drawable { Utils.getDefaultColor(context, R.color.light_mode_icon_color_dual_tone_fill); mIntrinsicSize = context.getResources().getDimensionPixelSize(R.dimen.signal_icon_size); - // mCutPath parameters - mEmptyStrokeWidth = context.getResources() - .getDimensionPixelSize(R.dimen.mobile_signal_empty_strokewidth); - mEmptyDiagInset = mEmptyStrokeWidth * INV_TAN; - mHandler = new Handler(); setDarkIntensity(0); } @@ -262,20 +253,22 @@ public class SignalDrawable extends Drawable { } if (mState == STATE_EMPTY) { + final float cutWidth = CUT_WIDTH_DP * height; + final float cutDiagInset = cutWidth * INV_TAN; + // Cut out a smaller triangle from the center of mFullPath mCutPath.reset(); mCutPath.setFillType(FillType.WINDING); - mCutPath.moveTo(width - padding - mEmptyStrokeWidth, - height - padding - mEmptyStrokeWidth); - mCutPath.lineTo(width - padding - mEmptyStrokeWidth, padding + mEmptyDiagInset); - mCutPath.lineTo(padding + mEmptyDiagInset, height - padding - mEmptyStrokeWidth); - mCutPath.lineTo(width - padding - mEmptyStrokeWidth, - height - padding - mEmptyStrokeWidth); - - // In empty state, draw the full path as the foreground paint - mForegroundPath.set(mFullPath); - mFullPath.reset(); - mForegroundPath.op(mCutPath, Path.Op.DIFFERENCE); + mCutPath.moveTo(width - padding - cutWidth, + height - padding - cutWidth); + mCutPath.lineTo(width - padding - cutWidth, padding + cutDiagInset); + mCutPath.lineTo(padding + cutDiagInset, height - padding - cutWidth); + mCutPath.lineTo(width - padding - cutWidth, + height - padding - cutWidth); + + // Draw empty state as only background + mForegroundPath.reset(); + mFullPath.op(mCutPath, Path.Op.DIFFERENCE); } else if (mState == STATE_AIRPLANE) { // Airplane mode is slashed, full-signal mForegroundPath.set(mFullPath); 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 efce87177faa..14868e07d446 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java @@ -334,6 +334,10 @@ public class MobileSignalController extends SignalController< } private boolean isRoaming() { + // During a carrier change, roaming indications need to be supressed. + if (isCarrierNetworkChangeActive()) { + return false; + } if (isCdma()) { final int iconMode = mServiceState.getCdmaEriIconMode(); return mServiceState.getCdmaEriIconIndex() != EriInfo.ROAMING_INDICATOR_OFF diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java index e0d8042238d2..4aa987738572 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java @@ -57,4 +57,10 @@ public class NotificationMenuRowTest extends LeakCheckedTest { row.createMenu(null); assertTrue(row.getMenuView() != null); } + + @Test + public void testResetUncreatedMenu() { + NotificationMenuRowPlugin row = new NotificationMenuRow(mContext); + row.resetMenu(); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java index 1627925ae1bc..15186dc2c701 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java @@ -496,6 +496,79 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { DEFAULT_ICON /* typeIcon */); } + @Test + public void testCarrierNetworkChange_roamingBeforeNetworkChange() { + int strength = SignalStrength.SIGNAL_STRENGTH_GREAT; + + setupDefaultSignal(); + setLevel(strength); + setGsmRoaming(true); + + // Verify baseline + verifyLastMobileDataIndicators(true /* visible */, + strength /* strengthIcon */, + DEFAULT_ICON /* typeIcon */, + true /* roaming */); + + // API call is made + setCarrierNetworkChange(true /* enabled */); + + // Carrier network change is true, show special indicator, no roaming. + verifyLastMobileDataIndicators(true /* visible */, + SignalDrawable.getCarrierChangeState(SignalStrength.NUM_SIGNAL_STRENGTH_BINS), + 0 /* typeIcon */, + false /* roaming */); + + // Revert back + setCarrierNetworkChange(false /* enabled */); + + // Verify back in previous state + verifyLastMobileDataIndicators(true /* visible */, + strength /* strengthIcon */, + DEFAULT_ICON /* typeIcon */, + true /* roaming */); + } + + @Test + public void testCarrierNetworkChange_roamingAfterNetworkChange() { + int strength = SignalStrength.SIGNAL_STRENGTH_GREAT; + + setupDefaultSignal(); + setLevel(strength); + + // Verify baseline + verifyLastMobileDataIndicators(true /* visible */, + strength /* strengthIcon */, + DEFAULT_ICON /* typeIcon */, + false /* roaming */); + + // API call is made + setCarrierNetworkChange(true /* enabled */); + + // Carrier network change is true, show special indicator, no roaming. + verifyLastMobileDataIndicators(true /* visible */, + SignalDrawable.getCarrierChangeState(SignalStrength.NUM_SIGNAL_STRENGTH_BINS), + 0 /* typeIcon */, + false /* roaming */); + + setGsmRoaming(true); + + // Roaming should not show. + verifyLastMobileDataIndicators(true /* visible */, + SignalDrawable.getCarrierChangeState(SignalStrength.NUM_SIGNAL_STRENGTH_BINS), + 0 /* typeIcon */, + false /* roaming */); + + // Revert back + setCarrierNetworkChange(false /* enabled */); + + // Verify back in previous state + verifyLastMobileDataIndicators(true /* visible */, + strength /* strengthIcon */, + DEFAULT_ICON /* typeIcon */, + true /* roaming */); + } + private void verifyEmergencyOnly(boolean isEmergencyOnly) { ArgumentCaptor<Boolean> emergencyOnly = ArgumentCaptor.forClass(Boolean.class); Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setEmergencyCallsOnly( diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java index 9e4d89cbc9c5..0e42e6d6a83d 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java @@ -271,6 +271,7 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo private void processKeyEvent(EventStreamState state, KeyEvent event, int policyFlags) { if (!state.shouldProcessKeyEvent(event)) { + super.onInputEvent(event, policyFlags); return; } mEventHandler.onKeyEvent(event, policyFlags); diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java index 30de4baf3460..6f6e1b721487 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -5666,13 +5666,15 @@ public class BackupManagerService { PerformFullTransportBackupTask pftbt = null; synchronized (mQueueLock) { if (mRunningFullBackupTask != null) { - if (DEBUG_SCHEDULING) { - Slog.i(TAG, "Telling running backup to stop"); - } pftbt = mRunningFullBackupTask; } } - pftbt.handleCancel(true); + if (pftbt != null) { + if (DEBUG_SCHEDULING) { + Slog.i(TAG, "Telling running backup to stop"); + } + pftbt.handleCancel(true); + } } }; new Thread(endFullBackupRunnable, "end-full-backup").start(); diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java index 4810f4fe8c82..f47b0d3c6e73 100644 --- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java @@ -383,7 +383,7 @@ public class CompanionDeviceManagerService extends SystemService implements Bind findDeviceCallback, getServiceCallback()); } catch (RemoteException e) { - throw new RuntimeException(e); + Log.e(LOG_TAG, "Error while initiating device discovery", e); } } diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index 61057dd25444..75206e48aa8b 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -86,6 +86,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int ACTIVE_LOG_MAX_SIZE = 20; private static final int CRASH_LOG_MAX_SIZE = 100; private static final String REASON_AIRPLANE_MODE = "airplane mode"; + private static final String REASON_DISALLOWED = "disallowed by system"; + private static final String REASON_SHARING_DISALLOWED = "sharing disallowed by system"; private static final String REASON_RESTARTED = "automatic restart"; private static final String REASON_START_CRASH = "turn-on crash"; private static final String REASON_SYSTEM_BOOT = "system boot"; @@ -227,25 +229,26 @@ class BluetoothManagerService extends IBluetoothManager.Stub { @Override public void onUserRestrictionsChanged(int userId, Bundle newRestrictions, Bundle prevRestrictions) { - if (!UserRestrictionsUtils.restrictionsChanged(prevRestrictions, newRestrictions, - UserManager.DISALLOW_BLUETOOTH, UserManager.DISALLOW_BLUETOOTH_SHARING)) { - return; // No relevant changes, nothing to do. - } - final boolean disallowed = newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH); + if (UserRestrictionsUtils.restrictionsChanged(prevRestrictions, newRestrictions, + UserManager.DISALLOW_BLUETOOTH_SHARING)) { + updateOppLauncherComponentState(userId, newRestrictions.getBoolean( + UserManager.DISALLOW_BLUETOOTH_SHARING)); + } - // DISALLOW_BLUETOOTH is a global restriction that can only be set by DO or PO on the - // system user, so we only look at the system user. - if (userId == UserHandle.USER_SYSTEM && disallowed && (mEnable || mEnableExternal)) { - try { - disable(null /* packageName */, true /* persist */); - } catch (RemoteException e) { - Slog.w(TAG, "Exception when disabling Bluetooth", e); + // DISALLOW_BLUETOOTH can only be set by DO or PO on the system user. + if (userId == UserHandle.USER_SYSTEM && + UserRestrictionsUtils.restrictionsChanged( + prevRestrictions, newRestrictions, UserManager.DISALLOW_BLUETOOTH)) { + if (userId == UserHandle.USER_SYSTEM && newRestrictions.getBoolean( + UserManager.DISALLOW_BLUETOOTH)) { + updateOppLauncherComponentState(userId, true); // Sharing disallowed + sendDisableMsg(REASON_DISALLOWED); + } else { + updateOppLauncherComponentState(userId, newRestrictions.getBoolean( + UserManager.DISALLOW_BLUETOOTH_SHARING)); } } - final boolean sharingDisallowed = disallowed - || newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH_SHARING); - updateOppLauncherComponentState(userId, sharingDisallowed); } }; @@ -2118,7 +2121,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; try { final IPackageManager imp = AppGlobals.getPackageManager(); - imp.setComponentEnabledSetting(oppLauncherComponent, newState, 0 /* flags */, userId); + imp.setComponentEnabledSetting(oppLauncherComponent, newState, + PackageManager.DONT_KILL_APP, userId); } catch (Exception e) { // The component was not found, do nothing. } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 5f679db3287d..904059a9cd1e 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -20,6 +20,7 @@ import static android.Manifest.permission.CHANGE_CONFIGURATION; import static android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST; import static android.Manifest.permission.INTERACT_ACROSS_USERS; import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL; +import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS; import static android.Manifest.permission.READ_FRAME_BUFFER; import static android.Manifest.permission.START_TASKS_FROM_RECENTS; @@ -10228,7 +10229,7 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public void moveStackToDisplay(int stackId, int displayId) { - enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "moveStackToDisplay()"); + enforceCallingPermission(INTERNAL_SYSTEM_WINDOW, "moveStackToDisplay()"); synchronized (this) { final long ident = Binder.clearCallingIdentity(); diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index fe0e07efe9bc..3de203669032 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -16,6 +16,7 @@ package com.android.server.am; +import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS; import static android.Manifest.permission.START_ANY_ACTIVITY; import static android.Manifest.permission.START_TASKS_FROM_RECENTS; @@ -38,11 +39,13 @@ import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCRE import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static android.os.Process.SYSTEM_UID; import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.FLAG_PRIVATE; import static android.view.Display.INVALID_DISPLAY; import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT; +import static android.view.Display.TYPE_VIRTUAL; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_PICTURE_IN_PICTURE_EXPANDED_TO_FULLSCREEN; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL; @@ -1678,6 +1681,24 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return false; } + // Check if the caller can manage activity stacks. + final int startAnyPerm = mService.checkPermission(INTERNAL_SYSTEM_WINDOW, callingPid, + callingUid); + if (startAnyPerm == PERMISSION_GRANTED) { + if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:" + + " allow launch any on display"); + return true; + } + + if (activityDisplay.mDisplay.getType() == TYPE_VIRTUAL + && activityDisplay.mDisplay.getOwnerUid() != SYSTEM_UID) { + // Limit launching on virtual displays, because their contents can be read from Surface + // by apps that created them. + if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:" + + " disallow launch on virtual display for not-embedded activity"); + return false; + } + if (!activityDisplay.isPrivate()) { // Anyone can launch on a public display. if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:" @@ -1699,15 +1720,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return true; } - // Check if the caller can manage activity stacks. - final int startAnyPerm = mService.checkPermission(MANAGE_ACTIVITY_STACKS, callingPid, - callingUid); - if (startAnyPerm == PERMISSION_GRANTED) { - if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:" - + " allow launch any on display"); - return true; - } - Slog.w(TAG, "Launch on display check: denied"); return false; } diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index a145435976fa..a31c33e4ab91 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -17,6 +17,7 @@ package com.android.server.am; import static android.app.Activity.RESULT_CANCELED; +import static android.app.ActivityManager.START_ABORTED; import static android.app.ActivityManager.START_CANCELED; import static android.app.ActivityManager.START_CLASS_NOT_FOUND; import static android.app.ActivityManager.START_DELIVERED_TO_TOP; @@ -279,7 +280,9 @@ class ActivityStarter { // mLastStartActivityRecord[0] is set in the call to startActivity above. outActivity[0] = mLastStartActivityRecord[0]; } - return mLastStartActivityResult; + + // Aborted results are treated as successes externally, but we must track them internally. + return mLastStartActivityResult != START_ABORTED ? mLastStartActivityResult : START_SUCCESS; } /** DO NOT call this method directly. Use {@link #startActivityLocked} instead. */ @@ -465,7 +468,7 @@ class ActivityStarter { // We pretend to the caller that it was really started, but // they will just get a cancel result. ActivityOptions.abort(options); - return START_SUCCESS; + return START_ABORTED; } // If permissions need a review before any of the app components can run, we diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index f3a292b7e1e0..20d7b28c55e1 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -1018,7 +1018,7 @@ class PackageManagerShellCommand extends ShellCommand { throw new RuntimeException(e.getMessage(), e); } try { - ResolveInfo ri = mInterface.resolveIntent(intent, null, 0, mTargetUser); + ResolveInfo ri = mInterface.resolveIntent(intent, intent.getType(), 0, mTargetUser); PrintWriter pw = getOutPrintWriter(); if (ri == null) { pw.println("No activity found"); @@ -1040,7 +1040,7 @@ class PackageManagerShellCommand extends ShellCommand { throw new RuntimeException(e.getMessage(), e); } try { - List<ResolveInfo> result = mInterface.queryIntentActivities(intent, null, 0, + List<ResolveInfo> result = mInterface.queryIntentActivities(intent, intent.getType(), 0, mTargetUser).getList(); PrintWriter pw = getOutPrintWriter(); if (result == null || result.size() <= 0) { @@ -1074,7 +1074,7 @@ class PackageManagerShellCommand extends ShellCommand { throw new RuntimeException(e.getMessage(), e); } try { - List<ResolveInfo> result = mInterface.queryIntentServices(intent, null, 0, + List<ResolveInfo> result = mInterface.queryIntentServices(intent, intent.getType(), 0, mTargetUser).getList(); PrintWriter pw = getOutPrintWriter(); if (result == null || result.size() <= 0) { @@ -1108,7 +1108,7 @@ class PackageManagerShellCommand extends ShellCommand { throw new RuntimeException(e.getMessage(), e); } try { - List<ResolveInfo> result = mInterface.queryIntentReceivers(intent, null, 0, + List<ResolveInfo> result = mInterface.queryIntentReceivers(intent, intent.getType(), 0, mTargetUser).getList(); PrintWriter pw = getOutPrintWriter(); if (result == null || result.size() <= 0) { diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 8112f9998c58..4477e5a0f173 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -1689,8 +1689,17 @@ public class PhoneWindowManager implements WindowManagerPolicy { } boolean isUserSetupComplete() { - return Settings.Secure.getIntForUser(mContext.getContentResolver(), + boolean isSetupComplete = Settings.Secure.getIntForUser(mContext.getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0; + if (mHasFeatureLeanback) { + isSetupComplete &= isTvUserSetupComplete(); + } + return isSetupComplete; + } + + private boolean isTvUserSetupComplete() { + return Settings.Secure.getIntForUser(mContext.getContentResolver(), + Settings.Secure.TV_USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0; } private void handleShortPressOnHome() { diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java index 5f34c6067997..4e4398ee9d91 100644 --- a/services/core/java/com/android/server/wm/AppWindowContainerController.java +++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java @@ -614,7 +614,7 @@ public class AppWindowContainerController return STARTING_WINDOW_TYPE_SPLASH_SCREEN; } else if (taskSwitch && allowTaskSnapshot) { return snapshot == null ? STARTING_WINDOW_TYPE_NONE - : snapshotOrientationSameAsDisplay(snapshot) || fromRecents + : snapshotOrientationSameAsTask(snapshot) || fromRecents ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN; } else { return STARTING_WINDOW_TYPE_NONE; @@ -640,24 +640,11 @@ public class AppWindowContainerController return true; } - private boolean snapshotOrientationSameAsDisplay(TaskSnapshot snapshot) { + private boolean snapshotOrientationSameAsTask(TaskSnapshot snapshot) { if (snapshot == null) { return false; } - final Rect rect = new Rect(0, 0, snapshot.getSnapshot().getWidth(), - snapshot.getSnapshot().getHeight()); - rect.inset(snapshot.getContentInsets()); - final Rect taskBoundsWithoutInsets = new Rect(); - mContainer.getTask().getBounds(taskBoundsWithoutInsets); - final DisplayInfo di = mContainer.getDisplayContent().getDisplayInfo(); - final Rect displayBounds = new Rect(0, 0, di.logicalWidth, di.logicalHeight); - final Rect stableInsets = new Rect(); - mService.mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, - stableInsets); - displayBounds.inset(stableInsets); - final boolean snapshotInLandscape = rect.width() >= rect.height(); - final boolean displayInLandscape = displayBounds.width() >= displayBounds.height(); - return snapshotInLandscape == displayInLandscape; + return mContainer.getTask().getConfiguration().orientation == snapshot.getOrientation(); } public void removeStartingWindow() { diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java b/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java index 70c7e586d3fe..608635491849 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java @@ -25,8 +25,8 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.SystemClock; -import android.util.Log; import android.util.LongSparseArray; +import android.util.Slog; import com.android.internal.annotations.GuardedBy; @@ -60,16 +60,21 @@ final class NetworkLoggingHandler extends Handler { /** Delay after which older batches get discarded after a retrieval. */ private static final long RETRIEVED_BATCH_DISCARD_DELAY_MS = 5 * 60 * 1000; // 5m + /** Do not call into mDpm with locks held */ private final DevicePolicyManagerService mDpm; private final AlarmManager mAlarmManager; private final OnAlarmListener mBatchTimeoutAlarmListener = new OnAlarmListener() { @Override public void onAlarm() { - Log.d(TAG, "Received a batch finalization timeout alarm, finalizing " + Slog.d(TAG, "Received a batch finalization timeout alarm, finalizing " + mNetworkEvents.size() + " pending events."); + Bundle notificationExtras = null; synchronized (NetworkLoggingHandler.this) { - finalizeBatchAndNotifyDeviceOwnerLocked(); + notificationExtras = finalizeBatchAndBuildDeviceOwnerMessageLocked(); + } + if (notificationExtras != null) { + notifyDeviceOwner(notificationExtras); } } }; @@ -110,17 +115,21 @@ final class NetworkLoggingHandler extends Handler { case LOG_NETWORK_EVENT_MSG: { final NetworkEvent networkEvent = msg.getData().getParcelable(NETWORK_EVENT_KEY); if (networkEvent != null) { + Bundle notificationExtras = null; synchronized (NetworkLoggingHandler.this) { mNetworkEvents.add(networkEvent); if (mNetworkEvents.size() >= MAX_EVENTS_PER_BATCH) { - finalizeBatchAndNotifyDeviceOwnerLocked(); + notificationExtras = finalizeBatchAndBuildDeviceOwnerMessageLocked(); } } + if (notificationExtras != null) { + notifyDeviceOwner(notificationExtras); + } } break; } default: { - Log.d(TAG, "NetworkLoggingHandler received an unknown of message."); + Slog.d(TAG, "NetworkLoggingHandler received an unknown of message."); break; } } @@ -133,40 +142,48 @@ final class NetworkLoggingHandler extends Handler { mAlarmManager.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP, when, BATCH_FINALIZATION_TIMEOUT_ALARM_INTERVAL_MS, NETWORK_LOGGING_TIMEOUT_ALARM_TAG, mBatchTimeoutAlarmListener, this); - Log.d(TAG, "Scheduled a new batch finalization alarm " + BATCH_FINALIZATION_TIMEOUT_MS + Slog.d(TAG, "Scheduled a new batch finalization alarm " + BATCH_FINALIZATION_TIMEOUT_MS + "ms from now."); } synchronized void pause() { - Log.d(TAG, "Paused network logging"); + Slog.d(TAG, "Paused network logging"); mPaused = true; } - synchronized void resume() { - if (!mPaused) { - Log.d(TAG, "Attempted to resume network logging, but logging is not paused."); - return; - } + void resume() { + Bundle notificationExtras = null; + synchronized (this) { + if (!mPaused) { + Slog.d(TAG, "Attempted to resume network logging, but logging is not paused."); + return; + } - Log.d(TAG, "Resumed network logging. Current batch=" + mCurrentBatchToken - + ", LastRetrievedBatch=" + mLastRetrievedBatchToken); - mPaused = false; + Slog.d(TAG, "Resumed network logging. Current batch=" + mCurrentBatchToken + + ", LastRetrievedBatch=" + mLastRetrievedBatchToken); + mPaused = false; - // If there is a batch ready that the device owner hasn't been notified about, do it now. - if (mBatches.size() > 0 && mLastRetrievedBatchToken != mCurrentBatchToken) { - scheduleBatchFinalization(); - notifyDeviceOwnerLocked(); + // If there is a batch ready that the device owner hasn't been notified about, do it now. + if (mBatches.size() > 0 && mLastRetrievedBatchToken != mCurrentBatchToken) { + scheduleBatchFinalization(); + notificationExtras = buildDeviceOwnerMessageLocked(); + } + } + if (notificationExtras != null) { + notifyDeviceOwner(notificationExtras); } } synchronized void discardLogs() { mBatches.clear(); mNetworkEvents = new ArrayList<>(); - Log.d(TAG, "Discarded all network logs"); + Slog.d(TAG, "Discarded all network logs"); } @GuardedBy("this") - private void finalizeBatchAndNotifyDeviceOwnerLocked() { + /** @returns extras if a message should be sent to the device owner */ + private Bundle finalizeBatchAndBuildDeviceOwnerMessageLocked() { + Bundle notificationExtras = null; if (mNetworkEvents.size() > 0) { // Finalize the batch and start a new one from scratch. if (mBatches.size() >= MAX_BATCHES) { @@ -177,27 +194,39 @@ final class NetworkLoggingHandler extends Handler { mBatches.append(mCurrentBatchToken, mNetworkEvents); mNetworkEvents = new ArrayList<>(); if (!mPaused) { - notifyDeviceOwnerLocked(); + notificationExtras = buildDeviceOwnerMessageLocked(); } } else { // Don't notify the DO, since there are no events; DPC can still retrieve // the last full batch if not paused. - Log.d(TAG, "Was about to finalize the batch, but there were no events to send to" + Slog.d(TAG, "Was about to finalize the batch, but there were no events to send to" + " the DPC, the batchToken of last available batch: " + mCurrentBatchToken); } // Regardless of whether the batch was non-empty schedule a new finalization after timeout. scheduleBatchFinalization(); + return notificationExtras; } - /** Sends a notification to the DO. Should only be called when there is a batch available. */ @GuardedBy("this") - private void notifyDeviceOwnerLocked() { + /** Build extras notification to the DO. Should only be called when there + is a batch available. */ + private Bundle buildDeviceOwnerMessageLocked() { final Bundle extras = new Bundle(); final int lastBatchSize = mBatches.valueAt(mBatches.size() - 1).size(); extras.putLong(DeviceAdminReceiver.EXTRA_NETWORK_LOGS_TOKEN, mCurrentBatchToken); extras.putInt(DeviceAdminReceiver.EXTRA_NETWORK_LOGS_COUNT, lastBatchSize); - Log.d(TAG, "Sending network logging batch broadcast to device owner, batchToken: " - + mCurrentBatchToken); + return extras; + } + + /** Sends a notification to the DO. Should not hold locks as DevicePolicyManagerService may + call into NetworkLoggingHandler. */ + private void notifyDeviceOwner(Bundle extras) { + Slog.d(TAG, "Sending network logging batch broadcast to device owner, batchToken: " + + extras.getLong(DeviceAdminReceiver.EXTRA_NETWORK_LOGS_TOKEN, -1)); + if (Thread.holdsLock(this)) { + Slog.wtfStack(TAG, "Shouldn't be called with NetworkLoggingHandler lock held"); + return; + } mDpm.sendDeviceOwnerCommand(DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE, extras); } diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java index 636b3f82ac31..3f0eacfad255 100644 --- a/tests/net/java/com/android/server/connectivity/TetheringTest.java +++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java @@ -407,7 +407,7 @@ public class TetheringTest { when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true); // Emulate pressing the WiFi tethering button. - mTethering.startTethering(ConnectivityManager.TETHERING_WIFI, null, false); + mTethering.startTethering(TETHERING_WIFI, null, false); mLooper.dispatchAll(); verify(mWifiManager, times(1)).startSoftAp(null); verifyNoMoreInteractions(mWifiManager); |