Merge "Refactoring of auto fill - lifecycle, auth, improvements"
diff --git a/api/system-current.txt b/api/system-current.txt
index a8000dc..4a16b839 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -6204,6 +6204,10 @@
method public void onDetached();
}
+ public class VrManager {
+ method public void setPersistentVrModeEnabled(boolean);
+ }
+
public final class WallpaperInfo implements android.os.Parcelable {
ctor public WallpaperInfo(android.content.Context, android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public int describeContents();
@@ -9006,6 +9010,7 @@
field public static final java.lang.String USB_SERVICE = "usb";
field public static final java.lang.String USER_SERVICE = "user";
field public static final java.lang.String VIBRATOR_SERVICE = "vibrator";
+ field public static final java.lang.String VR_SERVICE = "vrmanager";
field public static final java.lang.String WALLPAPER_SERVICE = "wallpaper";
field public static final java.lang.String WIFI_AWARE_SERVICE = "wifiaware";
field public static final java.lang.String WIFI_P2P_SERVICE = "wifip2p";
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 5a75a67..fc1d613 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -115,6 +115,7 @@
import android.service.autofill.IAutoFillManagerService;
import android.service.persistentdata.IPersistentDataBlockService;
import android.service.persistentdata.PersistentDataBlockManager;
+import android.service.vr.IVrManager;
import android.telecom.TelecomManager;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
@@ -814,6 +815,14 @@
IAutoFillManagerService service = IAutoFillManagerService.Stub.asInterface(b);
return new AutoFillManager(ctx, service);
}});
+
+ registerService(Context.VR_SERVICE, VrManager.class, new CachedServiceFetcher<VrManager>() {
+ @Override
+ public VrManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.VR_SERVICE);
+ return new VrManager(IVrManager.Stub.asInterface(b));
+ }
+ });
}
/**
diff --git a/core/java/android/app/VrManager.java b/core/java/android/app/VrManager.java
new file mode 100644
index 0000000..a0b0eea
--- /dev/null
+++ b/core/java/android/app/VrManager.java
@@ -0,0 +1,44 @@
+package android.app;
+
+
+import android.annotation.SystemApi;
+import android.content.ComponentName;
+import android.os.RemoteException;
+import android.service.vr.IVrManager;
+
+/**
+ * Used to control aspects of a devices Virtual Reality (VR) capabilities.
+ * <p>
+ * You do not instantiate this class directly; instead, retrieve it through
+ * {@link android.content.Context#getSystemService}.
+ * @hide
+ */
+@SystemApi
+public class VrManager {
+ private final IVrManager mService;
+
+ /**
+ * {@hide}
+ */
+ public VrManager(IVrManager service) {
+ mService = service;
+ }
+
+ /**
+ * Sets the persistent VR mode state of a device. When a device is in persistent VR mode it will
+ * remain in VR mode even if the foreground does not specify Vr mode being enabled. Mainly used
+ * by VR viewers to indicate that a device is placed in a VR viewer.
+ *
+ * <p>Requires {@link android.Manifest.permission#ACCESS_VR_MANAGER} permission.</p>
+ *
+ * @see Activity#setVrModeEnabled(boolean, ComponentName)
+ * @param enabled true if the device should be placed in persistent VR mode.
+ */
+ public void setPersistentVrModeEnabled(boolean enabled) {
+ try {
+ mService.setPersistentVrModeEnabled(enabled);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index f610a29..a7d5ac6 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -35,6 +35,7 @@
import android.app.IApplicationThread;
import android.app.IServiceConnection;
import android.app.Notification;
+import android.app.VrManager;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
@@ -3764,6 +3765,16 @@
public static final String OVERLAY_SERVICE = "overlay";
/**
+ * Use with {@link #getSystemService} to retrieve a
+ * {@link VrManager} for accessing the VR service.
+ *
+ * @see #getSystemService
+ * @hide
+ */
+ @SystemApi
+ public static final String VR_SERVICE = "vrmanager";
+
+ /**
* Determine whether the given permission is allowed for a particular
* process and user ID running in the system.
*
diff --git a/core/java/android/service/vr/IVrManager.aidl b/core/java/android/service/vr/IVrManager.aidl
index 62ecab3..10e4177 100644
--- a/core/java/android/service/vr/IVrManager.aidl
+++ b/core/java/android/service/vr/IVrManager.aidl
@@ -42,5 +42,13 @@
*/
boolean getVrModeState();
+ /**
+ * Sets the persistent VR mode state of a device. When a device is in persistent VR mode it will
+ * remain in VR mode even if the foreground does not specify VR mode being enabled. Mainly used
+ * by VR viewers to indicate that a device is placed in a VR viewer.
+ *
+ * @param enabled true if the device should be placed in persistent VR mode.
+ */
+ void setPersistentVrModeEnabled(in boolean enabled);
}
diff --git a/services/core/java/com/android/server/vr/VrManagerInternal.java b/services/core/java/com/android/server/vr/VrManagerInternal.java
index 0fc1900..45b7baf 100644
--- a/services/core/java/com/android/server/vr/VrManagerInternal.java
+++ b/services/core/java/com/android/server/vr/VrManagerInternal.java
@@ -79,4 +79,13 @@
* given in {@link android.service.vr.VrModeException} on failure.
*/
public abstract int hasVrPackage(@NonNull ComponentName packageName, int userId);
+
+ /**
+ * Sets the persistent VR mode state of a device. When a device is in persistent VR mode it will
+ * remain in VR mode even if the foreground does not specify Vr mode being enabled. Mainly used
+ * by VR viewers to indicate that a device is placed in a VR viewer.
+ *
+ * @param enabled true if the device should be placed in persistent VR mode.
+ */
+ public abstract void setPersistentVrModeEnabled(boolean enabled);
}
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 8368b05..51c4ce31 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -20,15 +20,10 @@
import android.app.AppOpsManager;
import android.app.NotificationManager;
import android.annotation.NonNull;
-import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
-import android.content.pm.FeatureInfo;
-import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Binder;
@@ -53,7 +48,6 @@
import android.util.SparseArray;
import com.android.internal.R;
-import com.android.server.LocalServices;
import com.android.server.SystemConfig;
import com.android.server.SystemService;
import com.android.server.utils.ManagedApplicationService.PendingEvent;
@@ -69,8 +63,6 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
-import java.util.List;
-import java.util.Map;
import java.util.Objects;
/**
@@ -121,8 +113,10 @@
// State protected by mLock
private boolean mVrModeAllowed;
private boolean mVrModeEnabled;
+ private boolean mPersistentVrModeEnabled;
private EnabledComponentsObserver mComponentObserver;
private ManagedApplicationService mCurrentVrService;
+ private ComponentName mDefaultVrService;
private Context mContext;
private ComponentName mCurrentVrModeComponent;
private int mCurrentVrModeUser;
@@ -157,6 +151,10 @@
if (mVrModeAllowed) {
consumeAndApplyPendingStateLocked();
} else {
+ // Disable persistent mode when VR mode isn't allowed, allows an escape hatch to
+ // exit persistent VR mode when screen is turned off.
+ mPersistentVrModeEnabled = false;
+
// Set pending state to current state.
mPendingState = (mVrModeEnabled && mCurrentVrService != null)
? new VrState(mVrModeEnabled, mCurrentVrService.getComponent(),
@@ -378,6 +376,12 @@
}
@Override
+ public void setPersistentVrModeEnabled(boolean enabled) {
+ enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
+ VrManagerService.this.setPersistentVrModeEnabled(enabled);
+ }
+
+ @Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
@@ -387,6 +391,8 @@
}
pw.println("********* Dump of VrManagerService *********");
pw.println("VR mode is currently: " + ((mVrModeAllowed) ? "allowed" : "disallowed"));
+ pw.println("Persistent VR mode is currently: " +
+ ((mPersistentVrModeEnabled) ? "enabled" : "disabled"));
pw.println("Previous state transitions:\n");
String tab = " ";
dumpStateTransitions(pw);
@@ -462,6 +468,11 @@
public int hasVrPackage(ComponentName packageName, int userId) {
return VrManagerService.this.hasVrPackage(packageName, userId);
}
+
+ @Override
+ public void setPersistentVrModeEnabled(boolean enabled) {
+ VrManagerService.this.setPersistentVrModeEnabled(enabled);
+ }
}
public VrManagerService(Context context) {
@@ -494,6 +505,15 @@
mComponentObserver.rebuildAll();
}
+
+ //TODO: something more robust than picking the first one
+ ArraySet<ComponentName> defaultVrComponents =
+ SystemConfig.getInstance().getDefaultVrComponents();
+ if (defaultVrComponents.size() > 0) {
+ mDefaultVrService = defaultVrComponents.valueAt(0);
+ } else {
+ Slog.i(TAG, "No default vr listener service found.");
+ }
} else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
synchronized (mLock) {
mVrModeAllowed = true;
@@ -637,8 +657,8 @@
}
}
+ mCurrentVrModeComponent = calling;
if (calling != null && !Objects.equals(calling, mCurrentVrModeComponent)) {
- mCurrentVrModeComponent = calling;
sendUpdatedCaller = true;
}
@@ -947,7 +967,25 @@
int userId, @NonNull ComponentName callingPackage) {
synchronized (mLock) {
- VrState pending = new VrState(enabled, targetPackageName, userId, callingPackage);
+ VrState pending;
+ ComponentName targetListener;
+ ComponentName foregroundVrComponent;
+
+ // If the device is in persistent VR mode, then calls to disable VR mode are ignored,
+ // and the system default VR listener is used.
+ boolean targetEnabledState = enabled || mPersistentVrModeEnabled;
+ if (!enabled && mPersistentVrModeEnabled) {
+ targetListener = mDefaultVrService;
+
+ // Current foreground component isn't a VR one (in 2D app case)
+ foregroundVrComponent = null;
+ } else {
+ targetListener = targetPackageName;
+ foregroundVrComponent = callingPackage;
+ }
+ pending = new VrState(
+ targetEnabledState, targetListener, userId, foregroundVrComponent);
+
if (!mVrModeAllowed) {
// We're not allowed to be in VR mode. Make this state pending. This will be
// applied the next time we are allowed to enter VR mode unless it is superseded by
@@ -956,7 +994,7 @@
return;
}
- if (!enabled && mCurrentVrService != null) {
+ if (!targetEnabledState && mCurrentVrService != null) {
// If we're transitioning out of VR mode, delay briefly to avoid expensive HAL calls
// and service bind/unbind in case we are immediately switching to another VR app.
if (mPendingState == null) {
@@ -971,7 +1009,19 @@
mPendingState = null;
}
- updateCurrentVrServiceLocked(enabled, targetPackageName, userId, callingPackage);
+ updateCurrentVrServiceLocked(
+ targetEnabledState, targetListener, userId, foregroundVrComponent);
+ }
+ }
+
+ private void setPersistentVrModeEnabled(boolean enabled) {
+ synchronized (mLock) {
+ mPersistentVrModeEnabled = enabled;
+
+ // Disabling persistent mode when not showing a VR should disable the overall vr mode.
+ if (!enabled && mCurrentVrModeComponent == null) {
+ setVrMode(false, null, 0, null);
+ }
}
}