From ce73c7e8c4960f8579da707500ffc15c45906f31 Mon Sep 17 00:00:00 2001 From: Przemyslaw Szczepaniak Date: Mon, 22 Jan 2018 11:00:41 +0000 Subject: [PATCH] Warn when running activity from deprecated app (< min supported sdk). As part of deprecation policy enforcement for android apps, minimum supported targetSdkVersion will be 17. Apks targeting values lower that one set in PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION (currently set to 0) will display a dismissible warning when run. More info can be found in go/android-targetsdkversion-warning + Fix in AppWarnings.setPackageFlag, "enable" logic was wrong way around ('false' was setting the flag and 'true' clearing it) + Added FLAG_ACTIVITY_NEW_TASK to AppInstallerUtil.createIntent result, otherwise it will crash system server when startActivity is called without this flag. Test: atest CtsActivityManagerDeviceTestCases:DeprecatedTargetSdkTest Bug: 63926630 Change-Id: I93e0079af763a97ee47b3d8212648d422bc6614d --- core/res/res/values/strings.xml | 5 ++ core/res/res/values/symbols.xml | 3 + .../server/am/ActivityManagerService.java | 1 + .../com/android/server/am/AppWarnings.java | 54 +++++++++++- .../am/DeprecatedTargetSdkVersionDialog.java | 83 +++++++++++++++++++ .../server/utils/AppInstallerUtil.java | 1 + 6 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 services/core/java/com/android/server/am/DeprecatedTargetSdkVersionDialog.java diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 170ba4264e04..a1e35c5afaa3 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -4612,6 +4612,11 @@ Turn on + + This app was built for an older version of Android and may not work properly. Try checking for updates, or contact the developer. + + Check for update + You have new messages diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 4ef0a6c93d9e..c3d4d5660e0f 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2698,6 +2698,9 @@ + + + diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index dc34567532bd..5199ea0af343 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -3366,6 +3366,7 @@ public class ActivityManagerService extends IActivityManager.Stub final void showAppWarningsIfNeededLocked(ActivityRecord r) { mAppWarnings.showUnsupportedCompileSdkDialogIfNeeded(r); mAppWarnings.showUnsupportedDisplaySizeDialogIfNeeded(r); + mAppWarnings.showDeprecatedTargetDialogIfNeeded(r); } private int updateLruProcessInternalLocked(ProcessRecord app, long now, int index, diff --git a/services/core/java/com/android/server/am/AppWarnings.java b/services/core/java/com/android/server/am/AppWarnings.java index a3c0345066de..806e95d71cd1 100644 --- a/services/core/java/com/android/server/am/AppWarnings.java +++ b/services/core/java/com/android/server/am/AppWarnings.java @@ -50,6 +50,7 @@ class AppWarnings { public static final int FLAG_HIDE_DISPLAY_SIZE = 0x01; public static final int FLAG_HIDE_COMPILE_SDK = 0x02; + public static final int FLAG_HIDE_DEPRECATED_SDK = 0x04; private final HashMap mPackageFlags = new HashMap<>(); @@ -61,6 +62,7 @@ class AppWarnings { private UnsupportedDisplaySizeDialog mUnsupportedDisplaySizeDialog; private UnsupportedCompileSdkDialog mUnsupportedCompileSdkDialog; + private DeprecatedTargetSdkVersionDialog mDeprecatedTargetSdkVersionDialog; /** * Creates a new warning dialog manager. @@ -125,6 +127,17 @@ class AppWarnings { } } + /** + * Shows the "deprecated target sdk" warning, if necessary. + * + * @param r activity record for which the warning may be displayed + */ + public void showDeprecatedTargetDialogIfNeeded(ActivityRecord r) { + if (r.appInfo.targetSdkVersion < Build.VERSION.MIN_SUPPORTED_TARGET_SDK_INT) { + mUiHandler.showDeprecatedTargetDialog(r); + } + } + /** * Called when an activity is being started. * @@ -133,6 +146,7 @@ class AppWarnings { public void onStartActivity(ActivityRecord r) { showUnsupportedCompileSdkDialogIfNeeded(r); showUnsupportedDisplaySizeDialogIfNeeded(r); + showDeprecatedTargetDialogIfNeeded(r); } /** @@ -236,6 +250,27 @@ class AppWarnings { } } + /** + * Shows the "deprecated target sdk version" warning for the given application. + *

+ * Note: Must be called on the UI thread. + * + * @param ar record for the activity that triggered the warning + */ + @UiThread + private void showDeprecatedTargetSdkDialogUiThread(ActivityRecord ar) { + if (mDeprecatedTargetSdkVersionDialog != null) { + mDeprecatedTargetSdkVersionDialog.dismiss(); + mDeprecatedTargetSdkVersionDialog = null; + } + if (ar != null && !hasPackageFlag( + ar.packageName, FLAG_HIDE_DEPRECATED_SDK)) { + mDeprecatedTargetSdkVersionDialog = new DeprecatedTargetSdkVersionDialog( + AppWarnings.this, mUiContext, ar.info.applicationInfo); + mDeprecatedTargetSdkVersionDialog.show(); + } + } + /** * Dismisses all warnings for the given package. *

@@ -259,6 +294,13 @@ class AppWarnings { mUnsupportedCompileSdkDialog.dismiss(); mUnsupportedCompileSdkDialog = null; } + + // Hides the "deprecated target sdk version" dialog if necessary. + if (mDeprecatedTargetSdkVersionDialog != null && (name == null || name.equals( + mDeprecatedTargetSdkVersionDialog.getPackageName()))) { + mDeprecatedTargetSdkVersionDialog.dismiss(); + mDeprecatedTargetSdkVersionDialog = null; + } } /** @@ -282,7 +324,7 @@ class AppWarnings { void setPackageFlag(String name, int flag, boolean enabled) { synchronized (mPackageFlags) { final int curFlags = getPackageFlags(name); - final int newFlags = enabled ? (curFlags & ~flag) : (curFlags | flag); + final int newFlags = enabled ? (curFlags | flag) : (curFlags & ~flag); if (curFlags != newFlags) { if (newFlags != 0) { mPackageFlags.put(name, newFlags); @@ -311,6 +353,7 @@ class AppWarnings { private static final int MSG_HIDE_UNSUPPORTED_DISPLAY_SIZE_DIALOG = 2; private static final int MSG_SHOW_UNSUPPORTED_COMPILE_SDK_DIALOG = 3; private static final int MSG_HIDE_DIALOGS_FOR_PACKAGE = 4; + private static final int MSG_SHOW_DEPRECATED_TARGET_SDK_DIALOG = 5; public UiHandler(Looper looper) { super(looper, null, true); @@ -334,6 +377,10 @@ class AppWarnings { final String name = (String) msg.obj; hideDialogsForPackageUiThread(name); } break; + case MSG_SHOW_DEPRECATED_TARGET_SDK_DIALOG: { + final ActivityRecord ar = (ActivityRecord) msg.obj; + showDeprecatedTargetSdkDialogUiThread(ar); + } break; } } @@ -352,6 +399,11 @@ class AppWarnings { obtainMessage(MSG_SHOW_UNSUPPORTED_COMPILE_SDK_DIALOG, r).sendToTarget(); } + public void showDeprecatedTargetDialog(ActivityRecord r) { + removeMessages(MSG_SHOW_DEPRECATED_TARGET_SDK_DIALOG); + obtainMessage(MSG_SHOW_DEPRECATED_TARGET_SDK_DIALOG, r).sendToTarget(); + } + public void hideDialogsForPackage(String name) { obtainMessage(MSG_HIDE_DIALOGS_FOR_PACKAGE, name).sendToTarget(); } diff --git a/services/core/java/com/android/server/am/DeprecatedTargetSdkVersionDialog.java b/services/core/java/com/android/server/am/DeprecatedTargetSdkVersionDialog.java new file mode 100644 index 000000000000..84dca7fe1c8a --- /dev/null +++ b/services/core/java/com/android/server/am/DeprecatedTargetSdkVersionDialog.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2017 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.am; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.os.Build; +import android.os.SystemPropertiesProto; +import android.view.Window; +import android.view.WindowManager; +import android.widget.CheckBox; + +import com.android.internal.R; +import com.android.server.utils.AppInstallerUtil; + +public class DeprecatedTargetSdkVersionDialog { + private final AlertDialog mDialog; + private final String mPackageName; + + public DeprecatedTargetSdkVersionDialog(final AppWarnings manager, Context context, + ApplicationInfo appInfo) { + mPackageName = appInfo.packageName; + + final PackageManager pm = context.getPackageManager(); + final CharSequence label = appInfo.loadSafeLabel(pm); + final CharSequence message = context.getString(R.string.deprecated_target_sdk_message); + + final AlertDialog.Builder builder = new AlertDialog.Builder(context) + .setPositiveButton(R.string.ok, (dialog, which) -> + manager.setPackageFlag( + mPackageName, AppWarnings.FLAG_HIDE_DEPRECATED_SDK, true)) + .setMessage(message) + .setTitle(label); + + // If we might be able to update the app, show a button. + final Intent installerIntent = AppInstallerUtil.createIntent(context, appInfo.packageName); + if (installerIntent != null) { + builder.setNeutralButton(R.string.deprecated_target_sdk_app_store, + (dialog, which) -> { + context.startActivity(installerIntent); + }); + } + + // Ensure the content view is prepared. + mDialog = builder.create(); + mDialog.create(); + + final Window window = mDialog.getWindow(); + window.setType(WindowManager.LayoutParams.TYPE_PHONE); + + // DO NOT MODIFY. Used by CTS to verify the dialog is displayed. + window.getAttributes().setTitle("DeprecatedTargetSdkVersionDialog"); + } + + public String getPackageName() { + return mPackageName; + } + + public void show() { + mDialog.show(); + } + + public void dismiss() { + mDialog.dismiss(); + } +} diff --git a/services/core/java/com/android/server/utils/AppInstallerUtil.java b/services/core/java/com/android/server/utils/AppInstallerUtil.java index af7ff41f4455..5d2dbe688674 100644 --- a/services/core/java/com/android/server/utils/AppInstallerUtil.java +++ b/services/core/java/com/android/server/utils/AppInstallerUtil.java @@ -56,6 +56,7 @@ public class AppInstallerUtil { final Intent result = resolveIntent(context, intent); if (result != null) { result.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName); + result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); return result; } return null; -- GitLab