From 6472501f2e7ba018d8aa43c61e55874d756cecb8 Mon Sep 17 00:00:00 2001 From: Suprabh Shukla Date: Wed, 15 Jun 2016 13:19:28 -0700 Subject: [PATCH] Resetting some settings on starting a new demo session Muting ringer and media volume and turning off the flashlight before starting a new session. Also, resetting the configuration of any new demo user to the configuration of user 0 on the device. Moved RetailDemoModeService and RetailDemoModeServiceInternal to more appropriate new packages Bug: 29519612 Change-Id: Ib65f89ce61afab2d2f1b2dd0c761f5d35a466181 --- .../android/app/ActivityManagerInternal.java | 10 +++ .../app}/RetailDemoModeServiceInternal.java | 10 ++- services/Android.mk | 1 + .../server/am/ActivityManagerService.java | 11 +++ .../com/android/server/power/Notifier.java | 2 +- .../java/com/android/server/SystemServer.java | 2 +- services/retaildemo/Android.mk | 12 +++ .../retaildemo}/RetailDemoModeService.java | 86 +++++++++++++++++-- .../UserInactivityCountdownDialog.java | 4 +- 9 files changed, 128 insertions(+), 10 deletions(-) rename {services/core/java/com/android/server/am => core/java/android/app}/RetailDemoModeServiceInternal.java (74%) create mode 100644 services/retaildemo/Android.mk rename services/{core/java/com/android/server/am => retaildemo/java/com/android/server/retaildemo}/RetailDemoModeService.java (79%) rename services/{core/java/com/android/server/am => retaildemo/java/com/android/server/retaildemo}/UserInactivityCountdownDialog.java (96%) diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 3a70a4cd4b99d..33ae553fb57f3 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -19,6 +19,7 @@ package android.app; import android.annotation.NonNull; import android.content.ComponentName; import android.content.IIntentSender; +import android.content.res.Configuration; import android.os.IBinder; import android.service.voice.IVoiceInteractionSession; @@ -151,4 +152,13 @@ public abstract class ActivityManagerInternal { * such as Power Save mode. */ public abstract void setPendingIntentWhitelistDuration(IIntentSender target, long duration); + + /** + * Updates and persists the {@link Configuration} for a given user. + * + * @param values the configuration to update + * @param userId the user to update the configuration for + */ + public abstract void updatePersistentConfigurationForUser(@NonNull Configuration values, + int userId); } diff --git a/services/core/java/com/android/server/am/RetailDemoModeServiceInternal.java b/core/java/android/app/RetailDemoModeServiceInternal.java similarity index 74% rename from services/core/java/com/android/server/am/RetailDemoModeServiceInternal.java rename to core/java/android/app/RetailDemoModeServiceInternal.java index 32de03a31cb9b..7ca214aae6026 100644 --- a/services/core/java/com/android/server/am/RetailDemoModeServiceInternal.java +++ b/core/java/android/app/RetailDemoModeServiceInternal.java @@ -14,8 +14,16 @@ * limitations under the License */ -package com.android.server.am; +package android.app; +/** + * Retail Demo Mode Service interface to be used locally inside system server + * + * @hide Only for use inside system server + */ public interface RetailDemoModeServiceInternal { + /** + * Used to notify RetailDemoModeService of any user activity. + */ public void onUserActivity(); } \ No newline at end of file diff --git a/services/Android.mk b/services/Android.mk index 1918db54a0494..3385bed0ba8b9 100644 --- a/services/Android.mk +++ b/services/Android.mk @@ -28,6 +28,7 @@ services := \ net \ print \ restrictions \ + retaildemo \ usage \ usb \ voiceinteraction diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 89715f8952ba5..ae870e873f3fe 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -63,6 +63,7 @@ import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import android.Manifest; +import android.annotation.NonNull; import android.annotation.UserIdInt; import android.app.Activity; import android.app.ActivityManager; @@ -21649,6 +21650,16 @@ public final class ActivityManagerService extends ActivityManagerNative } ((PendingIntentRecord) target).setWhitelistDuration(duration); } + + @Override + public void updatePersistentConfigurationForUser(@NonNull Configuration values, + int userId) { + Preconditions.checkNotNull(values, "Configuration must not be null"); + Preconditions.checkArgumentNonnegative(userId, "userId " + userId + " not supported"); + synchronized (ActivityManagerService.this) { + updateConfigurationLocked(values, null, false, true, userId); + } + } } private final class SleepTokenImpl extends SleepToken { diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java index 3ed6ec90e8459..9ccfd67980f53 100644 --- a/services/core/java/com/android/server/power/Notifier.java +++ b/services/core/java/com/android/server/power/Notifier.java @@ -18,12 +18,12 @@ package com.android.server.power; import android.app.ActivityManagerInternal; import android.app.AppOpsManager; +import android.app.RetailDemoModeServiceInternal; import com.android.internal.app.IAppOpsService; import com.android.internal.app.IBatteryStats; import com.android.server.EventLogTags; import com.android.server.LocalServices; -import com.android.server.am.RetailDemoModeServiceInternal; import android.app.ActivityManagerNative; import android.content.BroadcastReceiver; diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 8f8ba1d192734..76424d82a2b01 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -57,7 +57,6 @@ import com.android.internal.os.ZygoteInit; import com.android.internal.widget.ILockSettings; import com.android.server.accessibility.AccessibilityManagerService; import com.android.server.am.ActivityManagerService; -import com.android.server.am.RetailDemoModeService; import com.android.server.audio.AudioService; import com.android.server.camera.CameraService; import com.android.server.clipboard.ClipboardService; @@ -88,6 +87,7 @@ import com.android.server.pm.UserManagerService; import com.android.server.power.PowerManagerService; import com.android.server.power.ShutdownThread; import com.android.server.restrictions.RestrictionsManagerService; +import com.android.server.retaildemo.RetailDemoModeService; import com.android.server.soundtrigger.SoundTriggerService; import com.android.server.statusbar.StatusBarManagerService; import com.android.server.storage.DeviceStorageMonitorService; diff --git a/services/retaildemo/Android.mk b/services/retaildemo/Android.mk new file mode 100644 index 0000000000000..670c6bfa1e6ac --- /dev/null +++ b/services/retaildemo/Android.mk @@ -0,0 +1,12 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := services.retaildemo + +LOCAL_SRC_FILES += \ + $(call all-java-files-under,java) + +LOCAL_JAVA_LIBRARIES := services.core + +include $(BUILD_STATIC_JAVA_LIBRARY) diff --git a/services/core/java/com/android/server/am/RetailDemoModeService.java b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java similarity index 79% rename from services/core/java/com/android/server/am/RetailDemoModeService.java rename to services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java index bcf1bd4cc1d29..96e6da741a822 100644 --- a/services/core/java/com/android/server/am/RetailDemoModeService.java +++ b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java @@ -14,13 +14,15 @@ * limitations under the License */ -package com.android.server.am; +package com.android.server.retaildemo; +import android.app.ActivityManagerInternal; import android.app.ActivityManagerNative; import android.app.AppGlobals; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; +import android.app.RetailDemoModeServiceInternal; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; @@ -31,7 +33,13 @@ import android.content.IntentFilter; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.pm.UserInfo; +import android.content.res.Configuration; import android.database.ContentObserver; +import android.hardware.camera2.CameraAccessException; +import android.hardware.camera2.CameraCharacteristics; +import android.hardware.camera2.CameraManager; +import android.media.AudioManager; +import android.media.AudioSystem; import android.net.Uri; import android.os.Environment; import android.os.FileUtils; @@ -48,11 +56,14 @@ import android.util.Slog; import com.android.internal.os.BackgroundThread; import com.android.internal.R; import com.android.internal.widget.LockPatternUtils; +import com.android.server.LocalServices; import com.android.server.ServiceThread; import com.android.server.SystemService; -import com.android.server.am.UserInactivityCountdownDialog.OnCountDownExpiredListener; +import com.android.server.am.ActivityManagerService; +import com.android.server.retaildemo.UserInactivityCountdownDialog.OnCountDownExpiredListener; import java.io.File; +import java.util.ArrayList; public class RetailDemoModeService extends SystemService { private static final boolean DEBUG = false; @@ -70,8 +81,16 @@ public class RetailDemoModeService extends SystemService { private static final long WARNING_DIALOG_TIMEOUT = 6000; private static final long MILLIS_PER_SECOND = 1000; + private static final int[] VOLUME_STREAMS_TO_MUTE = { + AudioSystem.STREAM_RING, + AudioSystem.STREAM_MUSIC + }; + boolean mDeviceInDemoMode = false; + int mCurrentUserId; private ActivityManagerService mAms; + private ActivityManagerInternal mAmi; + private AudioManager mAudioManager; private NotificationManager mNm; private UserManager mUm; private PowerManager mPm; @@ -79,6 +98,9 @@ public class RetailDemoModeService extends SystemService { Handler mHandler; private ServiceThread mHandlerThread; private PendingIntent mResetDemoPendingIntent; + private CameraManager mCameraManager; + private String[] mCameraIdsWithFlash; + private Configuration mPrimaryUserConfiguration; private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override @@ -121,9 +143,9 @@ public class RetailDemoModeService extends SystemService { try { enabledState = pm.getComponentEnabledSetting( ComponentName.unflattenFromString(demoLauncherComponent), - getActivityManager().getCurrentUser().id); + mCurrentUserId); } catch (RemoteException exc) { - // XXX: shouldn't happen + Slog.e(TAG, "Unable to talk to Package Manager", exc); } if (enabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) { Slog.i(TAG, "User inactivity timeout reached"); @@ -218,6 +240,13 @@ public class RetailDemoModeService extends SystemService { return mUm; } + private AudioManager getAudioManager() { + if (mAudioManager == null) { + mAudioManager = getContext().getSystemService(AudioManager.class); + } + return mAudioManager; + } + private void registerSettingsChangeObserver() { final Uri deviceDemoModeUri = Settings.Global.getUriFor(Settings.Global.DEVICE_DEMO_MODE); final Uri deviceProvisionedUri = Settings.Global.getUriFor( @@ -272,6 +301,46 @@ public class RetailDemoModeService extends SystemService { getContext().registerReceiver(mBroadcastReceiver, filter); } + private String[] getCameraIdsWithFlash() { + ArrayList cameraIdsList = new ArrayList(); + try { + for (String cameraId : mCameraManager.getCameraIdList()) { + CameraCharacteristics c = mCameraManager.getCameraCharacteristics(cameraId); + if (Boolean.TRUE.equals(c.get(CameraCharacteristics.FLASH_INFO_AVAILABLE))) { + cameraIdsList.add(cameraId); + } + } + } catch (CameraAccessException e) { + Slog.e(TAG, "Unable to access camera while getting camera id list", e); + } + return cameraIdsList.toArray(new String[cameraIdsList.size()]); + } + + private void turnOffAllFlashLights() { + for (String cameraId : mCameraIdsWithFlash) { + try { + mCameraManager.setTorchMode(cameraId, false); + } catch (CameraAccessException e) { + Slog.e(TAG, "Unable to access camera " + cameraId + " while turning off flash", e); + } + } + } + + private void muteVolumeStreams() { + for (int stream : VOLUME_STREAMS_TO_MUTE) { + getAudioManager().setStreamVolume(stream, getAudioManager().getStreamMinVolume(stream), + 0); + } + } + + private Configuration getPrimaryUsersConfiguration() { + if (mPrimaryUserConfiguration == null) { + Settings.System.getConfiguration(getContext().getContentResolver(), + mPrimaryUserConfiguration = new Configuration()); + } + return mPrimaryUserConfiguration; + } + @Override public void onStart() { if (DEBUG) { @@ -290,9 +359,12 @@ public class RetailDemoModeService extends SystemService { return; } mPm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE); + mAmi = LocalServices.getService(ActivityManagerInternal.class); mWakeLock = mPm .newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, TAG); mNm = NotificationManager.from(getContext()); + mCameraManager = (CameraManager) getContext().getSystemService(Context.CAMERA_SERVICE); + mCameraIdsWithFlash = getCameraIdsWithFlash(); if (UserManager.isDeviceInDemoMode(getContext())) { mDeviceInDemoMode = true; @@ -318,10 +390,14 @@ public class RetailDemoModeService extends SystemService { if (!mWakeLock.isHeld()) { mWakeLock.acquire(); } + mCurrentUserId = userId; mNm.notifyAsUser(TAG, 1, createResetNotification(), UserHandle.of(userId)); + turnOffAllFlashLights(); + muteVolumeStreams(); + mAmi.updatePersistentConfigurationForUser(getPrimaryUsersConfiguration(), userId); } - public RetailDemoModeServiceInternal mLocalService = new RetailDemoModeServiceInternal() { + private RetailDemoModeServiceInternal mLocalService = new RetailDemoModeServiceInternal() { private static final long USER_ACTIVITY_DEBOUNCE_TIME = 2000; private long mLastUserActivityTime = 0; diff --git a/services/core/java/com/android/server/am/UserInactivityCountdownDialog.java b/services/retaildemo/java/com/android/server/retaildemo/UserInactivityCountdownDialog.java similarity index 96% rename from services/core/java/com/android/server/am/UserInactivityCountdownDialog.java rename to services/retaildemo/java/com/android/server/retaildemo/UserInactivityCountdownDialog.java index 1a1e85c847a94..e6548b79f9a11 100644 --- a/services/core/java/com/android/server/am/UserInactivityCountdownDialog.java +++ b/services/retaildemo/java/com/android/server/retaildemo/UserInactivityCountdownDialog.java @@ -14,7 +14,7 @@ * limitations under the License */ -package com.android.server.am; +package com.android.server.retaildemo; import android.app.AlertDialog; import android.app.Dialog; @@ -35,7 +35,7 @@ public class UserInactivityCountdownDialog extends AlertDialog { private long mCountDownDuration; private long mRefreshInterval; - protected UserInactivityCountdownDialog(Context context, long duration, long refreshInterval) { + UserInactivityCountdownDialog(Context context, long duration, long refreshInterval) { super(context); mCountDownDuration = duration;