Merge "Refactor statsd_testdrive to support recording N atoms at the same time."
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 791f3da..78fe002 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -2496,7 +2496,7 @@
* @param packageName The package performing the operation.
* @param result The result of the note.
*/
- void onOpNoted(String code, int uid, String packageName, int result);
+ void onOpNoted(int code, int uid, String packageName, int result);
}
/**
@@ -2953,7 +2953,7 @@
* @hide
*/
@RequiresPermission(value=Manifest.permission.WATCH_APPOPS, conditional=true)
- public void startWatchingNoted(@NonNull String[] ops, @NonNull OnOpNotedListener callback) {
+ public void startWatchingNoted(@NonNull int[] ops, @NonNull OnOpNotedListener callback) {
IAppOpsNotedCallback cb;
synchronized (mNotedWatchers) {
cb = mNotedWatchers.get(callback);
@@ -2963,17 +2963,13 @@
cb = new IAppOpsNotedCallback.Stub() {
@Override
public void opNoted(int op, int uid, String packageName, int mode) {
- callback.onOpNoted(sOpToString[op], uid, packageName, mode);
+ callback.onOpNoted(op, uid, packageName, mode);
}
};
mNotedWatchers.put(callback, cb);
}
try {
- final int[] opCodes = new int[ops.length];
- for (int i = 0; i < opCodes.length; i++) {
- opCodes[i] = strOpToOp(ops[i]);
- }
- mService.startWatchingNoted(opCodes, cb);
+ mService.startWatchingNoted(ops, cb);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2983,7 +2979,7 @@
* Stop watching for noted app ops. An app op may be immediate or long running.
* Unregistering a non-registered callback has no effect.
*
- * @see #startWatchingNoted(String[], OnOpNotedListener)
+ * @see #startWatchingNoted(int[], OnOpNotedListener)
* @see #noteOp(String, int, String)
*
* @hide
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index 8a0d916..f3810bd 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -257,8 +257,7 @@
return sDriverMap.get(OpenGlDriverChoice.DEFAULT);
}
// Make sure we have good settings to use
- if (globalSettingsDriverPkgs.isEmpty() || globalSettingsDriverValues.isEmpty()
- || (globalSettingsDriverPkgs.size() != globalSettingsDriverValues.size())) {
+ if (globalSettingsDriverPkgs.size() != globalSettingsDriverValues.size()) {
Log.w(TAG,
"Global.Settings values are invalid: "
+ "globalSettingsDriverPkgs.size = "
@@ -299,9 +298,120 @@
}
/**
+ * Attempt to setup ANGLE with a temporary rules file.
+ * True: Temporary rules file was loaded.
+ * False: Temporary rules file was *not* loaded.
+ */
+ private boolean setupAngleWithTempRulesFile(Context context,
+ String packageName,
+ String paths,
+ String devOptIn) {
+ // Check for temporary rules if debuggable or root
+ if (!isDebuggable(context) && !(getCanLoadSystemLibraries() == 1)) {
+ Log.v(TAG, "Skipping loading temporary rules file");
+ return false;
+ }
+
+ String angleTempRules = SystemProperties.get(ANGLE_TEMP_RULES);
+
+ if ((angleTempRules == null) || angleTempRules.isEmpty()) {
+ Log.v(TAG, "System property '" + ANGLE_TEMP_RULES + "' is not set or is empty");
+ return false;
+ }
+
+ Log.i(TAG, "Detected system property " + ANGLE_TEMP_RULES + ": " + angleTempRules);
+
+ File tempRulesFile = new File(angleTempRules);
+ if (tempRulesFile.exists()) {
+ Log.i(TAG, angleTempRules + " exists, loading file.");
+ try {
+ FileInputStream stream = new FileInputStream(angleTempRules);
+
+ try {
+ FileDescriptor rulesFd = stream.getFD();
+ long rulesOffset = 0;
+ long rulesLength = stream.getChannel().size();
+ Log.i(TAG, "Loaded temporary ANGLE rules from " + angleTempRules);
+
+ setAngleInfo(paths, packageName, devOptIn, rulesFd, rulesOffset, rulesLength);
+
+ stream.close();
+
+ // We successfully setup ANGLE, so return with good status
+ return true;
+ } catch (IOException e) {
+ Log.w(TAG, "Hit IOException thrown by FileInputStream: " + e);
+ }
+ } catch (FileNotFoundException e) {
+ Log.w(TAG, "Temp ANGLE rules file not found: " + e);
+ } catch (SecurityException e) {
+ Log.w(TAG, "Temp ANGLE rules file not accessible: " + e);
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Attempt to setup ANGLE with a (temporary) default rules file: b/121153494
+ * True: Rules file was loaded.
+ * False: Rules file was *not* loaded.
+ */
+ private boolean setupAngleRulesDebug(String packageName, String paths, String devOptIn) {
+ // b/121153494
+ // Skip APK rules file checking.
+ if (!DEBUG) {
+ Log.v(TAG, "Skipping loading the rules file.");
+ // Fill in some default values for now, so the loader can get an answer when it asks.
+ // Most importantly, we need to indicate which app we are init'ing and what the
+ // developer options for it are so we can turn on ANGLE if needed.
+ setAngleInfo(paths, packageName, devOptIn, null, 0, 0);
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Attempt to setup ANGLE with a rules file loaded from the ANGLE APK.
+ * True: APK rules file was loaded.
+ * False: APK rules file was *not* loaded.
+ */
+ private boolean setupAngleRulesApk(String anglePkgName,
+ ApplicationInfo angleInfo,
+ Context context,
+ String packageName,
+ String paths,
+ String devOptIn) {
+ // Pass the rules file to loader for ANGLE decisions
+ try {
+ AssetManager angleAssets =
+ context.getPackageManager().getResourcesForApplication(angleInfo).getAssets();
+
+ try {
+ AssetFileDescriptor assetsFd = angleAssets.openFd(ANGLE_RULES_FILE);
+
+ setAngleInfo(paths, packageName, devOptIn, assetsFd.getFileDescriptor(),
+ assetsFd.getStartOffset(), assetsFd.getLength());
+
+ assetsFd.close();
+
+ return true;
+ } catch (IOException e) {
+ Log.w(TAG, "Failed to get AssetFileDescriptor for " + ANGLE_RULES_FILE
+ + " from '" + anglePkgName + "': " + e);
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "Failed to get AssetManager for '" + anglePkgName + "': " + e);
+ }
+
+ return false;
+ }
+
+ /**
* Pass ANGLE details down to trigger enable logic
*/
- private void setupAngle(Context context, Bundle bundle, String packageName) {
+ public void setupAngle(Context context, Bundle bundle, String packageName) {
String devOptIn = getDriverForPkg(bundle, packageName);
if (DEBUG) {
@@ -327,86 +437,29 @@
String abi = chooseAbi(angleInfo);
// Build a path that includes installed native libs and APK
- StringBuilder sb = new StringBuilder();
- sb.append(angleInfo.nativeLibraryDir)
- .append(File.pathSeparator)
- .append(angleInfo.sourceDir)
- .append("!/lib/")
- .append(abi);
- String paths = sb.toString();
+ String paths = angleInfo.nativeLibraryDir
+ + File.pathSeparator
+ + angleInfo.sourceDir
+ + "!/lib/"
+ + abi;
if (DEBUG) Log.v(TAG, "ANGLE package libs: " + paths);
- // Look up rules file to pass to ANGLE
- FileDescriptor rulesFd = null;
- long rulesOffset = 0;
- long rulesLength = 0;
-
- // Check for temporary rules if debuggable or root
- if (isDebuggable(context) || (getCanLoadSystemLibraries() == 1)) {
- String angleTempRules = SystemProperties.get(ANGLE_TEMP_RULES);
- if (angleTempRules != null && !angleTempRules.isEmpty()) {
- Log.i(TAG, "Detected system property " + ANGLE_TEMP_RULES + ": " + angleTempRules);
- File tempRulesFile = new File(angleTempRules);
- if (tempRulesFile.exists()) {
- Log.i(TAG, angleTempRules + " exists, loading file.");
- FileInputStream stream = null;
- try {
- stream = new FileInputStream(angleTempRules);
- } catch (FileNotFoundException e) {
- Log.w(TAG, "Unable to create stream for temp ANGLE rules");
- }
-
- if (stream != null) {
- try {
- rulesFd = stream.getFD();
- rulesOffset = 0;
- rulesLength = stream.getChannel().size();
- Log.i(TAG, "Loaded temporary ANGLE rules from " + angleTempRules);
- } catch (IOException e) {
- Log.w(TAG, "Failed to get input stream for " + angleTempRules);
- }
- }
- }
- }
+ if (setupAngleWithTempRulesFile(context, packageName, paths, devOptIn)) {
+ // We setup ANGLE with a temp rules file, so we're done here.
+ return;
}
- // If no temp rules, load the real ones from the APK
- if (DEBUG && (rulesFd == null)) {
-
- // Pass the rules file to loader for ANGLE decisions
- AssetManager angleAssets = null;
- try {
- angleAssets =
- context.getPackageManager().getResourcesForApplication(angleInfo).getAssets();
- } catch (PackageManager.NameNotFoundException e) {
- Log.w(TAG, "Failed to get AssetManager for '" + anglePkgName + "'");
- return;
- }
-
- AssetFileDescriptor assetsFd = null;
- try {
- assetsFd = angleAssets.openFd(ANGLE_RULES_FILE);
- } catch (IOException e) {
- Log.w(TAG, "Failed to get AssetFileDescriptor for " + ANGLE_RULES_FILE + " from "
- + "'" + anglePkgName + "'");
- return;
- }
-
- if (assetsFd != null) {
- rulesFd = assetsFd.getFileDescriptor();
- rulesOffset = assetsFd.getStartOffset();
- rulesLength = assetsFd.getLength();
- } else {
- Log.w(TAG, "Failed to get file descriptor for " + ANGLE_RULES_FILE);
- return;
- }
+ // b/121153494
+ if (setupAngleRulesDebug(packageName, paths, devOptIn)) {
+ // We setup ANGLE with defaults, so we're done here.
+ return;
}
- // Further opt-in logic is handled in native, so pass relevant info down
- // TODO: Move the ANGLE selection logic earlier so we don't need to keep these
- // file descriptors open.
- setAngleInfo(paths, packageName, devOptIn, rulesFd, rulesOffset, rulesLength);
+ if (setupAngleRulesApk(anglePkgName, angleInfo, context, packageName, paths, devOptIn)) {
+ // We setup ANGLE with rules from the APK, so we're done here.
+ return;
+ }
}
/**
diff --git a/core/java/com/android/internal/app/ColorDisplayController.java b/core/java/com/android/internal/app/ColorDisplayController.java
index 213bb75..c093fe5 100644
--- a/core/java/com/android/internal/app/ColorDisplayController.java
+++ b/core/java/com/android/internal/app/ColorDisplayController.java
@@ -37,12 +37,8 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.time.DateTimeException;
-import java.time.Instant;
import java.time.LocalDateTime;
import java.time.LocalTime;
-import java.time.ZoneId;
-import java.time.format.DateTimeParseException;
/**
* Controller for managing night display and color mode settings.
@@ -152,28 +148,6 @@
}
/**
- * Returns the time when Night display's activation state last changed, or {@code null} if it
- * has never been changed.
- */
- public LocalDateTime getLastActivatedTime() {
- final ContentResolver cr = mContext.getContentResolver();
- final String lastActivatedTime = Secure.getStringForUser(
- cr, Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, mUserId);
- if (lastActivatedTime != null) {
- try {
- return LocalDateTime.parse(lastActivatedTime);
- } catch (DateTimeParseException ignored) {}
- // Uses the old epoch time.
- try {
- return LocalDateTime.ofInstant(
- Instant.ofEpochMilli(Long.parseLong(lastActivatedTime)),
- ZoneId.systemDefault());
- } catch (DateTimeException|NumberFormatException ignored) {}
- }
- return null;
- }
-
- /**
* Returns the current auto mode value controlling when Night display will be automatically
* activated. One of {@link #AUTO_MODE_DISABLED}, {@link #AUTO_MODE_CUSTOM}, or
* {@link #AUTO_MODE_TWILIGHT}.
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index 9bd5994..b531325 100644
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -17,6 +17,7 @@
package com.android.internal.location;
import java.io.UnsupportedEncodingException;
+import java.util.concurrent.TimeUnit;
import android.app.Notification;
import android.app.NotificationManager;
@@ -27,19 +28,17 @@
import android.content.IntentFilter;
import android.location.LocationManager;
import android.location.INetInitiatedListener;
+import android.os.SystemClock;
import android.telephony.TelephonyManager;
import android.telephony.PhoneNumberUtils;
import android.telephony.PhoneStateListener;
-import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
-import android.os.SystemProperties;
import android.util.Log;
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.R;
import com.android.internal.telephony.GsmAlphabet;
-import com.android.internal.telephony.TelephonyProperties;
/**
* A GPS Network-initiated Handler class used by LocationManager.
@@ -50,8 +49,7 @@
private static final String TAG = "GpsNetInitiatedHandler";
- private static final boolean DEBUG = true;
- private static final boolean VERBOSE = false;
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
// NI verify activity for bringing up UI (not used yet)
public static final String ACTION_NI_VERIFY = "android.intent.action.NETWORK_INITIATED_VERIFY";
@@ -94,6 +92,9 @@
public static final int GPS_ENC_SUPL_UCS2 = 3;
public static final int GPS_ENC_UNKNOWN = -1;
+ // Limit on SUPL NI emergency mode time extension after emergency sessions ends
+ private static final int MAX_EMERGENCY_MODE_EXTENSION_SECONDS = 300; // 5 minute maximum
+
private final Context mContext;
private final TelephonyManager mTelephonyManager;
private final PhoneStateListener mPhoneStateListener;
@@ -109,7 +110,7 @@
private volatile boolean mIsSuplEsEnabled;
// Set to true if the phone is having emergency call.
- private volatile boolean mIsInEmergency;
+ private volatile boolean mIsInEmergencyCall;
// If Location function is enabled.
private volatile boolean mIsLocationEnabled = false;
@@ -119,6 +120,10 @@
// Set to true if string from HAL is encoded as Hex, e.g., "3F0039"
static private boolean mIsHexInput = true;
+ // End time of emergency call, and extension, if set
+ private long mCallEndElapsedRealtimeMillis = 0;
+ private long mEmergencyExtensionMillis = 0;
+
public static class GpsNiNotification
{
public int notificationId;
@@ -146,16 +151,12 @@
if (action.equals(Intent.ACTION_NEW_OUTGOING_CALL)) {
String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
/*
- Emergency Mode is when during emergency call or in emergency call back mode.
- For checking if it is during emergency call:
- mIsInEmergency records if the phone is in emergency call or not. It will
+ Tracks the emergency call:
+ mIsInEmergencyCall records if the phone is in emergency call or not. It will
be set to true when the phone is having emergency call, and then will
be set to false by mPhoneStateListener when the emergency call ends.
- For checking if it is in emergency call back mode:
- Emergency call back mode will be checked by reading system properties
- when necessary: SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE)
*/
- setInEmergency(PhoneNumberUtils.isEmergencyNumber(phoneNumber));
+ mIsInEmergencyCall = PhoneNumberUtils.isEmergencyNumber(phoneNumber);
if (DEBUG) Log.v(TAG, "ACTION_NEW_OUTGOING_CALL - " + getInEmergency());
} else if (action.equals(LocationManager.MODE_CHANGED_ACTION)) {
updateLocationMode();
@@ -195,7 +196,10 @@
if (DEBUG) Log.d(TAG, "onCallStateChanged(): state is "+ state);
// listening for emergency call ends
if (state == TelephonyManager.CALL_STATE_IDLE) {
- setInEmergency(false);
+ if (mIsInEmergencyCall) {
+ mCallEndElapsedRealtimeMillis = SystemClock.elapsedRealtime();
+ mIsInEmergencyCall = false;
+ }
}
}
};
@@ -229,22 +233,35 @@
return mIsLocationEnabled;
}
- // Note: Currently, there are two mechanisms involved to determine if a
- // phone is in emergency mode:
- // 1. If the user is making an emergency call, this is provided by activly
- // monitoring the outgoing phone number;
- // 2. If the device is in a emergency callback state, this is provided by
- // system properties.
- // If either one of above exists, the phone is considered in an emergency
- // mode. Because of this complexity, we need to be careful about how to set
- // and clear the emergency state.
- public void setInEmergency(boolean isInEmergency) {
- mIsInEmergency = isInEmergency;
+ /**
+ * Determines whether device is in user-initiated emergency session based on the following
+ * 1. If the user is making an emergency call, this is provided by actively
+ * monitoring the outgoing phone number;
+ * 2. If the user has recently ended an emergency call, and the device is in a configured time
+ * window after the end of that call.
+ * 3. If the device is in a emergency callback state, this is provided by querying
+ * TelephonyManager.
+ * @return true if is considered in user initiated emergency mode for NI purposes
+ */
+ public boolean getInEmergency() {
+ boolean isInEmergencyExtension =
+ (SystemClock.elapsedRealtime() - mCallEndElapsedRealtimeMillis) <
+ mEmergencyExtensionMillis;
+ boolean isInEmergencyCallback = mTelephonyManager.getEmergencyCallbackMode();
+ return mIsInEmergencyCall || isInEmergencyCallback || isInEmergencyExtension;
}
- public boolean getInEmergency() {
- boolean isInEmergencyCallback = mTelephonyManager.getEmergencyCallbackMode();
- return mIsInEmergency || isInEmergencyCallback;
+ public void setEmergencyExtensionSeconds(int emergencyExtensionSeconds) {
+ if (emergencyExtensionSeconds > MAX_EMERGENCY_MODE_EXTENSION_SECONDS) {
+ Log.w(TAG, "emergencyExtensionSeconds " + emergencyExtensionSeconds
+ + " too high, reset to " + MAX_EMERGENCY_MODE_EXTENSION_SECONDS);
+ emergencyExtensionSeconds = MAX_EMERGENCY_MODE_EXTENSION_SECONDS;
+ } else if (emergencyExtensionSeconds < 0) {
+ Log.w(TAG, "emergencyExtensionSeconds " + emergencyExtensionSeconds
+ + " is negative, reset to zero.");
+ emergencyExtensionSeconds = 0;
+ }
+ mEmergencyExtensionMillis = TimeUnit.SECONDS.toMillis(emergencyExtensionSeconds);
}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java
index 6135aeb..ac69043 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java
@@ -36,6 +36,13 @@
View getView();
/**
+ * Get clock view for a large clock that appears behind NSSL.
+ */
+ default View getBigClockView() {
+ return null;
+ }
+
+ /**
* Set clock paint style.
* @param style The new style to set in the paint.
*/
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 2674f07c..75c0ec3 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -25,6 +25,12 @@
android:layout_height="match_parent"
android:background="@android:color/transparent" >
+ <FrameLayout
+ android:id="@+id/big_clock_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="gone" />
+
<include
layout="@layout/keyguard_status_view"
android:visibility="gone" />
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index 22a23a8..570d351 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -35,7 +35,11 @@
/**
* Frame for default and custom clock.
*/
- private FrameLayout mClockFrame;
+ private FrameLayout mSmallClockFrame;
+ /**
+ * Container for big custom clock.
+ */
+ private ViewGroup mBigClockContainer;
/**
* Status area (date and other stuff) shown below the clock. Plugin can decide whether
* or not to show it below the alternate clock.
@@ -46,22 +50,27 @@
new PluginListener<ClockPlugin>() {
@Override
public void onPluginConnected(ClockPlugin plugin, Context pluginContext) {
- View view = plugin.getView();
- if (view != null) {
- disconnectPlugin();
+ disconnectPlugin();
+ View smallClockView = plugin.getView();
+ if (smallClockView != null) {
// For now, assume that the most recently connected plugin is the
// selected clock face. In the future, the user should be able to
// pick a clock face from the available plugins.
- mClockPlugin = plugin;
- mClockFrame.addView(view, -1,
+ mSmallClockFrame.addView(smallClockView, -1,
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
initPluginParams();
mClockView.setVisibility(View.GONE);
- if (!plugin.shouldShowStatusArea()) {
- mKeyguardStatusArea.setVisibility(View.GONE);
- }
}
+ View bigClockView = plugin.getBigClockView();
+ if (bigClockView != null && mBigClockContainer != null) {
+ mBigClockContainer.addView(bigClockView);
+ mBigClockContainer.setVisibility(View.VISIBLE);
+ }
+ if (!plugin.shouldShowStatusArea()) {
+ mKeyguardStatusArea.setVisibility(View.GONE);
+ }
+ mClockPlugin = plugin;
}
@Override
@@ -86,7 +95,7 @@
protected void onFinishInflate() {
super.onFinishInflate();
mClockView = findViewById(R.id.default_clock_view);
- mClockFrame = findViewById(R.id.clock_view);
+ mSmallClockFrame = findViewById(R.id.clock_view);
mKeyguardStatusArea = findViewById(R.id.keyguard_status_area);
}
@@ -104,6 +113,20 @@
}
/**
+ * Set container for big clock face appearing behind NSSL and KeyguardStatusView.
+ */
+ public void setBigClockContainer(ViewGroup container) {
+ if (mClockPlugin != null && container != null) {
+ View bigClockView = mClockPlugin.getBigClockView();
+ if (bigClockView != null) {
+ container.addView(bigClockView);
+ container.setVisibility(View.VISIBLE);
+ }
+ }
+ mBigClockContainer = container;
+ }
+
+ /**
* It will also update plugin setStyle if plugin is connected.
*/
public void setStyle(Style style) {
@@ -199,9 +222,13 @@
private void disconnectPlugin() {
if (mClockPlugin != null) {
- View view = mClockPlugin.getView();
- if (view != null) {
- mClockFrame.removeView(view);
+ View smallClockView = mClockPlugin.getView();
+ if (smallClockView != null) {
+ mSmallClockFrame.removeView(smallClockView);
+ }
+ if (mBigClockContainer != null) {
+ mBigClockContainer.removeAllViews();
+ mBigClockContainer.setVisibility(View.GONE);
}
mClockPlugin = null;
}
diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
index 52d1260..af6ee1f 100644
--- a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
@@ -57,21 +57,13 @@
@GuardedBy("mNotedItems")
private final List<AppOpItem> mNotedItems = new ArrayList<>();
- protected static final int[] OPS;
- protected static final String[] OPS_STRING = new String[] {
- AppOpsManager.OPSTR_CAMERA,
- AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW,
- AppOpsManager.OPSTR_RECORD_AUDIO,
- AppOpsManager.OPSTR_COARSE_LOCATION,
- AppOpsManager.OPSTR_FINE_LOCATION};
-
- static {
- int numOps = OPS_STRING.length;
- OPS = new int[numOps];
- for (int i = 0; i < numOps; i++) {
- OPS[i] = AppOpsManager.strOpToOp(OPS_STRING[i]);
- }
- }
+ protected static final int[] OPS = new int[] {
+ AppOpsManager.OP_CAMERA,
+ AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
+ AppOpsManager.OP_RECORD_AUDIO,
+ AppOpsManager.OP_COARSE_LOCATION,
+ AppOpsManager.OP_FINE_LOCATION
+ };
public AppOpsControllerImpl(Context context, Looper bgLooper) {
mContext = context;
@@ -92,7 +84,7 @@
protected void setListening(boolean listening) {
if (listening) {
mAppOps.startWatchingActive(OPS, this);
- mAppOps.startWatchingNoted(OPS_STRING, this);
+ mAppOps.startWatchingNoted(OPS, this);
} else {
mAppOps.stopWatchingActive(this);
mAppOps.stopWatchingNoted(this);
@@ -254,14 +246,13 @@
}
@Override
- public void onOpNoted(String code, int uid, String packageName, int result) {
+ public void onOpNoted(int code, int uid, String packageName, int result) {
if (DEBUG) {
Log.w(TAG, "Op: " + code + " with result " + AppOpsManager.MODE_NAMES[result]);
}
if (result != AppOpsManager.MODE_ALLOWED) return;
- int op_code = AppOpsManager.strOpToOp(code);
- addNoted(op_code, uid, packageName);
- notifySuscribers(op_code, uid, packageName, true);
+ addNoted(code, uid, packageName);
+ notifySuscribers(code, uid, packageName, true);
}
private void notifySuscribers(int code, int uid, String packageName, boolean active) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index c7e4d34..c0909e3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -53,6 +53,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.keyguard.KeyguardClockSwitch;
import com.android.keyguard.KeyguardStatusView;
import com.android.systemui.DejankUtils;
import com.android.systemui.Dependency;
@@ -133,7 +134,7 @@
public static final int FLING_COLLAPSE = 1;
/**
- * Fing until QS is completely hidden.
+ * Fling until QS is completely hidden.
*/
public static final int FLING_HIDE = 2;
@@ -359,6 +360,10 @@
mKeyguardStatusBar = findViewById(R.id.keyguard_header);
mKeyguardStatusView = findViewById(R.id.keyguard_status_view);
+ KeyguardClockSwitch keyguardClockSwitch = findViewById(R.id.keyguard_clock_container);
+ ViewGroup bigClockContainer = findViewById(R.id.big_clock_container);
+ keyguardClockSwitch.setBigClockContainer(bigClockContainer);
+
mNotificationContainerParent = findViewById(R.id.notification_container_parent);
mNotificationStackScroller = findViewById(R.id.notification_stack_scroller);
mNotificationStackScroller.setOnHeightChangedListener(this);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
index fb2ceac..4150602 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
@@ -107,6 +107,25 @@
}
@Test
+ public void onPluginConnected_showPluginBigClock() {
+ // GIVEN that the container for the big clock has visibility GONE
+ FrameLayout bigClockContainer = new FrameLayout(getContext());
+ bigClockContainer.setVisibility(GONE);
+ mKeyguardClockSwitch.setBigClockContainer(bigClockContainer);
+ // AND the plugin returns a view for the big clock
+ ClockPlugin plugin = mock(ClockPlugin.class);
+ TextClock pluginView = new TextClock(getContext());
+ when(plugin.getBigClockView()).thenReturn(pluginView);
+ PluginListener listener = mKeyguardClockSwitch.getClockPluginListener();
+ // WHEN the plugin is connected
+ listener.onPluginConnected(plugin, null);
+ // THEN the big clock container is visible and it is the parent of the
+ // big clock view.
+ assertThat(bigClockContainer.getVisibility()).isEqualTo(VISIBLE);
+ assertThat(pluginView.getParent()).isEqualTo(bigClockContainer);
+ }
+
+ @Test
public void onPluginConnected_nullView() {
ClockPlugin plugin = mock(ClockPlugin.class);
PluginListener listener = mKeyguardClockSwitch.getClockPluginListener();
@@ -146,6 +165,26 @@
}
@Test
+ public void onPluginDisconnected_hidePluginBigClock() {
+ // GIVEN that the big clock container is visible
+ FrameLayout bigClockContainer = new FrameLayout(getContext());
+ bigClockContainer.setVisibility(VISIBLE);
+ mKeyguardClockSwitch.setBigClockContainer(bigClockContainer);
+ // AND the plugin returns a view for the big clock
+ ClockPlugin plugin = mock(ClockPlugin.class);
+ TextClock pluginView = new TextClock(getContext());
+ when(plugin.getBigClockView()).thenReturn(pluginView);
+ PluginListener listener = mKeyguardClockSwitch.getClockPluginListener();
+ listener.onPluginConnected(plugin, null);
+ // WHEN the plugin is disconnected
+ listener.onPluginDisconnected(plugin);
+ // THEN the big lock container is GONE and the big clock view doesn't have
+ // a parent.
+ assertThat(bigClockContainer.getVisibility()).isEqualTo(GONE);
+ assertThat(pluginView.getParent()).isNull();
+ }
+
+ @Test
public void onPluginDisconnected_nullView() {
ClockPlugin plugin = mock(ClockPlugin.class);
PluginListener listener = mKeyguardClockSwitch.getClockPluginListener();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
index bb44548..2582946 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
@@ -86,7 +86,7 @@
mCallback);
mController.onOpActiveChanged(
AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
- mController.onOpNoted(AppOpsManager.OPSTR_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
+ mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
AppOpsManager.MODE_ALLOWED);
verify(mCallback).onActiveStateChanged(AppOpsManager.OP_RECORD_AUDIO,
TEST_UID, TEST_PACKAGE_NAME, true);
@@ -136,7 +136,7 @@
TEST_UID, TEST_PACKAGE_NAME, true);
mController.onOpActiveChanged(AppOpsManager.OP_CAMERA,
TEST_UID, TEST_PACKAGE_NAME, true);
- mController.onOpNoted(AppOpsManager.OPSTR_FINE_LOCATION,
+ mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION,
TEST_UID, TEST_PACKAGE_NAME, AppOpsManager.MODE_ALLOWED);
assertEquals(3, mController.getActiveAppOps().size());
}
@@ -147,7 +147,7 @@
TEST_UID, TEST_PACKAGE_NAME, true);
mController.onOpActiveChanged(AppOpsManager.OP_CAMERA,
TEST_UID_OTHER, TEST_PACKAGE_NAME, true);
- mController.onOpNoted(AppOpsManager.OPSTR_FINE_LOCATION,
+ mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION,
TEST_UID, TEST_PACKAGE_NAME, AppOpsManager.MODE_ALLOWED);
assertEquals(2,
mController.getActiveAppOpsForUser(UserHandle.getUserId(TEST_UID)).size());
@@ -158,7 +158,7 @@
@Test
public void opNotedScheduledForRemoval() {
mController.setBGHandler(mMockHandler);
- mController.onOpNoted(AppOpsManager.OPSTR_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
+ mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
AppOpsManager.MODE_ALLOWED);
verify(mMockHandler).scheduleRemoval(any(AppOpItem.class), anyLong());
}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 7adcaba..2a80644 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -129,6 +129,7 @@
import android.util.Xml;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;
import com.android.internal.os.AppFuseMount;
import com.android.internal.os.BackgroundThread;
@@ -1709,6 +1710,10 @@
ServiceManager.getService("package"));
mIAppOpsService = IAppOpsService.Stub.asInterface(
ServiceManager.getService(Context.APP_OPS_SERVICE));
+ try {
+ mIAppOpsService.startWatchingMode(OP_REQUEST_INSTALL_PACKAGES, null, mAppOpsCallback);
+ } catch (RemoteException e) {
+ }
mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
}
@@ -3240,6 +3245,15 @@
}
}
+ private IAppOpsCallback.Stub mAppOpsCallback = new IAppOpsCallback.Stub() {
+ @Override
+ public void opChanged(int op, int uid, String packageName) throws RemoteException {
+ if (!ENABLE_ISOLATED_STORAGE) return;
+
+ remountUidExternalStorage(uid, getMountMode(uid, packageName));
+ }
+ };
+
private static final Pattern PATTERN_TRANSLATE = Pattern.compile(
"(?i)^(/storage/[^/]+/(?:[0-9]+/)?)(.*)");
diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS
index 5208ca5..e483b26 100644
--- a/services/core/java/com/android/server/am/OWNERS
+++ b/services/core/java/com/android/server/am/OWNERS
@@ -15,7 +15,7 @@
jjaggi@google.com
racarr@google.com
chaviw@google.com
-brycelee@google.com
+vishnun@google.com
akulian@google.com
roosa@google.com
diff --git a/services/core/java/com/android/server/display/ColorDisplayService.java b/services/core/java/com/android/server/display/ColorDisplayService.java
index 521fa23..b6c82d3 100644
--- a/services/core/java/com/android/server/display/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/ColorDisplayService.java
@@ -39,26 +39,31 @@
import android.os.Looper;
import android.os.UserHandle;
import android.provider.Settings.Secure;
+import android.provider.Settings.System;
import android.util.MathUtils;
import android.util.Slog;
import android.view.animation.AnimationUtils;
import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ColorDisplayController;
+import com.android.server.DisplayThread;
import com.android.server.SystemService;
import com.android.server.twilight.TwilightListener;
import com.android.server.twilight.TwilightManager;
import com.android.server.twilight.TwilightState;
+import java.time.DateTimeException;
+import java.time.Instant;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
+import java.time.format.DateTimeParseException;
/**
* Controls the display's color transforms.
*/
-public final class ColorDisplayService extends SystemService
- implements ColorDisplayController.Callback {
+public final class ColorDisplayService extends SystemService {
private static final String TAG = "ColorDisplayService";
@@ -71,6 +76,7 @@
* The identity matrix, used if one of the given matrices is {@code null}.
*/
private static final float[] MATRIX_IDENTITY = new float[16];
+
static {
Matrix.setIdentityM(MATRIX_IDENTITY, 0);
}
@@ -90,10 +96,12 @@
private ContentObserver mUserSetupObserver;
private boolean mBootCompleted;
- private ColorDisplayController mController;
+ private ColorDisplayController mNightDisplayController;
+ private ContentObserver mContentObserver;
private ValueAnimator mColorMatrixAnimator;
- private Boolean mIsActivated;
- private AutoMode mAutoMode;
+
+ private Boolean mIsNightDisplayActivated;
+ private NightDisplayAutoMode mNightDisplayAutoMode;
public ColorDisplayService(Context context) {
super(context);
@@ -186,42 +194,102 @@
private void setUp() {
Slog.d(TAG, "setUp: currentUser=" + mCurrentUser);
- // Create a new controller for the current user and start listening for changes.
- mController = new ColorDisplayController(getContext(), mCurrentUser);
- mController.setListener(this);
+ mNightDisplayController = new ColorDisplayController(getContext(), mCurrentUser);
+
+ // Listen for external changes to any of the settings.
+ if (mContentObserver == null) {
+ mContentObserver = new ContentObserver(new Handler(DisplayThread.get().getLooper())) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ super.onChange(selfChange, uri);
+
+ final String setting = uri == null ? null : uri.getLastPathSegment();
+ if (setting != null) {
+ switch (setting) {
+ case Secure.NIGHT_DISPLAY_ACTIVATED:
+ onNightDisplayActivated(mNightDisplayController.isActivated());
+ break;
+ case Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE:
+ onNightDisplayColorTemperatureChanged(
+ mNightDisplayController.getColorTemperature());
+ break;
+ case Secure.NIGHT_DISPLAY_AUTO_MODE:
+ onNightDisplayAutoModeChanged(
+ mNightDisplayController.getAutoMode());
+ break;
+ case Secure.NIGHT_DISPLAY_CUSTOM_START_TIME:
+ onNightDisplayCustomStartTimeChanged(
+ mNightDisplayController.getCustomStartTime());
+ break;
+ case Secure.NIGHT_DISPLAY_CUSTOM_END_TIME:
+ onNightDisplayCustomEndTimeChanged(
+ mNightDisplayController.getCustomEndTime());
+ break;
+ case System.DISPLAY_COLOR_MODE:
+ onDisplayColorModeChanged(mNightDisplayController.getColorMode());
+ break;
+ case Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED:
+ case Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED:
+ onAccessibilityTransformChanged();
+ break;
+ }
+ }
+ }
+ };
+ }
+ final ContentResolver cr = getContext().getContentResolver();
+ cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_ACTIVATED),
+ false /* notifyForDescendants */, mContentObserver, mCurrentUser);
+ cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE),
+ false /* notifyForDescendants */, mContentObserver, mCurrentUser);
+ cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_AUTO_MODE),
+ false /* notifyForDescendants */, mContentObserver, mCurrentUser);
+ cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_CUSTOM_START_TIME),
+ false /* notifyForDescendants */, mContentObserver, mCurrentUser);
+ cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_CUSTOM_END_TIME),
+ false /* notifyForDescendants */, mContentObserver, mCurrentUser);
+ cr.registerContentObserver(System.getUriFor(System.DISPLAY_COLOR_MODE),
+ false /* notifyForDescendants */, mContentObserver, mCurrentUser);
+ cr.registerContentObserver(
+ Secure.getUriFor(Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED),
+ false /* notifyForDescendants */, mContentObserver, mCurrentUser);
+ cr.registerContentObserver(
+ Secure.getUriFor(Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED),
+ false /* notifyForDescendants */, mContentObserver, mCurrentUser);
// Set the color mode, if valid, and immediately apply the updated tint matrix based on the
// existing activated state. This ensures consistency of tint across the color mode change.
- onDisplayColorModeChanged(mController.getColorMode());
+ onDisplayColorModeChanged(mNightDisplayController.getColorMode());
// Reset the activated state.
- mIsActivated = null;
+ mIsNightDisplayActivated = null;
setCoefficientMatrix(getContext(), DisplayTransformManager.needsLinearColorMatrix());
// Prepare color transformation matrix.
- setMatrix(mController.getColorTemperature(), mMatrixNight);
+ setMatrix(mNightDisplayController.getColorTemperature(), mMatrixNight);
// Initialize the current auto mode.
- onAutoModeChanged(mController.getAutoMode());
+ onNightDisplayAutoModeChanged(mNightDisplayController.getAutoMode());
// Force the initialization current activated state.
- if (mIsActivated == null) {
- onActivated(mController.isActivated());
+ if (mIsNightDisplayActivated == null) {
+ onNightDisplayActivated(mNightDisplayController.isActivated());
}
}
private void tearDown() {
Slog.d(TAG, "tearDown: currentUser=" + mCurrentUser);
- if (mController != null) {
- mController.setListener(null);
- mController = null;
+ getContext().getContentResolver().unregisterContentObserver(mContentObserver);
+
+ if (mNightDisplayController != null) {
+ mNightDisplayController = null;
}
- if (mAutoMode != null) {
- mAutoMode.onStop();
- mAutoMode = null;
+ if (mNightDisplayAutoMode != null) {
+ mNightDisplayAutoMode.onStop();
+ mNightDisplayAutoMode = null;
}
if (mColorMatrixAnimator != null) {
@@ -230,67 +298,61 @@
}
}
- @Override
- public void onActivated(boolean activated) {
- if (mIsActivated == null || mIsActivated != activated) {
+ private void onNightDisplayActivated(boolean activated) {
+ if (mIsNightDisplayActivated == null || mIsNightDisplayActivated != activated) {
Slog.i(TAG, activated ? "Turning on night display" : "Turning off night display");
- mIsActivated = activated;
+ mIsNightDisplayActivated = activated;
- if (mAutoMode != null) {
- mAutoMode.onActivated(activated);
+ if (mNightDisplayAutoMode != null) {
+ mNightDisplayAutoMode.onActivated(activated);
}
applyTint(false);
}
}
- @Override
- public void onAutoModeChanged(int autoMode) {
- Slog.d(TAG, "onAutoModeChanged: autoMode=" + autoMode);
+ private void onNightDisplayAutoModeChanged(int autoMode) {
+ Slog.d(TAG, "onNightDisplayAutoModeChanged: autoMode=" + autoMode);
- if (mAutoMode != null) {
- mAutoMode.onStop();
- mAutoMode = null;
+ if (mNightDisplayAutoMode != null) {
+ mNightDisplayAutoMode.onStop();
+ mNightDisplayAutoMode = null;
}
if (autoMode == ColorDisplayController.AUTO_MODE_CUSTOM) {
- mAutoMode = new CustomAutoMode();
+ mNightDisplayAutoMode = new CustomNightDisplayAutoMode();
} else if (autoMode == ColorDisplayController.AUTO_MODE_TWILIGHT) {
- mAutoMode = new TwilightAutoMode();
+ mNightDisplayAutoMode = new TwilightNightDisplayAutoMode();
}
- if (mAutoMode != null) {
- mAutoMode.onStart();
+ if (mNightDisplayAutoMode != null) {
+ mNightDisplayAutoMode.onStart();
}
}
- @Override
- public void onCustomStartTimeChanged(LocalTime startTime) {
- Slog.d(TAG, "onCustomStartTimeChanged: startTime=" + startTime);
+ private void onNightDisplayCustomStartTimeChanged(LocalTime startTime) {
+ Slog.d(TAG, "onNightDisplayCustomStartTimeChanged: startTime=" + startTime);
- if (mAutoMode != null) {
- mAutoMode.onCustomStartTimeChanged(startTime);
+ if (mNightDisplayAutoMode != null) {
+ mNightDisplayAutoMode.onCustomStartTimeChanged(startTime);
}
}
- @Override
- public void onCustomEndTimeChanged(LocalTime endTime) {
- Slog.d(TAG, "onCustomEndTimeChanged: endTime=" + endTime);
+ private void onNightDisplayCustomEndTimeChanged(LocalTime endTime) {
+ Slog.d(TAG, "onNightDisplayCustomEndTimeChanged: endTime=" + endTime);
- if (mAutoMode != null) {
- mAutoMode.onCustomEndTimeChanged(endTime);
+ if (mNightDisplayAutoMode != null) {
+ mNightDisplayAutoMode.onCustomEndTimeChanged(endTime);
}
}
- @Override
- public void onColorTemperatureChanged(int colorTemperature) {
+ private void onNightDisplayColorTemperatureChanged(int colorTemperature) {
setMatrix(colorTemperature, mMatrixNight);
applyTint(true);
}
- @Override
- public void onDisplayColorModeChanged(int mode) {
+ private void onDisplayColorModeChanged(int mode) {
if (mode == -1) {
return;
}
@@ -301,16 +363,15 @@
}
setCoefficientMatrix(getContext(), DisplayTransformManager.needsLinearColorMatrix(mode));
- setMatrix(mController.getColorTemperature(), mMatrixNight);
+ setMatrix(mNightDisplayController.getColorTemperature(), mMatrixNight);
final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class);
- dtm.setColorMode(mode, (mIsActivated != null && mIsActivated) ? mMatrixNight
- : MATRIX_IDENTITY);
+ dtm.setColorMode(mode, (mIsNightDisplayActivated != null && mIsNightDisplayActivated)
+ ? mMatrixNight : MATRIX_IDENTITY);
}
- @Override
- public void onAccessibilityTransformChanged(boolean state) {
- onDisplayColorModeChanged(mController.getColorMode());
+ private void onAccessibilityTransformChanged() {
+ onDisplayColorModeChanged(mNightDisplayController.getColorMode());
}
/**
@@ -338,7 +399,7 @@
final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class);
final float[] from = dtm.getColorMatrix(LEVEL_COLOR_MATRIX_NIGHT_DISPLAY);
- final float[] to = mIsActivated ? mMatrixNight : MATRIX_IDENTITY;
+ final float[] to = mIsNightDisplayActivated ? mMatrixNight : MATRIX_IDENTITY;
if (immediate) {
dtm.setColorMatrix(LEVEL_COLOR_MATRIX_NIGHT_DISPLAY, to);
@@ -383,7 +444,7 @@
* Set the color transformation {@code MATRIX_NIGHT} to the given color temperature.
*
* @param colorTemperature color temperature in Kelvin
- * @param outTemp the 4x4 display transformation matrix for that color temperature
+ * @param outTemp the 4x4 display transformation matrix for that color temperature
*/
private void setMatrix(int colorTemperature, float[] outTemp) {
if (outTemp.length != 16) {
@@ -412,7 +473,8 @@
* @param compareTime the LocalDateTime to compare against
* @return the prior LocalDateTime corresponding to this local time
*/
- public static LocalDateTime getDateTimeBefore(LocalTime localTime, LocalDateTime compareTime) {
+ @VisibleForTesting
+ static LocalDateTime getDateTimeBefore(LocalTime localTime, LocalDateTime compareTime) {
final LocalDateTime ldt = LocalDateTime.of(compareTime.getYear(), compareTime.getMonth(),
compareTime.getDayOfMonth(), localTime.getHour(), localTime.getMinute());
@@ -427,7 +489,8 @@
* @param compareTime the LocalDateTime to compare against
* @return the next LocalDateTime corresponding to this local time
*/
- public static LocalDateTime getDateTimeAfter(LocalTime localTime, LocalDateTime compareTime) {
+ @VisibleForTesting
+ static LocalDateTime getDateTimeAfter(LocalTime localTime, LocalDateTime compareTime) {
final LocalDateTime ldt = LocalDateTime.of(compareTime.getYear(), compareTime.getMonth(),
compareTime.getDayOfMonth(), localTime.getHour(), localTime.getMinute());
@@ -440,13 +503,47 @@
return dtm.isDeviceColorManaged();
}
- private abstract class AutoMode implements ColorDisplayController.Callback {
+ /**
+ * Returns the last time the night display transform activation state was changed, or {@link
+ * LocalDateTime#MIN} if night display has never been activated.
+ */
+ private @NonNull LocalDateTime getNightDisplayLastActivatedTimeSetting() {
+ final ContentResolver cr = getContext().getContentResolver();
+ final String lastActivatedTime = Secure.getStringForUser(
+ cr, Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, getContext().getUserId());
+ if (lastActivatedTime != null) {
+ try {
+ return LocalDateTime.parse(lastActivatedTime);
+ } catch (DateTimeParseException ignored) {
+ }
+ // Uses the old epoch time.
+ try {
+ return LocalDateTime.ofInstant(
+ Instant.ofEpochMilli(Long.parseLong(lastActivatedTime)),
+ ZoneId.systemDefault());
+ } catch (DateTimeException | NumberFormatException ignored) {
+ }
+ }
+ return LocalDateTime.MIN;
+ }
+
+ private abstract class NightDisplayAutoMode {
+
+ public abstract void onActivated(boolean activated);
+
public abstract void onStart();
public abstract void onStop();
+
+ public void onCustomStartTimeChanged(LocalTime startTime) {
+ }
+
+ public void onCustomEndTimeChanged(LocalTime endTime) {
+ }
}
- private class CustomAutoMode extends AutoMode implements AlarmManager.OnAlarmListener {
+ private final class CustomNightDisplayAutoMode extends NightDisplayAutoMode implements
+ AlarmManager.OnAlarmListener {
private final AlarmManager mAlarmManager;
private final BroadcastReceiver mTimeChangedReceiver;
@@ -456,7 +553,7 @@
private LocalDateTime mLastActivatedTime;
- CustomAutoMode() {
+ CustomNightDisplayAutoMode() {
mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
mTimeChangedReceiver = new BroadcastReceiver() {
@Override
@@ -476,15 +573,15 @@
// Maintain the existing activated state if within the current period.
if (mLastActivatedTime.isBefore(now) && mLastActivatedTime.isAfter(start)
&& (mLastActivatedTime.isAfter(end) || now.isBefore(end))) {
- activate = mController.isActivated();
+ activate = mNightDisplayController.isActivated();
}
}
- if (mIsActivated == null || mIsActivated != activate) {
- mController.setActivated(activate);
+ if (mIsNightDisplayActivated == null || mIsNightDisplayActivated != activate) {
+ mNightDisplayController.setActivated(activate);
}
- updateNextAlarm(mIsActivated, now);
+ updateNextAlarm(mIsNightDisplayActivated, now);
}
private void updateNextAlarm(@Nullable Boolean activated, @NonNull LocalDateTime now) {
@@ -502,10 +599,10 @@
intentFilter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
getContext().registerReceiver(mTimeChangedReceiver, intentFilter);
- mStartTime = mController.getCustomStartTime();
- mEndTime = mController.getCustomEndTime();
+ mStartTime = mNightDisplayController.getCustomStartTime();
+ mEndTime = mNightDisplayController.getCustomEndTime();
- mLastActivatedTime = mController.getLastActivatedTime();
+ mLastActivatedTime = getNightDisplayLastActivatedTimeSetting();
// Force an update to initialize state.
updateActivated();
@@ -521,7 +618,7 @@
@Override
public void onActivated(boolean activated) {
- mLastActivatedTime = mController.getLastActivatedTime();
+ mLastActivatedTime = getNightDisplayLastActivatedTimeSetting();
updateNextAlarm(activated, LocalDateTime.now());
}
@@ -546,11 +643,13 @@
}
}
- private class TwilightAutoMode extends AutoMode implements TwilightListener {
+ private final class TwilightNightDisplayAutoMode extends NightDisplayAutoMode implements
+ TwilightListener {
private final TwilightManager mTwilightManager;
+ private LocalDateTime mLastActivatedTime;
- TwilightAutoMode() {
+ TwilightNightDisplayAutoMode() {
mTwilightManager = getLocalService(TwilightManager.class);
}
@@ -562,26 +661,31 @@
}
boolean activate = state.isNight();
- final LocalDateTime lastActivatedTime = mController.getLastActivatedTime();
- if (lastActivatedTime != null) {
+ if (mLastActivatedTime != null) {
final LocalDateTime now = LocalDateTime.now();
final LocalDateTime sunrise = state.sunrise();
final LocalDateTime sunset = state.sunset();
// Maintain the existing activated state if within the current period.
- if (lastActivatedTime.isBefore(now) && (lastActivatedTime.isBefore(sunrise)
- ^ lastActivatedTime.isBefore(sunset))) {
- activate = mController.isActivated();
+ if (mLastActivatedTime.isBefore(now) && (mLastActivatedTime.isBefore(sunrise)
+ ^ mLastActivatedTime.isBefore(sunset))) {
+ activate = mNightDisplayController.isActivated();
}
}
- if (mIsActivated == null || mIsActivated != activate) {
- mController.setActivated(activate);
+ if (mIsNightDisplayActivated == null || mIsNightDisplayActivated != activate) {
+ mNightDisplayController.setActivated(activate);
}
}
@Override
+ public void onActivated(boolean activated) {
+ mLastActivatedTime = getNightDisplayLastActivatedTimeSetting();
+ }
+
+ @Override
public void onStart() {
mTwilightManager.registerListener(this, mHandler);
+ mLastActivatedTime = getNightDisplayLastActivatedTimeSetting();
// Force an update to initialize state.
updateActivated(mTwilightManager.getLastTwilightState());
@@ -590,10 +694,7 @@
@Override
public void onStop() {
mTwilightManager.unregisterListener(this);
- }
-
- @Override
- public void onActivated(boolean activated) {
+ mLastActivatedTime = null;
}
@Override
@@ -624,6 +725,7 @@
}
private final class BinderService extends IColorDisplayManager.Stub {
+
@Override
public boolean isDeviceColorManaged() {
final long token = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 29e1878..0f060fe 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -642,6 +642,17 @@
Log.e(TAG, "unable to parse SUPL_ES: " + suplESProperty);
}
}
+
+ String emergencyExtensionSecondsString
+ = properties.getProperty("ES_EXTENSION_SEC", "0");
+ try {
+ int emergencyExtensionSeconds =
+ Integer.parseInt(emergencyExtensionSecondsString);
+ mNIHandler.setEmergencyExtensionSeconds(emergencyExtensionSeconds);
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "unable to parse ES_EXTENSION_SEC: "
+ + emergencyExtensionSecondsString);
+ }
}
private void loadPropertiesFromResource(Context context,
diff --git a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
index 7ae2271..3a7919a 100644
--- a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
+++ b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
@@ -120,7 +120,7 @@
android.Manifest.permission.INTERACT_ACROSS_PROFILES, callingUid,
-1, true);
if (permissionFlag != PackageManager.PERMISSION_GRANTED
- || !mInjector.getUserManager().isSameProfileGroup(callerUserId, userId)) {
+ || !isSameProfileGroup(callerUserId, userId)) {
throw new SecurityException("Attempt to launch activity without required "
+ android.Manifest.permission.INTERACT_ACROSS_PROFILES + " permission"
+ " or target user is not in the same profile group.");
@@ -209,6 +209,15 @@
}
}
+ private boolean isSameProfileGroup(@UserIdInt int callerUserId, @UserIdInt int userId) {
+ final long ident = mInjector.clearCallingIdentity();
+ try {
+ return mInjector.getUserManager().isSameProfileGroup(callerUserId, userId);
+ } finally {
+ mInjector.restoreCallingIdentity(ident);
+ }
+ }
+
/**
* Verify that the given calling package is belong to the calling UID.
*/
diff --git a/services/core/java/com/android/server/wm/OWNERS b/services/core/java/com/android/server/wm/OWNERS
index fff42c5..8dda485 100644
--- a/services/core/java/com/android/server/wm/OWNERS
+++ b/services/core/java/com/android/server/wm/OWNERS
@@ -2,6 +2,6 @@
jjaggi@google.com
racarr@google.com
chaviw@google.com
-brycelee@google.com
+vishnun@google.com
akulian@google.com
roosa@google.com
diff --git a/services/tests/servicestests/src/com/android/server/appops/AppOpsNotedWatcherTest.java b/services/tests/servicestests/src/com/android/server/appops/AppOpsNotedWatcherTest.java
index 52f434d..edd89f9 100644
--- a/services/tests/servicestests/src/com/android/server/appops/AppOpsNotedWatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/appops/AppOpsNotedWatcherTest.java
@@ -52,8 +52,8 @@
// Try to start watching noted ops
final AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
try {
- appOpsManager.startWatchingNoted(new String[]{AppOpsManager.OPSTR_FINE_LOCATION,
- AppOpsManager.OPSTR_RECORD_AUDIO}, listener);
+ appOpsManager.startWatchingNoted(new int[]{AppOpsManager.OP_FINE_LOCATION,
+ AppOpsManager.OP_RECORD_AUDIO}, listener);
fail("Watching noted ops shoudl require " + Manifest.permission.WATCH_APPOPS);
} catch (SecurityException expected) {
/*ignored*/
@@ -67,23 +67,23 @@
// Start watching noted ops
final AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
- appOpsManager.startWatchingNoted(new String[]{AppOpsManager.OPSTR_FINE_LOCATION,
- AppOpsManager.OPSTR_CAMERA}, listener);
+ appOpsManager.startWatchingNoted(new int[]{AppOpsManager.OP_FINE_LOCATION,
+ AppOpsManager.OP_CAMERA}, listener);
// Note some ops
- appOpsManager.noteOp(AppOpsManager.OPSTR_FINE_LOCATION, Process.myUid(),
+ appOpsManager.noteOp(AppOpsManager.OP_FINE_LOCATION, Process.myUid(),
getContext().getPackageName());
- appOpsManager.noteOp(AppOpsManager.OPSTR_CAMERA, Process.myUid(),
+ appOpsManager.noteOp(AppOpsManager.OP_CAMERA, Process.myUid(),
getContext().getPackageName());
// Verify that we got called for the ops being noted
final InOrder inOrder = inOrder(listener);
inOrder.verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
- .times(1)).onOpNoted(eq(AppOpsManager.OPSTR_FINE_LOCATION),
+ .times(1)).onOpNoted(eq(AppOpsManager.OP_FINE_LOCATION),
eq(Process.myUid()), eq(getContext().getPackageName()),
eq(AppOpsManager.MODE_ALLOWED));
inOrder.verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
- .times(1)).onOpNoted(eq(AppOpsManager.OPSTR_CAMERA),
+ .times(1)).onOpNoted(eq(AppOpsManager.OP_CAMERA),
eq(Process.myUid()), eq(getContext().getPackageName()),
eq(AppOpsManager.MODE_ALLOWED));
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index b61e99b..2c712a1 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2617,8 +2617,7 @@
if (availableList == null) {
return null;
} else {
- return getAvailableSubscriptionInfoList().stream()
- .filter(subInfo -> !shouldHideSubscription(subInfo))
+ return availableList.stream().filter(subInfo -> !shouldHideSubscription(subInfo))
.collect(Collectors.toList());
}
}