diff options
8 files changed, 221 insertions, 10 deletions
diff --git a/core/res/res/layout/unsupported_display_size_dialog_content.xml b/core/res/res/layout/unsupported_display_size_dialog_content.xml new file mode 100644 index 000000000000..5e5cf00b27ac --- /dev/null +++ b/core/res/res/layout/unsupported_display_size_dialog_content.xml @@ -0,0 +1,31 @@ +<?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:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingTop="?attr/dialogPreferredPadding" + android:paddingLeft="?attr/dialogPreferredPadding" + android:paddingRight="?attr/dialogPreferredPadding"> + + <CheckBox + android:id="@+id/ask_checkbox" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="start" + android:text="@string/unsupported_display_size_show" /> +</FrameLayout> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 48744b61b965..b55a9b22118b 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -2768,6 +2768,11 @@ <!-- [CHAR LIMIT=200] Compat mode dialog: hint to re-enable compat mode dialog. --> <string name="screen_compat_mode_hint">Re-enable this in System settings > Apps > Downloaded.</string> + <!-- [CHAR LIMIT=200] Unsupported display size dialog: message. Refers to "Display size" setting. --> + <string name="unsupported_display_size_message"><xliff:g id="app_name">%1$s</xliff:g> does not support the current Display size setting and may behave unexpectedly.</string> + <!-- [CHAR LIMIT=50] Unsupported display size dialog: check box label. --> + <string name="unsupported_display_size_show">Always show</string> + <!-- Text of the alert that is displayed when an application has violated StrictMode. --> <string name="smv_application">The app <xliff:g id="application">%1$s</xliff:g> (process <xliff:g id="process">%2$s</xliff:g>) has violated its self-enforced StrictMode policy.</string> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 7e9b57c7a49b..d154b034e058 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2609,4 +2609,7 @@ <java-symbol type="array" name="config_defaultPinnerServiceFiles" /> <java-symbol type="string" name="suspended_widget_accessibility" /> + + <java-symbol type="layout" name="unsupported_display_size_dialog_content" /> + <java-symbol type="string" name="unsupported_display_size_message" /> </resources> diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 402165ae2481..60acf756ba0a 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -102,7 +102,6 @@ import android.app.NotificationManager; import android.app.PendingIntent; import android.app.ProfilerInfo; import android.app.admin.DevicePolicyManager; -import android.app.admin.DevicePolicyManagerInternal; import android.app.assist.AssistContent; import android.app.assist.AssistStructure; import android.app.backup.IBackupManager; @@ -205,6 +204,7 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.AtomicFile; import android.util.DebugUtils; +import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Log; import android.util.Pair; @@ -1513,6 +1513,7 @@ public final class ActivityManagerService extends ActivityManagerNative static final int NOTIFY_FORCED_RESIZABLE_MSG = 67; static final int NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG = 68; static final int VR_MODE_APPLY_IF_NEEDED_MSG = 69; + static final int SHOW_UNSUPPORTED_DISPLAY_SIZE_DIALOG_MSG = 70; static final int FIRST_ACTIVITY_STACK_MSG = 100; static final int FIRST_BROADCAST_QUEUE_MSG = 200; @@ -1523,6 +1524,7 @@ public final class ActivityManagerService extends ActivityManagerNative static KillHandler sKillHandler = null; CompatModeDialog mCompatModeDialog; + UnsupportedDisplaySizeDialog mUnsupportedDisplaySizeDialog; long mLastMemUsageReportTime = 0; /** @@ -1693,6 +1695,22 @@ public final class ActivityManagerService extends ActivityManagerNative } break; } + case SHOW_UNSUPPORTED_DISPLAY_SIZE_DIALOG_MSG: { + synchronized (ActivityManagerService.this) { + final ActivityRecord ar = (ActivityRecord) msg.obj; + if (mUnsupportedDisplaySizeDialog != null) { + mUnsupportedDisplaySizeDialog.dismiss(); + mUnsupportedDisplaySizeDialog = null; + } + if (ar != null && mCompatModePackages.getPackageNotifyUnsupportedZoomLocked( + ar.packageName)) { + mUnsupportedDisplaySizeDialog = new UnsupportedDisplaySizeDialog( + ActivityManagerService.this, mContext, ar.info.applicationInfo); + mUnsupportedDisplaySizeDialog.show(); + } + } + break; + } case START_USER_SWITCH_UI_MSG: { mUserController.showUserSwitchDialog((Pair<UserInfo, UserInfo>) msg.obj); break; @@ -3099,6 +3117,16 @@ public final class ActivityManagerService extends ActivityManagerNative mUiHandler.sendMessage(msg); } + final void showUnsupportedZoomDialogIfNeededLocked(ActivityRecord r) { + if (mConfiguration.densityDpi != DisplayMetrics.DENSITY_DEVICE_STABLE + && r.appInfo.requiresSmallestWidthDp > mConfiguration.smallestScreenWidthDp) { + final Message msg = Message.obtain(); + msg.what = SHOW_UNSUPPORTED_DISPLAY_SIZE_DIALOG_MSG; + msg.obj = r; + mUiHandler.sendMessage(msg); + } + } + private int updateLruProcessInternalLocked(ProcessRecord app, long now, int index, String what, Object obj, ProcessRecord srcApp) { app.lastActivityTime = now; @@ -17763,6 +17791,14 @@ public final class ActivityManagerService extends ActivityManagerNative removeUriPermissionsForPackageLocked(ssp, userId, true); removeTasksByPackageNameLocked(ssp, userId); + + // Hide the "unsupported display" dialog if necessary. + if (mUnsupportedDisplaySizeDialog != null && ssp.equals( + mUnsupportedDisplaySizeDialog.getPackageName())) { + mUnsupportedDisplaySizeDialog.dismiss(); + mUnsupportedDisplaySizeDialog = null; + } + mCompatModePackages.handlePackageUninstalledLocked(ssp); mBatteryStatsService.notePackageUninstalled(ssp); } } else { @@ -17834,6 +17870,21 @@ public final class ActivityManagerService extends ActivityManagerNative } break; } + case Intent.ACTION_PACKAGE_DATA_CLEARED: + { + Uri data = intent.getData(); + String ssp; + if (data != null && (ssp = data.getSchemeSpecificPart()) != null) { + // Hide the "unsupported display" dialog if necessary. + if (mUnsupportedDisplaySizeDialog != null && ssp.equals( + mUnsupportedDisplaySizeDialog.getPackageName())) { + mUnsupportedDisplaySizeDialog.dismiss(); + mUnsupportedDisplaySizeDialog = null; + } + mCompatModePackages.handlePackageDataClearedLocked(ssp); + } + break; + } case Intent.ACTION_TIMEZONE_CHANGED: // If this is the time zone changed action, queue up a message that will reset // the timezone of all currently running processes. This message will get @@ -18656,6 +18707,9 @@ public final class ActivityManagerService extends ActivityManagerNative final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0; if (isDensityChange) { + // Reset the unsupported display size dialog. + mUiHandler.sendEmptyMessage(SHOW_UNSUPPORTED_DISPLAY_SIZE_DIALOG_MSG); + killAllBackgroundProcessesExcept(Build.VERSION_CODES.N, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE); } diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 0513b1ad8a8a..a5fb41741522 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -2481,6 +2481,7 @@ final class ActivityStack { System.identityHashCode(next), next.task.taskId, next.shortComponentName); next.sleeping = false; + mService.showUnsupportedZoomDialogIfNeededLocked(next); mService.showAskCompatModeDialogLocked(next); next.app.pendingUiClean = true; next.app.forceProcessStateUpTo(mService.mTopProcessState); diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 7a43d53d7021..15f0a903a2c8 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -1217,6 +1217,7 @@ public final class ActivityStackSupervisor implements DisplayListener { PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY); r.sleeping = false; r.forceNewConfig = false; + mService.showUnsupportedZoomDialogIfNeededLocked(r); mService.showAskCompatModeDialogLocked(r); r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo); ProfilerInfo profilerInfo = null; diff --git a/services/core/java/com/android/server/am/CompatModePackages.java b/services/core/java/com/android/server/am/CompatModePackages.java index 26264e5da147..a54df4bf069d 100644 --- a/services/core/java/com/android/server/am/CompatModePackages.java +++ b/services/core/java/com/android/server/am/CompatModePackages.java @@ -57,6 +57,8 @@ public final class CompatModePackages { public static final int COMPAT_FLAG_DONT_ASK = 1<<0; // Compatibility state: compatibility mode is enabled. public static final int COMPAT_FLAG_ENABLED = 1<<1; + // Unsupported zoom state: don't warn the user about unsupported zoom mode. + public static final int UNSUPPORTED_ZOOM_FLAG_DONT_NOTIFY = 1<<2; private final HashMap<String, Integer> mPackages = new HashMap<String, Integer>(); @@ -147,6 +149,24 @@ public final class CompatModePackages { return flags != null ? flags : 0; } + public void handlePackageDataClearedLocked(String packageName) { + // User has explicitly asked to clear all associated data. + removePackage(packageName); + } + + public void handlePackageUninstalledLocked(String packageName) { + // Clear settings when app is uninstalled since this is an explicit + // signal from the user to remove the app and all associated data. + removePackage(packageName); + } + + private void removePackage(String packageName) { + if (mPackages.containsKey(packageName)) { + mPackages.remove(packageName); + scheduleWrite(); + } + } + public void handlePackageAddedLocked(String packageName, boolean updated) { ApplicationInfo ai = null; try { @@ -165,13 +185,17 @@ public final class CompatModePackages { // any current settings for it. if (!mayCompat && mPackages.containsKey(packageName)) { mPackages.remove(packageName); - mHandler.removeMessages(MSG_WRITE); - Message msg = mHandler.obtainMessage(MSG_WRITE); - mHandler.sendMessageDelayed(msg, 10000); + scheduleWrite(); } } } + private void scheduleWrite() { + mHandler.removeMessages(MSG_WRITE); + Message msg = mHandler.obtainMessage(MSG_WRITE); + mHandler.sendMessageDelayed(msg, 10000); + } + public CompatibilityInfo compatibilityInfoForPackageLocked(ApplicationInfo ai) { CompatibilityInfo ci = new CompatibilityInfo(ai, mService.mConfiguration.screenLayout, mService.mConfiguration.smallestScreenWidthDp, @@ -207,6 +231,10 @@ public final class CompatModePackages { return (getPackageFlags(packageName)&COMPAT_FLAG_DONT_ASK) == 0; } + public boolean getPackageNotifyUnsupportedZoomLocked(String packageName) { + return (getPackageFlags(packageName)&UNSUPPORTED_ZOOM_FLAG_DONT_NOTIFY) == 0; + } + public void setFrontActivityAskCompatModeLocked(boolean ask) { ActivityRecord r = mService.getFocusedStack().topRunningActivityLocked(); if (r != null) { @@ -223,9 +251,21 @@ public final class CompatModePackages { } else { mPackages.remove(packageName); } - mHandler.removeMessages(MSG_WRITE); - Message msg = mHandler.obtainMessage(MSG_WRITE); - mHandler.sendMessageDelayed(msg, 10000); + scheduleWrite(); + } + } + + public void setPackageNotifyUnsupportedZoomLocked(String packageName, boolean notify) { + final int curFlags = getPackageFlags(packageName); + final int newFlags = notify ? (curFlags&~UNSUPPORTED_ZOOM_FLAG_DONT_NOTIFY) : + (curFlags|UNSUPPORTED_ZOOM_FLAG_DONT_NOTIFY); + if (curFlags != newFlags) { + if (newFlags != 0) { + mPackages.put(packageName, newFlags); + } else { + mPackages.remove(packageName); + } + scheduleWrite(); } } @@ -321,9 +361,7 @@ public final class CompatModePackages { // Need to get compatibility info in new state. ci = compatibilityInfoForPackageLocked(ai); - mHandler.removeMessages(MSG_WRITE); - Message msg = mHandler.obtainMessage(MSG_WRITE); - mHandler.sendMessageDelayed(msg, 10000); + scheduleWrite(); final ActivityStack stack = mService.getFocusedStack(); ActivityRecord starting = stack.restartPackage(packageName); diff --git a/services/core/java/com/android/server/am/UnsupportedDisplaySizeDialog.java b/services/core/java/com/android/server/am/UnsupportedDisplaySizeDialog.java new file mode 100644 index 000000000000..501cd6bbba6d --- /dev/null +++ b/services/core/java/com/android/server/am/UnsupportedDisplaySizeDialog.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2011 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 com.android.internal.R; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.view.Window; +import android.view.WindowManager; +import android.widget.CheckBox; + +public class UnsupportedDisplaySizeDialog { + private final AlertDialog mDialog; + private final String mPackageName; + + public UnsupportedDisplaySizeDialog(final ActivityManagerService service, 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.unsupported_display_size_message, label); + + mDialog = new AlertDialog.Builder(context) + .setPositiveButton(R.string.ok, null) + .setMessage(message) + .setView(R.layout.unsupported_display_size_dialog_content) + .create(); + + // Ensure the content view is prepared. + 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("UnsupportedDisplaySizeDialog"); + + final CheckBox alwaysShow = (CheckBox) mDialog.findViewById(R.id.ask_checkbox); + alwaysShow.setChecked(true); + alwaysShow.setOnCheckedChangeListener((buttonView, isChecked) -> { + synchronized (service) { + service.mCompatModePackages.setPackageNotifyUnsupportedZoomLocked( + mPackageName, isChecked); + } + }); + } + + public String getPackageName() { + return mPackageName; + } + + public void show() { + mDialog.show(); + } + + public void dismiss() { + mDialog.dismiss(); + } +} |